Skip to content

Конспект книги «Чистая архитектура»

Notifications You must be signed in to change notification settings

ashergizer/clean-architecture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

author
Dmitriy Batogov
Jul 28, 2019
e42b073 · Jul 28, 2019

History

1 Commit
Jul 28, 2019

Repository files navigation

Чистая архитектура

Тезисы о важности архитектуры в программном продукте:

  • Хорошая архитектура позволяет минифицировать затраты на поддержку и улучшение программы в будущем.
  • Если не продумать архитектуру на старте проекта, а заниматься только продуктовыми задачами, то вскоре стоимость этих задач сильно возрастёт. Возможно, что в один момент придётся перестать работать над функционалом и сесть за дорогостоящее переделывание архитектуры.
  • Не стоит откладывать «на потом» архитектурные моменты. Вряд ли это время наступит, а плохие решения могут надолго закрепиться в проекте.
  • С плохой архитектурой увеличение количества разработчиков не поможет масштабированию.

Ценности программы

У программного обеспечения есть две ценности: структура и поведение.

Поведение — это то, как программа работает, какие требование бизнеса выполняет. Именно ради поведения бизнес нанимает разработчиков и платит им деньги.

Но кроме этого, у софта есть и другая ценность — структура. Структура — это возможность вносить изменения в программу.

Если программа работает правильно, но в неё нельзя вносить правки, она быстро придёт в негодность. Однако же, если программа работает неправильно, но в неё можно без проблем вносить правки, то исправить ошибку не составит большого труда.

Выбор между этими двумя ценностями — это всегда борьба. Борьба, в которой разработчику необходимо научиться доказывать пользу от рефакторинга и улучшения архитектуры.

Что важнее — правильная работа системы или простота ее изменения? Если задать этот вопрос руководителю предприятия, он наверняка ответит, что важнее правильная работа. Разработчики часто соглашаются с этим мнением. Но оно ошибочно.

Тесты

Тесты — не панацея. Наличие тестов не гарантирует, что программа работает правильно.

Все, что дает тестирование после приложения достаточных усилий, — это уверенность, что программа действует достаточно правильно.

Парадигмы программирования

Парадигмы программирования не добавляют нам новых возможностей, а что‑то запрещают, говорят о том, чего не стоит делать. Эти запреты позволяют строить более надёжные программы, которые легко адаптировать к новым требованиям.

Структурное программирование

Накладывает ограничение на прямую передачу управления. СП ознаменовалось отказом от безусловных переходов (go to) в пользу условных операторов и циклов.

Методология структурного программирования появилась как следствие усложнения программного обеспечения — неструктурированная разработка порождала программы, которые было сложно поддерживать.

ООП

ООП вовсе не про инкапсуляцию (ее можно организовать через заголовочные файлы в C, или через замыкания в JavaScript), не про про наследование и не про полиморфизм (обеспечить полиморфное поведение можно имея в распоряжении только функции), а про инверсию зависимостей. ООП накладывает ограничение на косвенную передачу управления.

Функциональное программирование

Главный принцип функционального программирования — запрет за изменение значений. Программу, данные в которой не меняются, легче понимать. Функциональное программирование накладывает ограничение на присваивание. Кроме этого ФП предлагает event sourcing — подход, когда хранится не состояния, а транзакции (переходы между состояниями).

SOLID

Принципы SOLID определяют, как функции и структуры данных объединять в сущности, и как эти сущности взаимодействуют друг с другом.

Использование этих принципов позволяет повысить вероятность того, что программист создаст систему, которую будет легко поддерживать и расширять в течение долгого времени.

Single Responsibility Principle

Программисты часто неправильно понимают суть этого принципа и считают, что он про ситуацию, когда «каждый модуль отвечает за что-то одно». На самом же деле, этот принцип про то, что только у одной группы заинтересованных лиц должна быть причина изменять модуль.

Часто при нарушении принципа единственной ответственности в репозитории образовываются мердж-конфликты — это индикатор того, что в коде есть проблемы. Кроме этого, нарушение SRP чревато разрушением системы в тех местах, которые не имеют прямого отношения к непосредственно изменяемому компоненту.

