[Программирование, Проектирование и рефакторинг] Чистая архитектура. Часть III — Принципы дизайна
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Эта серия статей – вольный и очень краткий пересказ книги Роберта Мартина (Дяди Боба) «Чистая Архитектура», выпущенной в 2018 году. Предыдущая часть здесь.Принципы дизайнаПринципы SOLID говорят нам, как нам соединять наши функции и данные в классы, и как эти классы должны быть взаимосвязаны. То есть эти принципы относятся к уровню модулей (mid-level). Однако они также применимы и к уровню компонентов (high-level архитектура).Принципы SOLID зародились в конце 80-х и стабилизировались в начале 2000-х.SRP: Принцип единственной ответственностиИсторически этот принцип был сформулирован так: модуль должен иметь одну и только одну причину для изменения.Однако Дядя Боб предлагает другую, более точную формулировку: модуль должен быть ответственным за одного и только за одного актёра.Модуль – это некоторое связанное множество функций и структур данных.Пример нарушения принципа: класс Employee с тремя методами calculatePay(), reportHours(), save(). Все эти три метода относятся к разным актёрам. calculatePay() – это бухгалтерия, reportHours() – это отдел кадров, save() – это администратор базы данных. Если один из актёров просит внести изменения в свой метод, то это может сломать логику других методов. Также это вносит трудности при слиянии изменений от разных актёров.Решение проблемы – вынести функции в отдельные классы. В каждом классе будут только та логика, которая относится к соответствующему актёру.OCP: Принцип открытости/закрытостиПрограммный артефакт должен быть открытым для расширения, но закрытым для изменения.Простыми словами: артефакт должен быть расширяемым без необходимости изменения его кода.Этот принцип очень важен для архитектурных компонент.Пример: финансовый отчёт умеет отображаться на веб-странице. Теперь клиент просит печатать его на чёрно-белом принтере. Если OCP выполняется, то доля кода, которого придётся изменить, будет близка к нулю. Чтобы этого достичь, компонент представления отчётов должен быть защищённым от изменения, а для этого он должен зависеть не от конкретной реализации это представления, а от интерфейса. Далее конкретные компоненты будут добавляться путём расширения, т.е. имплементации интерфейса.Компоненты, которые находятся на более высоких уровнях иерархии зависимостей, должны быть защищены от изменений в компонентах более низкого уровня.Проявлением нарушения OCP является также зависимость от вещей, которые не используются.LSP: Принцип подстановки ЛисковПринцип замещения: если S является подтипом T, тогда объекты типа T в программе могут быть замещены объектами типа S без каких-либо изменений желательных свойств этой программы.Другими словами, все реализации интерфейса должны строго соответствовать контракту, описанном в этом интерфейсе.Пример нарушения LSP: классическая проблема квадрата/прямоугольника.Пример более высокоуровневого нарушения LSP: агрегатор сервисов такси, где в одном из сервисов название одного из параметров REST-запроса отличается от остальных. Тогда добавление этого сервиса приведёт к нарушению работы всего агрегатора. Эту проблему можно решить, например, путём вынесения маппинга параметров во внешнюю БД.ISP: Принцип разделения интерфейсаПрограммные сущности не должны зависеть от методов, которые они не используют.Толстые интерфейсы нужно разделять на более мелкие, чтобы сущности знали только о тех методах, которые необходимы им в работе.В динамических языках меньше деклараций зависимостей, поэтому они подвержены этой проблеме меньше. Однако ISP распространяется и на более высокий уровень, где он означает, что не должно быть зависимостей от компонент, которые содержат слишком много лишнего. Например, зависимость от фреймворка, который тянет за собой специфичную базу данных. Изменения в этой базе данных приводят к необходимости редеплоя всего компонента.DIP: Принцип инверсии зависимостейПрограммные сущности должны зависеть от абстракций, не от деталей.В Java это значит, что модули должны зависеть от интерфейсов или абстрактных классов.Однако существуют платформенные классы, которые являются чрезвычайно стабильным, например, java.lang.String. На такие классы этот принцип не распространяется. С другой стороны, есть наша система, в которой есть много часто изменяемых классов. Для них этот принцип нужно соблюдать.Абстракции должны быть стабильными. Нужно делать зависимости от них, а не от их конкретных реализаций, которые могут меняться слишком часто.Не рекомендуется наследоваться от часто изменяемых классов.Как создавать инстансы конкретных классов, если мы не можем от них зависеть? Для этого есть несколько решений:
- Шаблон Абстрактная Фабрика
- Контейнеры, которые сами внедряют зависимости (XML, аннотации)
- Сервисы
В дальнейшем к принципу DIP мы будем обращаться чаще, чем к остальным принципам, потому что он диктует нам важнейшее правило построения грамотной архитектуры: Правила Зависимостей.Продолжение следует...
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, C] Чем сложна демонизация POSIX (перевод)
- [Python, Программирование, Учебный процесс в IT, DevOps] Python for Ops, разработчикам вход воспрещён
- [Программирование, C++, C, Разработка под Linux] Приёмы неблокирующего программирования: введение в compare-and-swap (перевод)
- [Программирование, Java, Компиляторы] Передача и вызов лямбд на сервере и отказаться от docker/deploy/…
- [Программирование, Haskell, Функциональное программирование, Rust] Как мы выбираем языки программирования в Typeable
- [Программирование, C++, Работа с 3D-графикой, Разработка игр, CGI (графика)] Vulkan. Руководство разработчика. Непрограммируемые стадии конвейера (перевод)
- [Программирование, C#, Unity] Немного о графиках, сплайнах и генерации ландшафта
- [Программирование, Проектирование и рефакторинг] Чистая архитектура. Часть II — Парадигмы программирования
- [Программирование, Алгоритмы, Математика] Вебинар от Яндекс.Практикума «Конечные автоматы в реальной жизни»: теория, кодинг и Q&A за один вечер
- [Занимательные задачки, Программирование, Алгоритмы, Node.JS, VueJS] Создаем кэшируемую пагинацию, которая не боится неожиданного добавления данных в БД
Теги для поиска: #_programmirovanie (Программирование), #_proektirovanie_i_refaktoring (Проектирование и рефакторинг), #_arhitektura (архитектура), #_proektirovanie (проектирование), #_djadja_bob (дядя боб), #_robert_martin (роберт мартин), #_programmirovanie (
Программирование
), #_proektirovanie_i_refaktoring (
Проектирование и рефакторинг
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:09
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Эта серия статей – вольный и очень краткий пересказ книги Роберта Мартина (Дяди Боба) «Чистая Архитектура», выпущенной в 2018 году. Предыдущая часть здесь.Принципы дизайнаПринципы SOLID говорят нам, как нам соединять наши функции и данные в классы, и как эти классы должны быть взаимосвязаны. То есть эти принципы относятся к уровню модулей (mid-level). Однако они также применимы и к уровню компонентов (high-level архитектура).Принципы SOLID зародились в конце 80-х и стабилизировались в начале 2000-х.SRP: Принцип единственной ответственностиИсторически этот принцип был сформулирован так: модуль должен иметь одну и только одну причину для изменения.Однако Дядя Боб предлагает другую, более точную формулировку: модуль должен быть ответственным за одного и только за одного актёра.Модуль – это некоторое связанное множество функций и структур данных.Пример нарушения принципа: класс Employee с тремя методами calculatePay(), reportHours(), save(). Все эти три метода относятся к разным актёрам. calculatePay() – это бухгалтерия, reportHours() – это отдел кадров, save() – это администратор базы данных. Если один из актёров просит внести изменения в свой метод, то это может сломать логику других методов. Также это вносит трудности при слиянии изменений от разных актёров.Решение проблемы – вынести функции в отдельные классы. В каждом классе будут только та логика, которая относится к соответствующему актёру.OCP: Принцип открытости/закрытостиПрограммный артефакт должен быть открытым для расширения, но закрытым для изменения.Простыми словами: артефакт должен быть расширяемым без необходимости изменения его кода.Этот принцип очень важен для архитектурных компонент.Пример: финансовый отчёт умеет отображаться на веб-странице. Теперь клиент просит печатать его на чёрно-белом принтере. Если OCP выполняется, то доля кода, которого придётся изменить, будет близка к нулю. Чтобы этого достичь, компонент представления отчётов должен быть защищённым от изменения, а для этого он должен зависеть не от конкретной реализации это представления, а от интерфейса. Далее конкретные компоненты будут добавляться путём расширения, т.е. имплементации интерфейса.Компоненты, которые находятся на более высоких уровнях иерархии зависимостей, должны быть защищены от изменений в компонентах более низкого уровня.Проявлением нарушения OCP является также зависимость от вещей, которые не используются.LSP: Принцип подстановки ЛисковПринцип замещения: если S является подтипом T, тогда объекты типа T в программе могут быть замещены объектами типа S без каких-либо изменений желательных свойств этой программы.Другими словами, все реализации интерфейса должны строго соответствовать контракту, описанном в этом интерфейсе.Пример нарушения LSP: классическая проблема квадрата/прямоугольника.Пример более высокоуровневого нарушения LSP: агрегатор сервисов такси, где в одном из сервисов название одного из параметров REST-запроса отличается от остальных. Тогда добавление этого сервиса приведёт к нарушению работы всего агрегатора. Эту проблему можно решить, например, путём вынесения маппинга параметров во внешнюю БД.ISP: Принцип разделения интерфейсаПрограммные сущности не должны зависеть от методов, которые они не используют.Толстые интерфейсы нужно разделять на более мелкие, чтобы сущности знали только о тех методах, которые необходимы им в работе.В динамических языках меньше деклараций зависимостей, поэтому они подвержены этой проблеме меньше. Однако ISP распространяется и на более высокий уровень, где он означает, что не должно быть зависимостей от компонент, которые содержат слишком много лишнего. Например, зависимость от фреймворка, который тянет за собой специфичную базу данных. Изменения в этой базе данных приводят к необходимости редеплоя всего компонента.DIP: Принцип инверсии зависимостейПрограммные сущности должны зависеть от абстракций, не от деталей.В Java это значит, что модули должны зависеть от интерфейсов или абстрактных классов.Однако существуют платформенные классы, которые являются чрезвычайно стабильным, например, java.lang.String. На такие классы этот принцип не распространяется. С другой стороны, есть наша система, в которой есть много часто изменяемых классов. Для них этот принцип нужно соблюдать.Абстракции должны быть стабильными. Нужно делать зависимости от них, а не от их конкретных реализаций, которые могут меняться слишком часто.Не рекомендуется наследоваться от часто изменяемых классов.Как создавать инстансы конкретных классов, если мы не можем от них зависеть? Для этого есть несколько решений:
=========== Источник: habr.com =========== Похожие новости:
Программирование ), #_proektirovanie_i_refaktoring ( Проектирование и рефакторинг ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 09:09
Часовой пояс: UTC + 5