Разработка
Отсутствие архитектуры лучше, чем плохая архитектура
Мне потребовалось несколько лет, чтобы научиться писать код, масштабируемый на десятки членов команды и миллионы строк кода. Потребовалось еще больше времени, чтобы снова научиться писать глупый код.
Мне потребовалось несколько лет, чтобы научиться писать код, масштабируемый на десятки членов команды и миллионы строк кода. Потребовалось еще больше времени, чтобы снова научиться писать глупый код.
Оказывается, «построение прочной архитектуры» в вашем коде может легко стать напряженной работой и прокрастинацией.
Оказывается, вы можете потратить много энергии, пытаясь избавиться от всего дублирования кода и придумывая мощные абстракции для поддержки «будущих вариантов использования».
Оказывается, одна часть вашего кода может преднамеренно быть хорошо продуманным, защищенным произведением инженерного чуда, а за другую вас уволят.
Когда вы впервые изучали «лучшие практики программирования», вы каким-то образом предполагали, что существует четкая грань между хорошей и плохой архитектурой. Вы читали или слышали ужасные истории о неподдерживаемых проектах со слишком большим количеством гнилого спагетти-кода. Неизбежно в конечном итоге получилось так, что вы стали работать над одним из них.
Так вы поняли, что значит разделять задачи, извлекать абстракции, инвертировать зависимости и так далее. Время от времени вы получали менее 50 комментариев к вашим пул реквестам. И так вы чувствовали себя настоящим профессионалом!
Но те ужасные истории, которые вы слышали… они были правдой. Без достаточной заботы, предусмотрительности и дисциплины проект становился беспорядочным быстрее, чем ожидалось. Вы видели бесконечные таблицы «приоритетного технического долга», который все равно не исправлялся, потому что вам нужно было выпустить новую версию. И единственный человек, который все еще знал, как все устроено, прямо тогда уволился!
Но все это в прошлом. За эти годы вы разработали дюжину эвристик и нашли лучшие правила, которые предотвращают переписывание вашего кода через два (теперь уже три!) года. Ура!
Идти далеко или идти быстро
До сих пор я описывал то, что мне нравится называть «уйти далеко с кодом». Любой может написать код, который будет работать несколько дней, прежде чем станет непригодным для сопровождения. Чтобы научиться поддерживать кодовые базы живыми и процветающими в течение многих лет активной работы, нужны практика, слезы и несколько переписываний.
Теперь, если вы работаете в организации с (а) достаточными ресурсами и (б) высокой уверенностью в том, что вы делаете, уйти далеко будет вашим самым важным трудовым навыком. В значительной степени это то, что сделает вас Senior программистом и будет платить вам невероятную зарплату.
Однако, если вы когда-либо работали со стартапами или основывали свои собственные коммерческие проекты (не имея ни ресурсов, ни уверенности), вы быстро заметили бы, что «идти далеко» — это не то, о чем вы думаете большую часть времени.
Идти быстро
Оказывается, разработка кода — введение детальных концепций, абстракций, отношений и присвоение всем этим вещам имен, областей действия и обязанностей — имеет свою цену. Кроме того, сносить такие конструкции стоит в 10 раз дороже, чем строить.
Из-за нехватки времени вы, скорее всего, будете добавлять все больше и больше вещей к протекающим абстракциям, чем сносить их и переписывать весь скоуп.
Еще один риск заключается в том, что проектирование и структурирование кода — отличный и увлекательный способ прокрастинации. Как техническому основателю, мне не нравятся многие вещи, которые я должен делать, чтобы запустить успешный проект. Работа с кодом часто кажется просто убежищем от всего беспокойства, вызванного вещами, которые я должен делать вместо этого.
В большинстве случаев, затраты на создание слишком большой структуры выходят за рамки простого «качество требует времени». Например, чаще всего вы просто еще не знаете, что строите, по большому счету. Большая часть кода в конечном итоге будет выброшена или переписана по мере того, как вы приближаетесь к product-market fit, и редко бывает легко понять, какой код останется, поэтому вы склонны рассматривать почти весь код как временный.
Так какое здесь оптимальное решение? Неужели нам действительно нужно вернуться и начать писать тот же дерьмовый код, что и в начале? Это звучит неправильно!
Писать глупый код нормально
Я не думаю, что у меня есть самые правильные ответы. Тем не менее, позвольте мне поделиться несколькими практическими эвристиками, которые я изучил и которые помогли мне избежать плохих результатов в обеих крайностях: неподдерживаемый проект или ужасно низкая скорость.
1. Код не одинаков
Как и во многих других случаях, в вашем коде есть много случаев распределения Парето.
Впервые это пришло мне в голову, когда я пытался понять, как написать как можно меньше тестов, которые обеспечили бы максимальное улучшение стабильности. Вскоре стало очевидно, что чаще всего вызывается только крошечная часть моего кода, и в случае сбоя она доставит больше всего проблем.
Итак, я расширил эту модель, чтобы решить, на что я должен потратить дополнительное время и заботу и пожертвовать скоростью сейчас ради долгосрочных выгод.
У меня есть 3-летняя SaaS с 60 тысячами строк кода. Когда я начал обращать внимание, я был удивлен, увидев, что большую часть кода я не читал и не редактировал месяцами (или вообще никогда). Это большинство конечных точек API, большинство страниц пользовательского интерфейса и т.д. Кроме того, большая часть этого кода вызывалась на порядки реже, чем другая.
И когда я увидел copy-paste функции и гигантские функции «сделать все и сразу», я испытал такое странное облегчение, что не стал тратить время на рефакторинг. Я имею в виду… он работает! Я все еще могу понять код и внести изменения. Я мог бы потратить пару часов на то, чтобы лучше его структурировать и сэкономить несколько минут, когда буду работать с ним в следующий раз… через год.
Чтобы было ясно, я не выступаю за написание плохо пахнущего кода как такового. Вместо этого я имею ввиду написание простого кода, который часто смешивает поток более высокого уровня с деталями более низкого уровня, не зацикливаясь на проблемных областях. Он все еще может быть элегантным до определенной степени. Он по-прежнему должен хорошо представлять намерение и объяснять, что он делает.
Еще один полезный прием — отгородить самые важные части от остальных, чтобы деготь не попал в мед.
2. Пусть сначала будет запрос на структуру
Если предыдущая аналогия заключалась в написании тестов, то здесь речь пойдет об оптимизации производительности.
Одна из лучших эвристик в отношении производительности заключается в том, что все улучшения должны выполняться с помощью открытого профилировщика — никаких угадываний!
Я бы сказал, что то же самое полезно для рефакторинга.
Гораздо проще придумать общие случаи (абстракции), когда у вас уже есть 3-4 конкретных случая (часто с дублированием кода). Пусть такие случаи сначала появятся. Таким образом, вам больше не придется предсказывать будущее, а просто структурировать то, что уже есть.
Другими словами, будьте умеренны в удалении (или предотвращении) дублирования кода и повторений в целом.
Эта идея настолько популярна, что в Википедии есть статья, в которой упоминается книга, написанная в 1999 году!
Это не абсолютное правило. Иногда, особенно в случае служебных функций, вы просто знаете, что вам нужно сначала сделать строительный блок, а затем использовать его везде. Доверяйте своей интуиции, но убедитесь, что вы осознанно относитесь к выбору.
3. Всегда начинайте с одного
Я нахожу эту концепцию настолько полезной, что собираюсь написать целую статью, посвященную ей.
Правило довольно простое: если у вас нет веских аргументов против, начните с файла, класса, функции, таблицы и т.д.
Как и при создании абстракций на основе существующих случаев, разделение всегда проще, если у вас уже есть материал для работы. Таким образом, вам не придется гадать, в какие корзины попадут вещи в будущем.
Начать с одного — это надежный (хотя и радикальный) способ устранить многие ментальные барьеры, мешающие вам что-то сделать.
Как и в случае с другими правилами, есть веские причины их нарушать. Доверяйте своей интуиции, но убедитесь, что вы не откладываете на потом настоящую работу.
Один из примеров, который люди часто приводят, — это то, как у Питера Левелса был один файл index.php для бизнеса, который приносил сумасшедший доход.
Что лучше
Вот и все!
Резюме таково: если вы хотите двигаться быстро, вы должны отложить построение архитектуры, и если часть вашего кода дерьмо, по крайней мере, пусть оно будет мягким.
Как всегда, спасибо, что зашли так далеко.
Если вам понравился эта статья, возможно, вам понравятся и другие этого автора. Ссылка на блог ниже.