Соблюдать принцип единственной ответственности помогает TDD, а также паттерны «Выделение класса» и «Фасад».

Open Closed Principle

Программные сущности должна быть открыты для расширения и закрыты для изменения.

«Открытость для расширения» означает, что поведение сущности может быть расширено путём создания новых типов сущностей.

«Закрытость для изменения» говорит о важности проектирования системы таким образом, чтобы при добавления нового функционала количество изменений в существующем коде стремилось к нулю.

Liskov Substitution Principle

Принцип заключается в том, что если B является подтипом типа A, то тогда все объекты типа A в программе могут быть безболезненно заменены объектами типа B. Иными словами, код должен иметь возможность работать с любым подтипом, так будто это базовый тип.

Классический пример нарушения принципа LSP — наследование класса Square от класса Rectangle (определяющим методы setHeight и setWidth). Квадрат, расширяющий класс прямоугольника, не получится использовать как прямоугольник из-за того, что стороны квадрата равны и не могут задаваться отдельно.

Interface Segregation Principle

Принцип разделения интерфейсов говорит о том, что программные сущности не должны зависеть от методов, которые они не используют.

На практике это значит, что нужно разбивать «толстые» интерфейсы на более мелкие, лучше удовлетворяющие потребностям конкретных сущностей.

Dependency Inversion Principle

Лучше не зависеть от деталей, потому что они нестабильны. Абстракции меняются реже конкретных реализаций.

Применяя этот принцип, одни модули можно легко заменять другими посредством замены модуля зависимости. В такой ситуации перемены в низкоуровневом модуле не повлияют на высокоуровневый.

Разумеется, полностью соблюсти этот принцип для всех не получится — некоторые сущности будут знать о конкретной реализации. Лучше, чтобы о реализациях знало минимальное число модулей.

Компоненты

Компоненты — это единицы развёртывания. Они представляют наименьшие сущности, которые можно развертывать в составе системы.

  • Классы и модули компонента должны выпускаться вместе и иметь общую цель использования, применяться для решения конкретной задачи.
  • В один компонент должны включаться классы, которые меняются по одним причинам и в одно время (смотри Open Closed Principle).
  • Нельзя допускать зацикленности в графе зависимостей компонента. Если в зависимостях есть цикл, его можно разорвать с помощью принципа инверсии зависимостей.

Принцип стабильных зависимостей

Зависимости должны быть направлены в сторону устойчивости. Некоторые компоненты должны быть более изменяемыми, но важно, чтобы менее стабильные компоненты всегда зависели от более стабильных.

Нестабильность = Кол‑во выходов / (Кол‑во входов + Кол‑во выходов)

Принцип стабильности абстракций

Компонент должен быть настолько же абстрактным, насколько он стабилен.

Абстрактность = Кол‑во абстрактных классов и интерфейсов в компоненте / Общее количество классов в компоненте

Границы

Границы должны отделять сущности, которые имеют значение для бизнес‑логики, от тех, которые не имеют. Например, бизнес‑логика не должна зависеть ни от схемы БД, ни от языка запросов.

Чистая архитектура

  • Сущности инкапсулируют критичные бизнес‑правила.
  • Юзкейсы содержат специфические для приложения правила.
  • Адаптеры интерфейсов конвертируют данные из формата, удобного для юзкейсов, в формат удобный для внешних слоёв.

Признаки чистой архитектуры

  • Не зависит от фреймворков. Грамотная архитектура у проекта — та, при которой выбор фреймворка становится настолько неважным, что это решение можно откладывать до самого последнего момента.

  • Не зависит от пользовательского интерфейса, базы данных и каких-либо внешних агентов. Бизнес‑логике не важно, какую мы используем базу данных, будем ли мы доставлять данные через веб или иначе, она не зависит от устройства, на котором будет работать система и т.д.

  • Легко тестируется. Если тесты сильно связаны с компонентами, то небольшое изменение может уронить сотни тестов.

About

Конспект книги «Чистая архитектура»

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published