Десять принципов объектно-ориентированного дизайна, которые должен знать Java-программист

Десять принципов объектно-ориентированного дизайна, которые должен знать Java-программист


Принципы объектно-ориентированного дизайна (далее — ООД) — ядро объектно-ориентированного программирования (далее — ООП), но я вижу большинство Java-программистов, работающих с паттернами Singleton («Одиночка», например Singleton), «Декоратор» (Decorator) или «Наблюдатель» (Observer), и не уделяющих должного внимания изучению объектно-ориентированного анализа и дизайна. Конечно, важно изучать основы ООП: абстракция, инкапсуляция, полиморфизм и наследование, но, в то же время, не менее важно знать принципы дизайна, чтобы создавать хорошо структурированные и понятные продукты. Постоянно наблюдаю программистов, разработчиков различного уровня, которые или не слышали о принципах ООД SOLID, или просто не знают о преимуществах, которые тот или иной принцип дизайна дает, или как применить его в коде.

В итоге, всегда стремитесь к связности кода и хорошему дизайну в решении. Отличные примеры для изучения Java и ООД — открытый код Apache и Sun. Они демонстрируют, как принципы ООД должны использоваться в написании кода, в программах на Java. Иллюстрация применения паттернов в JDK: Factory, паттерн «фабрика» в классе BorderFactory, Что такое паттерн дизайна Factory..., паттерн Singleton, «одиночка», в классе Runtime RunTime, паттерн Decorator, «декоратор», в различных java.io классах. К слову, если вы заинтересованы практиковаться в java-коде, прочтите Effective Java, Joshua Bloch (например, Effective Java в переводе на русский), шедевр от автора Java API. Еще на тему ООД и паттернов рекомендую Head First Design Pattern (на русском Дизайны проектирования), а также Head First Object Oriented Analysis and Design (на английском OOAD). Эти книги помогут писать лучший код, используя преимущества принципов ООД.

Хотя лучший способ усвоить любые принципы — практиковаться и понимать последствия нарушения этих самых принципов, тема этой статьи — введение в принципы ООД для java-программистов, которые пока их не используют или только изучают язык. Я полагаю, каждый из озвученных принципов ООД (SOLID) достоин отдельной статьи с подробным объяснением сути, и я в дальнейшем постараюсь (написать эти статьи — прим. перев.), но сейчас приготовьтесь просто быстро пробежаться.

DRY (Не повторяйтесь)

Первым принципом обозначим «не повторяйтесь», что значит, не пишите повторяющегося кода, используйте принцип абстракции, обобщая простые вещи в одном месте. Если у вас присутствует один и тот же блок кода более, чем в двух местах, подумайте об отдельном методе для него. Если есть константа для многоразового использования, создайте глобальную переменную с модификаторами public final. Большим преимуществом использования данного принципа является легкость дальнейшей технической поддержки.
Важно также не злоупотреблять этим принципом, когда, к примеру, повторение кода существует не для самого кода, а для реализации функциональности. Например, когда вы проверяете OrderID и SSN, это не значит, что они идентичны или станут таковыми в будущем. Используя одинаковый код для двух разных функций или элементов, вы связываете их тесно, и когда OrderID поменяет формат, код проверки SSN перестанет работать. Имейте в виду такие связки и не комбинируйте все подряд, что использует схожий код, но на самом деле, не является связанным.

Инкапсулируйте то, что меняется

Одна вещь постоянна в мире программного обеспечения — изменение. Инкапсулируйте код, который в будущем будет меняться. Преимущество принципа в легкости тестирования и поддержки надлежащим образом инкапсулированного кода. При написании программ на java следуйте, по умолчанию, правилу создания переменных и методов с модификатором доступа private, расширяя доступ шаг за шагом, от private к protected, но не public. Несколько принципов дизайна java используют инкапсуляцию, паттерн Factory — хороший пример, где код создания объектов инкапсулирован и достаточно гибок, чтобы позже создавать новые объекты, но без воздействия на существующий код.

Открыто-закрытый принцип дизайна

