Источник
Обзор на tellmeabout.tech
Статья из клуба Code of Architecture — часть 1
Clean Architecture: A Craftsman's Guide to Software Structure and Design (Чистая архитектура. Искусство разработки программного обеспечения)
Авторы: Robert C. Martin
Издательство: Pearson, 2017
Объём: 432 страницы
Классика от Uncle Bob: SOLID принципы, component cohesion и coupling, Main Sequence и plugin-архитектура.
Оригинал
ПереводВведение: Дизайн и Архитектура
Основной тезис введения книги прост и амбициозен:
"When software is done right, it requires a fraction of the human resources to create and maintain. Changes are simple and rapid. Defects are few and far between."
Архитектура = Дизайн?
По мнению автора, нет разницы между архитектурой и дизайном — это единый континуум от высокоуровневых структур до низкоуровневых деталей.
Главный вывод
"The only way to go fast, is to go well" — правильная архитектура окупается в долгосрочной перспективе.
Связанная книга
A Philosophy of Software Design
Ousterhout также говорит о борьбе со сложностью и стратегическом программировании
Два аспекта ценности ПО
Каждая программная система имеет два аспекта ценности для стейкхолдеров:
Behavior (Поведение)
Функциональные требования — как система работает. Важно для бизнеса. Обычно воспринимается как "срочное".
Structure (Структура)
Архитектурные аспекты — сложность внесения изменений. Важно для команды. Обычно воспринимается как "важное".
Автор предлагает использовать матрицу Эйзенхауэра для принятия решений. Проблема в том, что бизнес-менеджеры часто возносят срочные, но не важные задачи, откладывая важные архитектурные решения.
"It is the responsibility of the software development team to assert the importance of architecture over the urgency of features."
Парадигмы программирования
Существует три основные парадигмы программирования, каждая из которых накладывает ограничения и имеет значение для архитектуры:
| Парадигма | Ограничение | Преимущество | Для архитектуры |
|---|---|---|---|
Structured Programming | Запрет goto | Декомпозиция на тестируемые функции | Функциональная декомпозиция |
Object-Oriented Programming | Безопасный полиморфизм | Plugin-архитектура, DIP | Разделение компонентов |
Functional Programming | Иммутабельность | Отсутствие race conditions | Segregation of Mutability |
Structured Programming
Дейкстра доказал, что любую программу можно сконструировать из трёх структур:sequence,selection,iteration.
"Testing shows the presence, not the absence, of bugs" — Дейкстра
Object-Oriented Programming
OOP — это комбинация инкапсуляции, наследования и полиморфизма. С точки зрения архитектора, самое важное — полиморфизм, который обеспечивает инверсию зависимостей и независимую разработку/деплой.
"OO is the ability to gain absolute control over every source code dependency in the system."
Functional Programming
Основная особенность — иммутабельность переменных. Для архитектуры это означает отсутствие race conditions и deadlocks. Отсюда пришёл паттерн Event Sourcing.
"Event sourcing is a strategy wherein we store the transactions, but not the state."
Часть 2
Обзор на tellmeabout.tech
Принципы SOLID и Component Principles
Design Principles (SOLID)
Принципы SOLID направлены на создание mid-level структур ПО, которые:
- Толерантны к изменениям
- Просты для понимания
- Являются базисом для переиспользуемых компонентов
Принципы SOLID
Кликните на букву для подробностей
SSingle Responsibility Principle
Не "функция должна делать одну вещь", а модуль должен быть ответственен перед одним актором. Симптомы нарушения: accidental duplication и merge conflicts.
OOpen-Closed Principle
Артефакт должен быть открыт для расширения, но закрыт для модификации. Это один из движущих факторов архитектуры систем.
LLiskov Substitution Principle
Подтипы должны быть взаимозаменяемы с базовыми типами. Нарушение этого принципа приводит к "развесистой" логике с альтернативными ветками.
IInterface Segregation Principle
Клиент не должен зависеть от методов, которые он не использует. На уровне архитектуры: не зависеть от компонентов с избыточной функциональностью.
DDependency Inversion Principle
Наиболее гибкие системы — те, в которых зависимости в исходном коде ссылаются только на абстракции. Используйте Factory паттерн для инверсии зависимостей.
Dependency Inversion с Factory паттерном
Как инвертировать зависимости с помощью абстракций
Проблема: прямая зависимость
Application напрямую зависит от ConcreteImpl — нарушение DIP
Связанная книга
Fundamentals of Software Architecture
Richards и Ford развивают тему component coupling через Connascence
Component Principles
Компоненты — это единицы развёртывания (units of deployment). После 50 лет развития мы пришли к plugin-архитектуре как стандарту.
Component Cohesion
Три принципа определяют, как разбивать классы по компонентам:
REP
Reuse/Release Equivalence
Классы, которые релизятся вместе, должны иметь общую тему или цель.
CCP
Common Closure
Собирать в компоненты классы, которые меняются по одним причинам и в одно время.
CRP
Common Reuse
Не заставляйте пользователей компонента зависеть от того, что им не нужно.
Tension Diagram: Component Cohesion
Архитектор балансирует между этими принципами в зависимости от потребностей проекта
Component Coupling
Три принципа управляют взаимоотношениями между компонентами:
ADP: Acyclic Dependencies Principle
Не допускайте циклов в графе зависимостей компонентов.
Граф зависимостей должен быть направленным ациклическим графом (DAG). Для устранения циклов используйте DIP.
SDP: Stable Dependencies Principle
Зависите в направлении стабильности.
Метрики: FanIn (входящие), FanOut (исходящие), I = FanOut / (FanIn + FanOut). I=0 — полностью стабильный, I=1 — полностью нестабильный.
SAP: Stable Abstractions Principle
Компонент должен быть настолько абстрактным, насколько он стабилен.
Метрика: A = Na / Nc (количество абстрактных классов к общему количеству). Микс SAP + SDP = DIP для компонентов.
Main Sequence и зоны риска
Идеальная диагональ: баланс между абстрактностью и стабильностью. Формула: D = |A + I - 1|
Конкретные и стабильные компоненты (A≈0, I≈0). Сложно менять, так как много зависимостей.
Абстрактные и нестабильные компоненты (A≈1, I≈1). Абстракции без реализаций.
Ключевые выводы
Архитектура важна
"If architecture comes last, then the system will become ever more costly to develop."
Plugin Architecture
OOP даёт возможность создавать plugin-архитектуры с независимой разработкой и деплоем.
Эволюция структуры
Структура компонентов должна эволюционировать со временем — её нельзя спроектировать раз и навсегда.
Main Sequence
Компоненты должны располагаться вдоль главной последовательности, избегая зон "боли" и "бесполезности".
