Что такое архитектура на самом деле
Архитектура — это решения, которые дорого менять. Не диаграммы и не паттерны. Дизайн и архитектура работают на разных горизонтах стоимости. «Best practice» — это категориальная ошибка: контекст определяет пригодность, а не название паттерна.
Стартап выпускает монолит. Он работает. Через два года команда выросла до тридцати инженеров, и каждая фича занимает шесть недель, потому что всё завязано на модуль payments. CTO называет это «проблемой архитектуры» — но никто никогда не принимал решение связать payments со всем остальным. Просто никто никогда не принимал решения этого не делать. Связность накапливалась по одному маленькому срезу пути, каждый разумный сам по себе, пока отмотать её назад не потребовало бы переписать половину системы. Команда всё это время принимала архитектурные решения — просто не называла их так.
Определение через стоимость изменения
Самое полезное определение программной архитектуры — не про диаграммы со стрелочками и не про именованные паттерны. Ральф Джонсон сформулировал просто: архитектура — это решения, которые сложно изменить. Мартин Фаулер уточнил: решения, которые стоят всё дороже и дороже менять по мере того, как система растёт вокруг них.
Эта формулировка сразу отделяет архитектуру от обычного дизайна. Если сегодня выбрал имя переменной, а завтра захотел лучше — rename-рефактор занимает двадцать секунд. Это дизайн — низкая стоимость возврата. Если вложил логику billing прямо в HTTP-обработчик, а через двенадцать месяцев хочешь вызывать тот же billing из фонового задания, мобильного приложения и партнёрского API — это структурная проблема, которая потребует недель рискованной хирургии. Это архитектура — решение с высокой стоимостью возврата.
Вывод неудобный: ты принимаешь архитектурные решения постоянно, независимо от того, называешь ли ты их так. Вопрос не в том, принимать ли их, а в том, принимать ли их намеренно.
Дизайн vs архитектура: два разных горизонта
Дизайн и архитектура — не два уровня иерархии; они работают на разных временных горизонтах и с разными конвертами стоимости.
Дизайн — это форма решения внутри уже установленного структурного контекста. Какой класс содержит этот метод? Как назвать эту функцию? Как должен выглядеть API этого модуля? Эти выборы важны для читаемости и корректности, но их можно пересмотреть без структурной хирургии. Дизайн-решения живут внутри границ, которые нарисовала архитектура.
Архитектура рисует эти границы. Где проходит граница между доменом billing и доменом shipping? Владеет ли каждый домен своей схемой БД, или они используют общую? Может ли сервис заказов обращаться к сервису биллинга синхронно, или это должно идти через событие? Эти решения распространяются структурно — они ограничивают каждое дизайн-решение, принятое после них.
Путаница возникает потому, что одна и та же технология может быть и тем, и другим. Выбор PostgreSQL для прототипа — это дизайн-решение: можно сменить. Выбор PostgreSQL как единственной общей БД, схему которой напрямую запрашивают восемь сервисов, каждый из которых предполагает конкретные структуры таблиц, — это архитектурное решение. Ты встроил допущение настолько глубоко, что БД нельзя заменить, не заменив все восемь сервисов сразу.
▸Почему это работает
Почему это различие важно на практике? Потому что команды относятся к двум видам решений по-разному. Дизайн-решения пересматривают на код-ревью. Архитектурные решения принимаются в разговорах, которые могут нигде не фиксироваться. Эта асимметрия — то, как связность тихо накапливается: никто не говорит «сегодня мы принимаем архитектурное решение подцепить billing к HTTP-слою». Говорят «давай пока просто вызовем функцию billing прямо из обработчика» — фраза, звучащая как дизайн-решение, но в контексте являющаяся архитектурным.
Категориальная ошибка «best practice»
«Используй микросервисы» — это best practice. «Используй hexagonal architecture» — best practice. «Отдели бизнес-логику от инфраструктуры» — best practice. Эти предписания появляются в книгах, докладах и инженерных блогах, и они не ошибочны — они описывают паттерны, решавшие реальные проблемы в конкретных командах в конкретных контекстах. Ошибка — трактовать предписание как контекстно-независимое.
Best practices — это решения для конкретных сил. Паттерн hexagonal architecture существует потому, что силы «мне нужно тестировать бизнес-логику без базы данных» и «мне нужно запускать одно и то же приложение из HTTP-сервера, CLI и очереди сообщений» оказывают реальное давление. Если эти силы присутствуют в твоей системе, hexagonal architecture хорошо подходит. Если твоя система — это CRUD API, на которую эти силы никогда не будут давить, hexagonal architecture добавляет слои, интерфейсы и indirection без соответствующей пользы. Это не «best» для тебя — это overkill.
Правильный вопрос никогда не «что является best practice?». Он — «каким силам подвержена моя система, и какие структуры отвечают этим силам?». Это рамка, которую использует весь остальной трек. Каждый рассматриваемый паттерн будет представлен как ответ на поимённый набор сил — и компромиссы, которые он при этом делает.
Чем архитектура не является
Две вещи часто маскируются под архитектуру:
Диаграммы. Диаграмма описывает архитектуру — она не является архитектурой. Команды часто путают артефакт с реальностью. Архитектура — это фактическая структура связанности в кодовой базе; диаграмма — модель этой структуры. Когда диаграмма говорит «billing — отдельный сервис», а код разделяет схему БД с ordering, диаграмма неверна, а связность — реальность.
Upfront-дизайн. Архитектура не требует фазы проектирования перед написанием кода. Многие из самых устойчивых систем проектировались инкрементально — каждое решение принималось тогда, когда силы были достаточно понятны, чтобы принять хорошее решение. Что архитектура требует — так это намеренности: понимания, какие решения дорого менять, принятия их обдуманно и фиксации причин. Это может происходить в любой точке проекта.
▸lesson.inset.note
Практический тест — является ли решение архитектурным: спроси «если мне нужно отменить это через двенадцать месяцев, сколько кодовой базы придётся трогать?». Если ответ — «большую часть», решение архитектурное, независимо от того, было ли оно помечено как таковое. Этот тест также раскрывает, почему кажущиеся незначительными решения — например, выставляет ли сервис свою внутреннюю модель данных как публичный API — становятся архитектурными по мере роста потребителей системы.
Команда кладёт логику billing прямо в HTTP route handlers. Через полгода им нужен billing из фонового задания и партнёрского webhook. Что делает это архитектурным, а не дизайн-решением?
Команда строит CRUD API для простого внутреннего инструмента, у которого никогда не будет нескольких точек входа и нет давления на тестирование бизнес-логики. Senior-инженер предлагает принять hexagonal architecture. Что является наиболее точным ответом?
Актуальная диаграмма архитектуры показывает billing как изолированный сервис. Реальный код вызывает логику billing напрямую из слоя репозитория сервиса заказов через общую внутреннюю библиотеку. Какая из них является реальной архитектурой?
- 01Как отличить архитектурное решение от дизайн-решения?
- 02Почему 'best practice' является категориальной ошибкой применительно к архитектурным паттернам?
- 03Если диаграмма архитектуры и код расходятся, какая из них является реальной архитектурой?
Архитектура — это набор решений, которые становятся всё дороже отменять по мере того, как система созревает вокруг них. Это отделяет её от дизайна — который работает внутри уже установленного структурного контекста и остаётся дешёвым для пересмотра. Различие не об уровне диаграммы или количестве файлов: однострочное решение, связывающее billing с HTTP-слоем, является архитектурным; многофайловый rename-рефактор — нет.
Именованные паттерны — hexagonal, clean, DDD, CQRS — это ответы на конкретные силы. Это не best practices для универсального следования; это решения, стоящие своей сложности только тогда, когда присутствуют силы, которые они адресуют. Принятие их без этих сил — это спекулятивная архитектура, создающая накладные расходы без соответствующей пользы.
Диаграмма — это не архитектура; архитектура — это код. Намерения, проектные документы и диаграммы описывают архитектуру, которую хотели. Фактическая связанность в кодовой базе — это существующая архитектура. На протяжении всего трека мы будем называть силы первыми, а структурные ответы — вторыми: это единственный способ рассуждать о том, подходит ли данная структура для данной системы.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.