Классы, методы, функции должны быть открыты для расширения (новой функциональности) и закрыты для модификации. Это отличный принцип из набора SOLID, соответствующий букве «О», предотвращающий изменение протестированного и работающего кода. Идеально, если вы добавляете новую функциональность только, когда ваш код должен тестироваться, и в этом цель этого принципа ООД.

Принцип уникальной ответственности (SRP)

SRP соответствует букве S в SOLID и означает, что не должно существовать более 1 причины для изменения класса, иными словами, класс должен обладать уникальной функциональностью. Если один класс java реализует 2 набора функций, их сцепление создает ситуацию, при которой изменение одного нарушит имеющееся сочетание, что потребует нового раунда тестирования во избежание сюрпризов при использовании программ.

Внедрение зависимостей (DI) или принцип инверсии управления (IOC)

Не просите зависимости, фреймворк вам её обеспечит. Этот принцип отлично реализован в фреймворке Spring. Прелесть принципа в том, что любой класс с внедренной зависимостью (DI, часть фреймворка Spring), легко тестировать с помощью объекта-муляжа и легко поддерживать, потому что код, создающий объект, инкапсулирован в фреймворке, и не смешивается с клиентским кодом. Существует множество способов внедрять зависимости, например, используя инструментарий в байт-коде от фреймворков аспектно-ориентированного программирования типа AspectJ или используя прокси, как в Spring. Посмотрите этот пример использования принципа DI & IOC, представляющего букву D в аббревиатуре SOLID.

Предпочитайте структуру наследованию

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

Принцип подстановки Лисков (LSP)

Согласно принципу LSP, буква L в SOLID, функции, которые используют ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом. LSP тесно связан с принципом уникальной ответственности и принципом разделения интерфейсов. Если у базового класса больше функциональности, чем у производного, такое соотношение нарушает принцип LSP. Чтобы следовать этому принципу, производный класс или подкласс должен расширять функциональность, а не сужать её.

Принцип разделения интерфейсов (ISP)

Данный принцип гласит, что класс не должен внедрять интерфейс (Что такое интерфейс в Java...), если интерфейс не используется. В основном, такое происходит, когда интерфейс многофункциональный, а класс требует только одной функциональности. Разработка интерфейсов — сложная работа, реализовав интерфейс, трудно изменить его без изменения всей реализации. Другое преимущество использования принципа ISP заключается в том, что интерфейс внедряет методы до того, как какой-либо класс может их использовать, поэтому уникальная функциональность требует внедрения меньшего количества методов.

Программирование для интерфейса, а не реализации

«Всегда программируйте для интерфейса, а не реализации.» Следование этому принципу приведет вас к гибкому коду, который сможет работать с любой новой реализацией интерфейса. Используйте переменные интерфейсного типа, методы с возвращаемым значением или методы с параметрами. Те же советы содержатся в Effective Java и книгах по ООД.

Принцип делегирования

Не делайте всё самостоятельно, поручите работу соответствующему классу. Хрестоматийный пример применения принципа делегирования — использование методов equals() и hashCode(). Для сравнения двух объектов мы поручаем классу самостоятельно сделать эту работу, вместо того, чтобы оставлять проверку клиентскому классу. Преимущество этого принципа в избежании двойного кода и легкости в изменении поведения.
Все изложенные принципы объектно-ориентированного дизайна помогут вам писать гибкий и лучший код, связный, но без лишних связок. Теория — первый шаг. Важнее всего развивать способность к анализу, где применимы эти принципы ООД. Следите, не нарушаете ли вы какой-либо из принципов, подвергая опасности гибкость кода. Вместе с тем, ничто не совершенно, невозможно всегда решать проблемы только применением принципов ООД в программировании. Они критичны, по большей части, для корпоративных решений, проектов с длинным циклом технической поддержки.

Оригинал статьи

6 комментариев

vps
  • vps
  • 0
По принципам S.O.L.I.D (на русском и с примерами) можно ещё почитать здесь.
Lam-lam
Спасибо за статью!
Но «design» здесь имхо лучше было перевести как «разработка»
tanzwud
почему вы так считаете?
Lam-lam
мне кажется, что в русском языке слово «дизайн» скорее ассоциируется с созданием визуальном среды
MaximAba
Вот тут презенташка красивая: Объектно-ориентированный дизайн
tempys
круть презентуха
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.