Не называйте код словом «Продукт». Об архитектуре
Это статья для руководителей отделов разработки, бывших разработчиков. Я очень часто слышу два противоположных мнения. Они звучат примерно так:
- «Нам важен готовый продукт — плевать на плохой код»
- «Нам важен поддерживаемый продукт — пусть это и будет долго»
Это вечный спор между «говнокодом» и «скоростью разработки», менеджерами и разработчиками. Ошибаются обе стороны. Это два конца одной палки. На этой палке я бы написал красными буквами «ошибки руководителя разработки». Кому интересная эта тема — добро пожаловать под кат. А еще под катом много букв об архитектуре ПО, микросервисах и здравом смысле.
Вообще эта статья началась с обсуждения Agile Manifesto в facebook… Тема обсуждения была примерно следующей — «готовый продукт важнее чем люди и их взаимодействие». В целом я понимаю боль автора и боль всех участвовавших в комментариях. Еще я понимаю что словом «Продукт» часто называют то, что продуктом не является. И это порождает последствия и проблемы в реальных программных решениях.
Продукт (в нашем случае программный продукт) — это бренд и маркетинг, продажи, постподажная поддержка, реклама и предпродажная работа, и конечно наш код. Процесс, называемый словом «бизнес» — обеспечивает сращивание этих частей воедино, и это сращивание приносит деньги.
Код (наше программное обеспечение, ПО) — это часть продукта. Как и другие части она должна легко скрещиваться с остальными частями и подстраиваться под них. Под понятием «легко» — я подразумеваю следующий набор: «быстро», «не титаническим трудом», «без внезапных последствий».
Многие ошибаются и говорят что качество кода здесь решающий момент. Обычно все сводиться к тому, что «говнокод можно быстро написать и запустить», а «хороший код не имеет внезапных последствий». Нет. Решающий момент — это возможность это ПО менять. Ведь процесс скрещивания ПО с остальными частями бизнеса — это и есть его изменение.
Когда маркетологи просят сохранять utm-метки зареганного юзера, когда нужно отправлять емейлы определенной верстки, когда нужно добавить в ваш интернет-магазин фичу «а с этим покупают еще» — это и есть процесс интеграции ПО с остальными частями бизнеса. Именно этот процесс должен происходить быстро, просто, без внезапных багов. И не нужно изобретать велосипед — все уже придумано до нас.
Модульность
Если Вы не приверженец SOA/микросервисов и пишите монолит — сделайте его модульным. Зачем это нужно? Вот набор основных пунктов:
- 1 фича — 1 модуль. Можно легко и быстро написать с нуля «из грязи и веток» — то, что требуется для бизнеса сейчас. Когда возникнет нужда это поддерживать — можно легко изменить код модуля для большей читаемости, сохранив интерфейс.
- Компоновка. Хороший модуль — не вещь в себе. Его можно переиспользовать и компоновать. Вспоминаем bash и pipe;-) «cat /etc/passwd | grep root | tr ':' ' ' | awk '{print $2}'» — вот он пример модульности и компоновки. Unix-way называется.
- Легко выкинуть/выключить. Если маркетинг ошибся (а в среднем 70% действий маркетинга — это пробы, ошибки, снова пробы) — можно легко выкинуть лишний кусок.
Как это поможет быстро и надежно делать фичи? Ну во первых писать с нуля маленький модуль — это и правда быстро. Во вторых — имея возможность компоновки — через полгода-год большую часть писать вообще не придется — просто скомпоновать и чуть-чуть дописать (новый маленький модуль). Про отсутствие титанического труда есть единственное условие — опишите архитектуру модуля и их взаимодействия (компоновки) в документации и строго ей следуйте, не усложняйте ее сразу и не изменяйте потом. Возьмите за основу известный всем фреймворк. Если этого придерживаться и не выходить за рамки продуманной арихектуры — титанический труд не потребуется. Вы же не пересобираете grep каждый раз когда что то делаете в консоли.
Про баги и предсказуемость — модуль живущий в рамках себя и имеющий простой неизменный интерфейс очень легко тестировать. Я не говорю о написании unit-тестов прямо сразу. В первый момент это может быть ручное тестирование. Прибегать к автоматике следует только когда есть нужда запускать ее каждый раз — т.е. модуль активно меняется внутри.
SOA/микросервисы
Эта та же самая модульность и правила те же, только более гибкая. Разница в том, что модули теперь называются сервисы и взаимодействуют не вызовом публичных методов, а по сети передачи данных. Правила те же, но с добавлением нового — оно делает жизнь бизнеса еще легче. Вот полный список:
- 1 фича — 1 сервис.
- Компоновка.
- Легко выкинуть/выключить.
- Стандартные протоколы взаимодействия. Это огромный плюс SOA — ведь по стандартному протоколу вы можете легко добавить в ваше решение сторонее ПО. Образно — использование Radius, OAuth2 — позволяет легко авторизовывать своих пользователей в стороннем продукте. Использование стандартны форматов данных (json, xml) интегрироваться с различными ентерпраз решениями, например с каким то готовым движком интернет магазина. Чтобы это было не тяжким трудом — читаем выше (1 сервис — 1 фича, компоновка, следовать единой схеме)
Разработать и продумать SOA архитектуру, выбрать протоколы и форматы сложнее чем разработать модульный монолит, но большой плюс SOA — это то, что все велосипеды придуманы до нас — нужно только выбрать.
Какое это имеет отношение к слову «Продукт»?
На самом деле одно единственное — простая и гибкая архитектура помогает строить продукт и делает из IT надежную часть бизнеса, а не «слабое звено компании».
Иметь возможность быстро выпускать изменения с предсказуемым поведением, без постоянного прироста затрат — основное требование к команде разработки. Конечно есть и другие требования, они свои в каждом бизнесе, но они относятся более к деталям работы, а не к сути.
«Кому нужна архитектурочка»?
Ответ так же прост как и вопрос — не надо путать понятие архитектуры и «красивого кода». Красивый код нужен разработчикам, чтобы его было легко править, можно было им мериться с коллегами. Простая и гибкая архитектура — заказчику, чтобы его требования к разработке выполнялись.
Архитектура — это как набор спичечных коробков. В них можно спички положить, можно траву. Можно наколеночный код, можно красивый. Она ни к чему не обязывает. Если вы такой спичечный коробок сделаете, что ничего кроме спички в него не засунуть, то конечно этот коробок — фигня полная.
То, как же нам «передавать данные в шаблоны из контроллеров» — в виде массивов или объектов-коллекций — в большинстве случаев не имеет вообще никакого отношения к архитектуре ПО.
Так же не нужно относить к архитектуре выбор языка на котором вы пишите — на любом полноценном языке программирования можно создать хорошую архитектуру, а можно и плохую.
Как создавать хорошую архитектуру?
Работа по продумыванию взаимодействия и компоновки модулей/сервисов — по большей части основана на выборе. Чтобы выбирать — нужно знать стек технологий с которыми вы работаете. Выбирать наиболее простые.
Знать стек технологий — это не значит «я знаю кунг-фу, карате и другие крутые слова». Знать стек нужно с начала, а не с конца — многие вещи родились 30 лет назад и работают отлично, выполняя свои функции до сих пор. Конечно всегда хочется взять что-то новое и попробовать, поучиться —, но «пробовать и учиться» — это для Junior/Middle разработчика, не для архитектора.
Знать стек технологий нужно детально и изнутри. Всегда задайте себе вопрос — «почему я выбрал это?». Если вы ответили на этот вопрос «я с этим знаком больше» — значит у вас недостаточно опыта для трезвого выбора решения, нужно изучать технологии.
Если вы ответили «кроме этого решения — альтернатив нет» — есть два варианта:
- Вы не знаете о существовании альтернатив — ищите их! Ну уж за 40 лет IT решений изобрели огромную массу на самые разные случаи.
- Вы делаете что-то странное. Если до вас так никто не делал — наверное были причины не делать именно так. Не думайте, что у вас уникальный проект и прочее — если вы не строите Токамак — то он не уникальный в общем смысле. Просто с ним что-то не так.
Что делать если вам достался уже готовый проект с пятнадцатилетним legacy? В нем нет модульности, нет сервисов, а те что есть — далеко не микро. Идите по стратегии разбиения монолита. От большого старого монолита удобно идти к микросервисам. Выносите атомарные части во вне. Начните с вынесения технически сложных вещей — это сразу минимизирует баги и даст время на позитивную разработку.
Микросервис — это как функциональное программирование. Только не функция, а сервис. Он прост, атомарен. Когда в микросервисе есть только одна функция — например предоставлять OAuth — он только это и должен делать, БД должна быть вне него. Или сервис для ресайза картинок — только ресайзит их. Не нужно в нем же их хранить.
Итог
Итог наверное в том, что холивар «красивый код»/«быстрое решение» в целом ни о чем. Базируется он обычно на нерасширяемой архитектуре.
Архитектура — не самое важное в ПО. Ее не нужно развивать и разрабатывать — это работа на 3–5 дней. Сесть, подумать, описать. И еще на полгода-год для руководителя — научить всех ее придерживаться.
Архитектура — не серебряная пуля. Она не делает ни фич, но может сделать баги. Грамотная архитектура — позволяет делать фичи быстро на коленке рядом с остальным красивым кодом и не портить общую картину. Компоновать, переиспользовать. Неграмотная — приводит к внезапным проблемам и долгой разработке. Ее отсутствие — обычно к тому же что и неграмотная.
О чем статья? По сути ни о чем. Она для тех кто продолжает спорить — «красивый код» vs «быстрое решение».
© Megamozg