На этой неделе я столкнулся с некоторыми фундаментальными аспектами объектно-ориентированного программирования, которые я стремился включить в качестве строительных блоков моего подхода к решению задач этой недели.
Как говорит Роберт С. Мартин, автор книги Чистый код: руководство по гибкому программному мастерству:
Разрабатываете ли вы системы или отдельные модули, никогда не забывайте использовать самое простое, что может работать.
Среди наиболее интересных на данный момент — принцип единой ответственности, принцип открытости-закрытости и принцип инверсии зависимостей.
ТВЕРДЫЕ принципы
Единая ответственность, Открыто-закрыто, Замена Лискова, Разделение интерфейсов, Инверсия зависимостей.
Принцип единой ответственности (SRP)
Это много, чтобы принять во внимание, но суть SRP сводится к ограничению того, за что отвечают ваши классы и методы.
Принцип единственной ответственности (SRP) гласит, что у класса или модуля должна быть одна и только однапричина для изменения. Этот принцип дает нам как определение ответственности, так и ориентир для размера класса. У классов должна быть одна обязанность — одна причина для изменения.
(Чистый код: руководство по гибкому программному обеспечению, глава 10, стр. 138)
Каждый класс и метод должны иметь и должны знать о своей определенной, ограниченной роли. Возложение ответственности на класс Oystercard
за маршрут, в котором он находится (например, места, в которых он начинается и заканчивается), стоимость проезда, иистория путешествия — это не просто плохое программирование (или запах кода) это ненужное усложнение и надвигающаяся головная боль для нас и следующего человека, которому придется иметь дело с этой кодовой базой. Вместо этого мы придерживаемся более разрозненного подхода:
- Класс
Oystercard
, отвечающий за поддержание баланса при касании пользователем станции и выходе из нее; - Класс
Station
, который отслеживает названия и зоны станций; - Класс
Journey
, который заботится о станциях входа и выхода в путешествии; - Класс
Journey Log
, роль которого заключается в записи истории поездок; - Класс
Fare
, отвечающий за расчет стоимости проезда в зависимости от количества пройденных зон.
Принцип «открыто-закрыто» и инкапсуляция
Принцип открытости-закрытости утверждает, что классы или модули должны быть открыты для расширения, но закрыты для модификации.
Инкапсуляция важна, потому что она ограничивает область рассматриваемых методов или классов. Публичные методы получения и установки используются для управления характеристиками некоторых атрибутов класса, которые хранятся в закрытых методах.
Например, метод initialize
в этом фрагменте кода позволяет создать экземпляр новой карты Oyster с нулевым балансом. Преимущество хранения deduct(amount)
как частного метода заключается в том, что он ограничивает доступ, который вы предоставляете другим к этому методу. Это потенциально может уберечь вас от ошибок или недостатков, которые могут привести к списанию неправильной суммы с вашей карты.
Инверсия зависимостей и внедрение зависимостей
Принцип инверсии зависимости утверждает две вещи. Во-первых, модули высокого уровня не должны зависеть от модулей низкого уровня. Скорее, оба рассматриваемых модуля должны зависеть от абстракций. Во-вторых, абстракции не должны зависеть от деталей: детали должны зависеть от абстракций. В общем, как высокоуровневые, так и низкоуровневые объекты должны зависеть от одной и той же абстракции.
Инверсия контроля переносит второстепенные обязанности с объекта на другие объекты, предназначенные для этой цели, тем самым поддерживаяпринцип единой ответственности.
(Чистый код: руководство по Agile Software Craftsmanship, глава 11, стр. 157)
Чтобы поддержать принцип инверсии зависимостей, внедрение зависимостей — это метод, который переносит обязанности с создания экземпляров зависимостей на специальные методы, тем самым инвертируя управление.
Преимущества гибкого подхода
Следование приведенным выше принципам означает, что в конечном итоге код будет более гибким, поскольку внесение изменений в четко определенные, несвязанные классы означает, что небольшое изменение не нарушит всю программу. Кроме того, если в вашем коде где-то есть ошибка, будет легче определить, протестировать и устранить источник проблемы.
Я понимаю, что, хотя я все еще нахожусь на начальных этапах своего пути в программировании, может быть сложно уследить за всеми принципами SOLID за один раз, но я надеюсь, что благодаря постоянным итерациям эти принципы Agile станут второй натурой.