Что такое RFC, зачем он нужен и как его писать #1

Дисклеймер:
Сразу предупрежу, что все мои статьи в этой серии это лишь описание моего опыта и мои знания могут быть не полными в некоторых областях или не подходить вашей ситуации.
Всем привет, это начало серии обучающих статей на разные темы, как часто и на какие темы они будут выходить я не знаю, особенно первое, а по темам, можете предлагать сами в комментариях, буду помогать разобраться.
Если вы с чем-то не согласны или у вас есть что добавить (например в этой статье это будет про личный опыт неудач без RFC), напишите, в случае если это конструктивная правка, я внесу корректировку в статью с указанием автора, поскольку цель этой серии создать в СНГ комьюнити базу по стандартам Биг Теха запада и дать разработчикам новые знания.
Про RFC статьи будут разделены на 2 части:
В первой я расскажу о том что такое RFC, чем отличается от дизайн документа, почему вообще они появились, что будет если их не писать когда надо (личный и крайне не приятный опыт), к каким принципам написания я пришел, когда их стоит писать, а когда нет.
Во второй части же я прямо в статье напишу RFC по системе поисковика на Go и дам мини дз на написания своего RFC, который вы сможете кинуть как PR в репозиторий и я объясню что стоит исправить.
Начнем с ответа на вопрос, что такое вообще RFC.
Сразу скажу что RFC можно писать в двух стилях, оба существуют и в разных ситуациях\компаниях используется свой, различия появляются на последнем этапе, база у них одинаковая:
RFC это документ который приглашает к обсуждению идеи\архитектуры\решений, по факту в нем сначала решается жизнеспособна ли идея, можем ли мы так написать\изменить код, нужно ли нам это и сколько нам будет это стоить.
Также добавлю что по идее документируются принятые и отклоненные решения, какие решения рассматривались в противовес принятым, но к сожалению такое вне крупных компаний или RFC от сильных инженеров я вижу достаточно редко, что зачастую сильно усложняет работу.
Мое мнение что так происходит поскольку люди считают что признать что они в чем-то ошиблись это стыдно и выглядит менее профессионально.
А дальше начинаются различия:
В первом случае RFC становится финальным артефактом и по нему идет реализация, то есть получается гибрид RFC и дизайн документа.
Лично я и придерживаюсь этого стиля, поскольку в основном работаю в одиночку, у меня смешиваются RFC и дизайн документ в единое целое
Во втором случае RFC остается самостоятельным документом как таковым, но так же и становится базой для написания дизайн документа, по которому и будет сделана реализация далее.
Добавлю что нет единого правильного способа писать RFC и пути его развития, это все остается на усмотрение авторов, компании, ситуации и тд.
Чем отличается RFC от Дизайн документа.
Если RFC это документ который задает вопрос нужно ли нам это делать и в каком направлении, то дизайн документ дает инструкцию о том как именно мы будем это делать.
Если приводить аналогию из жизни, то звучать она будет примерно так:
RFC это запись видео того, как дизайнер проектировал набор от начала и до конца, какие принимал решения, какие выборы сделал и что отклонил.
А дизайн документ это уже напечатанная инструкция к этому лего набору, которой вы следуете чтобы собрать модельку.
По поводу видео я возможно чуть перегнул для облегчения понимания аналогии, ибо тут это зависит от автора RFC, у кого-то это будет дневник принятых решений, почему так, у кого-то это будет похоже на просмотр видео, где ты после прочтения видишь что сначала было принято решение А, потом после пересмотра решение Б, а потом вообще решение С. Лично я придерживаюсь второго стиля, но ни один не является единственным истинно верным, все всегда зависит от компании, автора, требований и других факторов.
Почему появились RFC.
Вам нужно написать сложную систему, например новую глобальную фичу на сайте, по типу системы ивентов\платформу для разработчиков, казалось бы, есть ТЗ, что может пойти не так, вы садитесь, начинаете писать, и тут начинаются проблемы, сначала оказалось что фреймворк который вы выбрали не имеет нужной фичи, а другой имеет, потом ломается API, потом оказывается что нужна еще одна фича, который не было в тз, а чтобы ее интегрировать нужно переписать половину кода и в конце начинают появляться фантомные баги и в итоге спустя пол года вы принимаете решение переписать все с нуля и выкидываете всю работу.
Думаю многим знакома такая ситуация. И как вы уже догадались именно чтобы избежать таких ситуаций были и придуманы RFC и дизайн документы
Сначала разграничу понятия:
ТЗ это то, чего хочет заказчик, даже тз написаное по всем гостам, это лишь описание идеи заказчика чтобы разработчик мог понять идею.
RFC же это то, как инженер предлагает решить задачу полученную из ТЗ, то есть какой выбрать язык, какой фреймворк или же писать самим и так далее.
Дизайн документ это то, как команда будет писать код.
Добавлю что по моему опыту в СНГ комьюнити сейчас наблюдается очень неприятная тенденция, что все это (ТЗ, RFC, Дизайн документ) слилось в один термин под названием ТЗ. Это также подтверждает мой недавний диалог с подругой, тоже из IT сферы (разрешение на публикацию получено):
꧁༺Bez sahara ༻꧂: котэ, вопрос
꧁༺Bez sahara ༻꧂: а что у вас в колледже говорят про тз, что это
꧁༺Bez sahara ༻꧂: просто по моему опыту сейчас это смесь всего и вся
Kote Chan: Это то, как должен выглядеть продукт в результате. ТЗ всегда должно разрабатываться перед реализацией, это часть проектирования. Так ты сможешь слепить в голове то, что ты делаешь, определить для себя требования
Kote Chan в ответ ꧁༺Bez sahara ༻꧂:> просто по моему опыту сейчас это смесь всего и вся
В плане?꧁༺Bez sahara ༻꧂: я просто почитал пару тз и часто туда пихают сразу и ТЗ и дизайн документ
Kote Chan: Ну, обычно в прототипах чисто схематично внешний вид
꧁༺Bez sahara ༻꧂: по факту структура такаяТЗ>RFC>дизайн документ
Kote Chan: Первое не поняла, но остальное так-то пишется в ТЗ
Kote Chan: Но без диаграмм
꧁༺Bez sahara ༻꧂: интересно получается
Kote Chan: При желании можно написать описание работы некоторых функций, да
Kote Chan в ответ ꧁༺Bez sahara ༻꧂:> как писать код, какой фреймворк использовать, схемы api и бд
Но это на усмотрение заказчика꧁༺Bez sahara ༻꧂ в ответ Kote Chan:> Но это на усмотрение заказчика
зачастую как раз нет, это решается на уровне RFC꧁༺Bez sahara ༻꧂: заказчик дает что ему надо, это структурируют в тз, передается инженерам, они обсуждают и решают как писать, пишут rfc, тот передается команде реализации
Kote Chan в ответ ꧁༺Bez sahara ༻꧂:> зачастую как раз нет, это решается на уровне RFC
Заказчик может выдвинуть свои требования, касаемо стека꧁༺Bez sahara ༻꧂ в ответ Kote Chan:> Заказчик может выдвинуть свои требования, касаемо стека
в таком случае даKote Chan в ответ ꧁༺Bez sahara ༻꧂:> по факту структура такая ТЗ>RFC>дизайн документ
Про это затрону ещёKote Chan в ответ Kote Chan:> Про это затрону ещё
В групповом проекте у нас было так, что был отдельный человек, который смотрел какую бд и какой стек для чего использовать, одновременно с написанием ТЗKote Chan: Просто, смотри, это не то дело, что учат. Всё это по факту есть в гостах
Kote Chan: Нам всё время говорят ссылайтесь на госты
Как видно получается интересная ситуация, что в РФ судя по всему, проблема смешения всего внутри ТЗ в разы глубже чем я думал до этого диалога.
Личный опыт разработки сложной системы только с ТЗ, без RFC и дизайн документа.
А это пожалуй самая болезненная для меня тема.
Как я писал в более ранней статье, я один из разработчиков сайта по манге, из чего у меня последовала идея написать свой кодек картинок, поскольку все обычные форматы для кодирования изображений созданы чтобы быть универсальными, они были не подстроены под специфику манги и манхвы, из-за этого, я подумал, что написав свой собственный кодек изображений можно было бы достичь лучшего сжатия и лучшей работы конкретно для нашей читалки, тем более что в то время в разработке была читалка на Canvas, следовательно внедрение было бы безболезненным для нас.
Начал я с написания мини тз, звучало оно просто:
Было три основные цели:
Вес не хуже WebP.
Ноль работы CPU на декоде одного пикселя (то есть как только мы распаковали картинку из brotli, декодироваться она должна полностью на gpu параллельно)
Random access, то есть я должен иметь возможность декодировать полосу картинки отдельно, что позволит экономить ресурсы телефона.
Вообще говоря сами требования звучат противоречиво друг для друга, но таковыми кажутся лишь в рамках универсальности, для доменной специфики они вполне выполнимы (что было мной доказано позже в коде).
После написания этого ТЗ стоило бы задуматься о том, чтобы пойти писать RFC или хотя бы дизайн документ, но увы нет, я поверил в себя и пошел сразу же писать код, из-за чего потратил полторы недели на разработку и принятие и тестирование кучи неверных решений или принятия очевидных решений только после траты огромного количества времени, которые мог бы принять еще во время написания RFC потратив пару минут, вместо часов профилирования, приведу примеры (поскольку писал код давно, сейчас не уверен что могу вспомнить все):
Отключить словарь Brotli, поскольку словарь создан под текстовые веб-данные, а картинки это бинарный поток
DCT, поскольку на манге очень часто есть структура из точек, я бы мог его написать во время написания RFC за пару минут, но по факту потратил час или полтора просто на то, чтобы понять почему у меня смазываются градиенты серого на манге, попробовать несколько алгоритмов и наконец вспомнить про DCT.
Deblock, на то, чтобы убрать швы на градиентах я потратил 2 часа и только в конце понял что это можно сглаживать фильтром на декодере.
Как видите даже эти три в сумме дали мне примерно 6 часов работы, кажется что это не так уж и много, всего 1 рабочий день, но проблема в том, что только отклоненных решений там не пара, суммарно было отклонено после тестирование 16 идей и это только из того, что я вспомнил, а по факту более 20, если учитывать что 16 идей, каждая по 2ч, то получаем 32 часа бездарно потраченного времени минимум, добавить к этому время на поиск и использование очевидных решений и по факту получаем порядка 50 часов, усугубляет ситуацию то, что сам кодек писался всего 2 недели, так что от четверти до половины времени было потрачено вникуда, в самом оптимистичном сценарии, по факту больше.
Если бы я посвятил хотя бы те 6 часов потраченных на поиск очевидных решений на написания RFC, что уж говорить про 50+ часов, я бы вероятно достиг лучших результатов в плане скорости и сжатия.
Ссылку на репозиторий с кодеком прикладываю https://github.com/BezSaharaD/Astramanga-Codec-v1
Как писать RFC.
Раз мы наконец разобрались что такое RFC, зачем оно нужно, переходим к тому, как писать RFC, точнее к тому, к какому паттерну написания RFC я пришел.
Написание RFC начинается с вопроса "что" что ты хочешь сделать, чего ты хочешь добиться этим проектом, для каких целей ты его делаешь.
После того как вы задали себе этот вопрос и дали на него ответ, начинается интересное, потому что у большинства есть привычка задавать лишь 1 вопрос, тот самый "что" что мы возьмем чтобы решить эту проблему, что мы решаем в этой проблеме и тд.
Но этот подход жизнеспособен только на относительно простых системах, как только появляется глубина, этих вопросов становится недостаточно чтобы покрыть все, что потом приводит к багам, ранним рефакторингам, несогласию решений и поломкам.
А решаются эти проблемы добавлением всего трех вопросов:
"Почему" Почему мы выбрали Elasticsearch, а не Apache Solr или Meilisearch \ Почему в принципе стал возможен этот баг.
"Как" Как нам починить этот баг так, чтобы закрыть сразу весь класс багов в будущем, а не только этот \ Как нам иметь на поиске 0 downtime и одновременно держать 100 000 RPS.
"Когда" Когда и при каких условиях мы заменим SQLite на PostgreSQL \ Когда и при каких условиях мы будем рефакторить этот микросервис.Это на самом деле самый каверзный и сложный вопрос из трех, поскольку он заставляет думать сразу о нескольких вещах: что сломается первым, почему это сломается, как это сломается, как это починить, как не допустить поломки, на что заменить в случае поломки. то есть вопрос крайне сложный, первое время я вам не советую пытаться дать на него полный ответ, давайте на него лишь краткий ответ, какая метрика должна упасть чтобы мы подумали о замене, но ни в коем случае не пропускайте его, это один из самых важных вопросов больших проектов, без которых шансы на смерть растут экспоненциально.
Как итог мы имеем 4 вопроса которые надо задавать во время проектирования, чтобы закрыть большинство дыр:
"Что" Что мы проектируем
"Почему" Почему мы это проектируем так, а не иначе
"Как" Как мы проектируем эту систему
"Когда" Когда и в каких условиях мы будем ее пересматривать
Добавлю три важных уточнения:
Первое: документируйте вопросы и ответы на них, то есть не в голове отвечайте на них, а прямо в документе, это позволит вам\другому разработчику через полгода не пытаться вспомнить ответы на эти вопросы, а прочитать их в тексте и получить ответы на вопросы и быстрее влиться в разработку, плюс не будет хождения кругами.
Второе: по факту задав и задокументировав ответ даже всего на один вопрос вы очень сильно повысите читаемость документа и доверие к нему, а также защитите от указанных мной ранее проблем, поскольку рассмотрите альтернативы и дадите аргумент почему они хуже, ну или почему они лучше и их стоит взять.
Третье: вытекающее из первого, документируйте решения в тексте кратко, а в конце отдельным блоком полностью развернуто, чтобы вы или другой человек всегда мог при первом чтении увидеть, что решение взято не с потолка, а после проверок и сравнений, а в конце или при повторном прочтении увидеть полный список того, что было рассмотрено и почему отклонено (пример такого подхода есть в моем RFC на Spectra, раздел 13).
Так же как пример приложу свой RFC который прямо сейчас в процессе написания и где я пишу по этим же паттернам: https://github.com/BezSaharaD/Spectra
Когда писать RFC.
На этот вопрос нет и не может быть однозначного ответа, в каждой компании, в каждой команде, у каждого человека свои правила, убеждения и привычки по поводу написания документации и RFC.
В одной компании может вообще не быть культуры RFC и все пишут по ТЗ сразу код, в другой строгая структура ТЗ>RFC>дизайн документ, в третьей на усмотрение человека, в четвертой в зависимости от сложности задачи.
Лично я придерживаюсь логики: насколько система известна и проработана у других людей и сколько не явных, но важных решений мне надо принять чтобы это реализовать, приведу пример:
Есть задача написать магазин с фильтрами и сортировкой на сотни товаров, это типовая задача которую все давно отработали и на нее есть много данных, информации и RFC, в данном случае я сразу сажусь писать дизайн документ, поскольку задача явная и простая и все подводные камни давно проработаны до меня.
А есть задача написать поиск для сайта по манге, больше 100 тысяч произведений, поиск не равномерный, а с уклоном в популярные произведения, RPS имеет явные пики и просадки в течение дня, сами фильтры тоже имеют уклон в одну сторону. В данном случае получается ситуация что слишком много не явных решений надо принять:
Как держать пики, что делать во время простоя, как лучше распределить ресурсы для популярных произведений, какой фреймворк и бд выбрать для поиска и почему не другие, как делать миграцию и когда. Все это огромный пласт решений, который требует решений, но будет заметен не сразу, а лишь во время написания документа.
На этом логически заканчивается первая часть, я покрыл большую часть базы, но пропустил достаточно важную тему ADR, по ней я к сожалению не могу дать достаточной информации, поскольку я в силу работы в одиночку, придерживаюсь стиля слияния RFC, ADR и дизайн документа в одну структуру вместо разделения на разные документы.
Просьба людей с опытом в ADR дать свои мнения или ссылки на статьи, я вставлю их в саму статью с указанием автора, плюс прошу и вас предоставить свои результаты провалов из-за отсутствия RFC или другого документа, это будет полезно людям.
Статья по написанию RFC (где я прямо в статье напишу RFC на поисковик) когда выйдет я к сожалению предсказать не могу, ибо занят на основном проекте.
Материал по ADR:
https://habr.com/ru/companies/otus/articles/840412/
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.