Чистая архитектура. Искусство разработки программного обеспечения. Роберт Мартин
Чтение книги онлайн.
Читать онлайн книгу Чистая архитектура. Искусство разработки программного обеспечения - Роберт Мартин страница 26
Решить поставленную задачу проще всего простым добавлением инструкции if в модуль, занимающийся пересылкой заказов:
if (driver.getDispatchUri(). startsWith("acme.com"))…
Конечно, ни один архитектор, дорожащий своей репутацией, не позволил бы добавить такую конструкцию в систему. Появление слова «acme» непосредственно в коде создает возможность появления самых разных неприятностей, не говоря уже о бреши в безопасности.
Например, представьте, что компания Acme добилась большого успеха, купила компанию Purple Taxi и объединенная компания решила сменить имя и адрес веб-сайта и объединить все системы оригинальных компаний. Получается, что теперь мы должны добавить еще одну инструкцию if для «purple»?
Архитектор должен изолировать систему от ошибок, подобных этой, и добавить модуль, управляющий созданием команд доставки заказов в соответствии с параметрами, указанным для URI в базе данных с настройками. Настройки могли бы выглядеть как-то так:
UPI
Acme.com
Формат команды
/pickupAddress/%s/pickupTime/%s/dest/%s
UPI
*.*
Формат команды
/pickupAddress/%s/pickupTime/%s/destination/%s
В результате архитектор вынужден добавить важный и сложный механизм из-за того, что интерфейсы не всех REST-служб оказались совместимыми.
Заключение
Принцип подстановки Барбары Лисков может и должен распространяться до уровня архитектуры. Простое нарушение совместимости может вызвать загрязнение архитектуры системы значительным количеством дополнительных механизмов.
10. Принцип разделения интерфейсов
Происхождение названия принципа разделения интерфейсов (Interface Segregation Principle; ISP) наглядно иллюстрирует схема на рис. 10.1.
Рис. 10.1. Принцип разделения интерфейсов
В данной ситуации имеется несколько классов, пользующихся операциями в классе OPS
. Допустим, что User1
использует только операцию op1
, User2
– только op2
и User3
– только op3
.
Теперь представьте, что OPS
– это класс, написанный на таком языке, как Java. Очевидно, что в такой ситуации исходный код User1
непреднамеренно будет зависеть от op2
и op3
, даже при том, что он не пользуется ими. Эта зависимость означает, что изменения в исходном коде метода op2
в классе OPS
потребуют повторной компиляции и развертывания класса User1
, несмотря на то что для него ничего не изменилось.
Эту проблему можно решить разделением операций по интерфейсам, как показано на рис. 10.2.
Рис. 10.2. Разделение операций
Если снова представить, что этот интерфейс реализован на языке со строгим контролем типов, таком как Java, исходный код User1
будет зависеть от U1Ops
и op1
, но не от OPS
. То есть изменения в OPS
, которые не касаются User1
, не потребуют повторной компиляции и развертывания User1
.
Принцип разделения интерфейсов и язык
Очевидно,