This repository includes the most valuable quotes (in my mind) from "Clean Architecture: A Craftsman's Guide to Software Structure and Design" book by Robert C. Martin.
All rights are reserved by Robert C. Martin and publisher "Piter".
Main language is Russian 🇷🇺
Quotes from next sections were presented:
- Introduction
- What Is Design and Architecture
- Structured Programming
- Functional Programming
- SRP: The Single Responsibility Principle
- OCP: The Open-Closed Principle
- DIP: The Dependency Inversion Principle
- Component Cohesion
- Component Coupling
- What Is Architecture
- Independence
- Screaming Architecture
- The Clean Architecture
- Services: Great and Small
- Clean Embedded Architecture
- Frameworks Are Details
- Architecture Archaeology
- Аfterword
Если вы думаете, что хорошая архитектура стоит дорого, попробуйте плохую архитектуру.
Разработчики верят в известную ложь: "Мы сможем навести порядок потом, нам бы только выйти на рынок!" В результате порядок так и не наводится, потому что давление конкуренции на рынке никогда не ослабевает. Выход на рынок означает, что теперь у вас на хвосте висят конкуренты и вы должны стремиться оставаться впереди них и бежать вперед изо всех сил.
Самонадеянность, управляющая перепроектированием, приведет к тому же беспорядку, что и прежде.
Однажды Дейкстра сказал: "Тестирование показывает присутствие ошибок, а не их отсутствие". Иными словами, тестированием можно доказать неправильность программы, но нельзя доказать ее правильность. Все, что дает тестирование после приложения достаточных усилий - это уверенность, что программа действует достаточно правильно.
Регистрация событий (event sourcing) - это стратегия, согласно которой сохраняются транзакции, а не состояния. Когда требуется получить состояние, мы просто применяем все транзакции с самого начала.
Принцип единой ответственности требует разделять код, от которого зависят разные акторы.
Если компонент A требуется защитить от изменений в компоненте B, компонент B должен зависеть от компонента A.
Транзитивные (переходящие) зависимости нарушают общий принцип, согласно которому программные сущности не должны зависеть от того, что они не используют непосредственно.
Принцип инверсии зависимостей (Dependency Inversion Principle; DIP) утверждает, что наиболее гибикими получаются системы, в которых зависимости в исходном коде направлены на абстракции, а не на конкретные реализации. Это правило действует и для языков с динамической системой типов. Исходный код не должен зависеть от модулей с конкретной реализацией. Однако в этих языках труднее определить, что такое конкретный модуль. В частности, это любой модуль, в котором реализованы вызываемые функции.
Все зависимости в исходном коде должны пересекать границу в одном направлении - в сторону абстракции.
Собирайте вместе все, что изменяется по одной причине и в одно время. Разделяйте все, что изменяется в разное время и по разной причине.
Эквивалентность повторного использования (REP) - объединение для удобства пользователей. Принцип согласованного изменения (CCP) - объединение для удобства сопровождения. Принцип повторного использования (CRP) - разделение для устранения лишних выпусков.
На ранних этапах разработки проекта принцип CCP намного важнее, чем REP, удобство разработки важнее удобства повторного использования.
Зависимости должны быть направлены в сторону устойчивости.
Метрики устойчивости: число входящих зависимостей, количество исходящих зависимостей.
Цель формы - упростить разработку, развертывание и сопровождение программной системы, содержащей ее. Главная стратегия такого упрощения в том, чтобы как можно дольше иметь как можно больше вариантов.
Разные организации коллективов разработчиков предпочитают разные архитектурные решения. С одной стороны, маленькая команда из пяти разработчиков может эффективно развивать монолитную систему без четкого определения границ между компонентами или интерфейсами. Фактически на ранних этапах разработки такая команда может посчитать архитектурные рамки чем-то вроде препятствия. Вероятно, в этом заключается причина, почему многие системы имеют плохую архитектуру: их архитектура не была продумана с самого начала, потому что разработчиков было немного и они не желали отвлекаться на создание общей архитектуры.
Чем дольше вы сможете откладывать конкретные решения, тем большим объемом информации вы будете обладать, чтобы сделать правильный выбор.
Архитектура должна поддерживать разнообразие вариантов использования. Добавление новых use cases не должно оказывать влияние на имеющиеся.
Есть разные виды дублирования. Есть истинное дублирование, когда любое изменение в одной копии требует того же изменения во всех остальных копиях. А есть ложное или случайное дублирование. Если два фрагмента кода, кажущиеся одинаковыми, развиваются разными путями - если они изменяются с разной скоростью и по разным причинам - этот случай не является истинным дублированием. Вернитесь к ним через несколько лет, и вы увидите, что они совершенно не похожи друг на друга.
Хорошая архитектура защищает большую часть исходного кода от изменений. Она оставляет режим разделения открытым, поэтому для крупнмасштабных вариантов развертывания может использоваться один режим, а для мелкомасштабных - другой.
Представьте, что перед вами чертежи здания. Они подготовлены архитектором и представляют собой планы здания. О чем они вам говорят? Если это чертежи коттеджа, вы неаверняка увидите на них парадный вход, вестибюль, ведущий в гостинную и, может быть, в столовую. Рядом со столовой, скорее всего, будет расположена кухня. Рядом с кухней, вероятно, будет малая столовая и где-то поблизости - общая комната. При рассмотрении этих планов у вас не возникнет сомнений, что вы видите коттедж для одной семьи. Архитектура как бы кричит: "Это коттедж". А теперь представьте, что вы рассматриваете архитектуру библиотеки. Вы наверняка увидите центральный вход, места для размещения библиотекарей, читальные залы, небольшие конференц-залы и галереи для хранения книг. Архитектура кричит: "Это библиотека". А что кричит архитектура вашего приложения? Увидев высокоуровневую структуру каталогов и пакетов с исходным кодом, услышите ли вы, как она кричит: "Это медицинская система", или "Это система учета", или "Это система управления складским хозяйством"? Или вы услышите: "Rails" или "Spring/Hebirnate", или "ASP"?
Архитектуры не связанаы (и не должны быть связаны) с фреймворками. Архитектура не должна определяться фреймворками. Фреймворки - это инструменты, а вовсе не аспекты, определяющие черты архитектуры. Если ваша архитектура опирается на фреймворки, она не сможет опираться на варианты использования.
Ничто во внутреннем круге ничего не знает о внешних кругах. Точно так же форматы данных, объявленные во внешних кругах, не должны использоваться во внутренних, особенно если это форматы генерируются фреймворком во внешнем круге.
Системы, разделенные на сервисы по функциональному признаку очень уязвимы для новых особенностей, пересекающих все функциональные уровни.
Несмотря на то, что программное обеспечение не изнашивается, оно может быть разрушено неуправляемыми зависимостями от микропрограмм и оборудования.
Сначала заставьте его работать. Затем перепишите его правильно. Затем заставьте его работать быстро.
Большинство авторов фреймворков предлагают результаты своего труда бесплатно, потому что хотят быть полезными для сообщества. Они хотят внести свой вклад. Это похвально. Однако, независимо от благородства мотивов, авторы не думают о ваших интересах. И не могут думать, потому что они не знают ни вас, ни ваших проблем. Но они знают свои проблемы и проблемы своих коллег и друзей. И они пишут свои фреймворки для решения этих проблем, а не ваших. Конечно, ваши проблемы, скорее всего, частично будут совпадать с этими другими проблемами. Иначе фреймворки не были бы столь популярны. Поэтому фреймворки могут быть очень полезными - в той мере, в какой существует совпадение.
Риски фреймворков. Фреймворки часто не отличаются особой чистотой. Фреймворк может помочь с реализацией первых возможностей приложения, однако, достигнув некоторого уровня зрелости, ваш продукт перерастет фреймворк. Фреймворк может развиваться в направлении, бесполезном для вас. Может появиться новый, более удачный фреймворк.
Нельзя создать универсальную инфраструктуру, не создав прежде работающую инфраструктуру. Универсальные инфраструктуры должны создаваться одновременно с несколькими приложениями, использующими их.
Написание работоспособного кода, который не мешает будущему коду - умение нетривиальное.