Вы находитесь на странице: 1из 5

Объектно-ориентированное программирование (ООП) – это набор основных концепций

(абстракция, инкапсуляция, наследование, полиморфизм), конструкций (классы, методы) и


принципов.
Принципы ООП (объектно ориентированного программирования) — это парадигмы на
которых базируется подход в основе которого лежит объектная модель.
Объект — это совокупность характеристик и поведений, которое соответствует некой
сущности. Чтобы создать объект в программе, нужно описать шаблон для этого объекта,
который называется классом. Объекты создаются на основе уже существующих классов.
Характеристики объекта в классе описываются в виде переменных, которые называются
полями(свойствами).
Поведение объекта в классе описывается функциями, которые называются методами.

Базовые принципы ООП (основная концепция ООП):


Абстракция — отделение концепции от ее экземпляра. Это модель некоего объекта или
явления реального мира, в которой опущены незначительные детали, не играющие
существенной роли в данном контексте.
Наследование — способность объекта или класса базироваться на другом объекте или
классе. Это возможность создания новых классов на основе существующих. Это главный
механизм для повторного использования кода. Наследственное отношение классов четко
определяет их иерархию;
Инкапсуляция — размещение одного объекта или класса внутри другого для
разграничения доступа к ним. Это способность объектов скрывать часть своего состояния и
поведения от других объектов, предоставляя внешнему миру только определённый
интерфейс взаимодействия с собой.
Полиморфизм — реализация задач одной и той же идеи разными способами. Это
способность программы выбирать различные реализации при вызове операций с одним и
тем же названием (абстрактный метод).

Используйте следующее вместе с наследованием:


Делегация — перепоручение задачи от внешнего объекта внутреннему;
Агрегация — включение объектом-контейнером ссылки на объект-содержимое; при
уничтожении первого последний продолжает существование. Это специализированная
разновидность ассоциации, которая описывает отношения один-ко-многим, многие-ко-
многим, часть-целое между несколькими объектами, тогда как ассоциация устанавливает
связь только между двумя объектами.
Композиция — включение объектом-контейнером объекта-содержимого и управление
его поведением; последний не может существовать вне первого. Это более строгий вариант
агрегации, когда один объект состоит из других. Особенность этого отношения заключается в
том, что компонент может существовать только как часть контейнера.

SOLID
Принцип единственной обязанности /Single Responsibility Principle
Для каждого класса должно быть определено единственное назначение. Все ресурсы,
необходимые для его осуществления, должны быть инкапсулированы в этот класс и
подчинены только этой задаче.

Принцип открытости/закрытости /Open-Closed Principle


Программные сущности должны быть открыты для расширения, но закрыты для
изменений.

Принцип подстановки Барбары Лисков/Liskov Substitution Principle (LSP)


Методы, использующие некий тип, должны иметь возможность использовать его
подтипы, не зная об этом.

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


Предпочтительнее разделять интерфейсы на более мелкие тематические, чтобы
реализующие их классы не были вынуждены определять методы, которые непосредственно в
них не используются.

Принцип инверсии зависимостей/Dependency Inversion Principle (DIP)


Система должна конструироваться на основе абстракций «сверху вниз»: не абстракции
должны формироваться на основе деталей, а детали должны формироваться на основе
абстракций.

Не повторяйся (Don’t repeat yourself — DRY)


Избегайте повторного написания кода, вынося в абстракции часто используемые задачи
и данные. Каждая часть вашего кода или информации должна находиться в единственном
числе в единственном доступном месте. Это один из принципов читаемого кода.

KISS (акроним для «Keep it simple, stupid» — «Делай проще, тупица») — принцип
проектирования, принятый в ВМС США в 1960.
Принцип KISS утверждает, что большинство систем работают лучше всего, если они
остаются простыми, а не усложняются. Поэтому в области проектирования простота должна
быть одной из ключевых целей, и следует избегать ненужной сложности.

YAGNI («You aren't gonna need it»; с англ. — «Вам это не понадобится») — процесс и
принцип проектирования ПО, при котором в качестве основной цели и/или ценности
декларируется отказ от избыточной функциональности, — то есть отказ добавления
функциональности, в которой нет непосредственной надобности.

GRASP (An General Responsibility Assignment Software Patterns) выделяет следующие


принципы-шаблоны:
1) Information Expert (Информационные эксперт) или просто эксперт – это скорее
ответственность. Экспертом может быть любой класс. Тут даже дело не в проектировании, а в
осведомленности. Зачем нам нужен информационный эксперт? Затем, что если объект
владеет всей нужной информацией для какой-то операции или функционала, то значить и
этот объект будет выполнять либо делегировать выполнение этой операции.
Итак рассмотрим пример. Есть некая система продаж. И есть класс Sale (продажа). Нам
необходимо посчитать общую сумму продаж. Тогда кто будет считать общую сумму по
продажам? Конечно же класс – Sales, потому что именно он обладает всей информацией
необходимой для этого.
2) Creator (Создатель) – суть ответственности такого объекта в том, что он создает другие
объекты. Сразу напрашивается аналогия с фабриками. Так оно и есть. Фабрики тоже имеют
именно ответственность – Создатель.
Но есть ряд моментов, которые должны выполнятся, когда мы наделяем объект
ответственность создатель:
1. Создатель содержит или агрегирует создаваемые объекты
2. Создатель использует создаваемые объекты
3. Создатель знает как проинициализировать создаваемый объект
4. Создатель записывает создаваемые объекты (эту штуку я до конце не понял на самом
деле)
3) Controller (Контроллер) - Уже где-то слышали, не правда ли? Controller или Контролер
– это объект-прослойка между UI логикой и предметной (бизнес) логикой приложения.
Создаем контроллер так чтобы все вызовы от UI перенаправлялись именно ему и
соответственно все данные UI тоже получает через него.
Напоминает MVC, MVP? Так и есть. Это по сути Presenter из MVP и контроллер из MVC.
Разница между MVC и MVP есть, но это касается только направлений вызовов, ну и это тему
естественно другой беседы.
Итак, котроллер отвечает на такой вопрос: “Как UI должен взаимодействовать с
доменной логикой приложения?” или просто “Как взаимодействовать с системой?”. Это чем
то напоминает фасад. Фасад тоже предоставляет облегченный доступ к целой подсистеме
объектов. Так и тут контроллер для UI своего рода фасад которые предоставляет доступ к
целой подсистеме бизнес логики.
4) Low Coupling (Слабая связанность) - Тоже известная штука. Low Coupling или Слабая
связанность. Если объекты в приложении сильно связанны то любой изменение приводит к
изменениям во всех связанных объектах. А это неудобно и порождает баги. Вот по-этому
везде пишут что необходимо чтобы код был слабо связан и зависел от абстракций.
Например если наш класс Sale реализует интерфейс ISale и другие объекты зависят
именно от ISale, т.е. от абстракции, то когда мы захотим внести изменения касательно Sale –
нам нужно будет всего лишь подменить реализацию.
Low Coupling встречается и в SOLID принципах в виде – Dependency Injection. Сейчас
можно часто услышать такой принцип. Но суть остается прежней: “Программируйте на основе
абстракций (интерфейс, абстрактный класс и т.п.), а не реализаций”.
5) High Cohesion (Высокая сцепленность) – это соотносится к слабой связанности, они
идут в паре и одно всегда приводит к другому. Это как инь и янь, всегда вместе. Дело в том
что наши классы когда мы их задумываем имеют какую-то одну ответственность (Single
resposibility principle), например Sale(продажа) обладает всеми ответственностями которые
касаются продаж, например как мы уже говорили вычисление общей суммы – Total. Но
давайте представим что мы совершили оплошность и привнесли в Sale еще такую
ответственность как Payment (платеж). Что получится? Получится что одни члены класса
которые касаются Sale буду между собой достаточно тесно связанны, и также членные класса
которые оперируют с Payment между собой будут тесно связаны, но в целом сцепленность
класса SaleAndPayment будет низкой, так как по сути мы имеем дело с двумя обособленными
частями в одном целом. И резонно будет провести рефакторинг и разделить класс
SaleAndPayment на Sale и Payment, которые внутри будут тесно связанны или по другому
сцеплены.
Так что высокая сцепленность это как мера того что мы не нарушаем single resposibility
principle . Об этом говорит сайт https://intellect.icu . Вернее сказать, выскоая сцепленность
получается в результате соблюдения такого приципа из SOLID как single resposibility principle
(SRP).
Основной вопрос на который дает ответ высокая сцепленность – “Как поддерживать
объекты сфокусированными на одной ответственности, понятными, управляемыми и как
побочный эффект иметь слабо связанный код?”. Их разделять. Подробнее это описано в 17
главе книги Лармана.
6)Pure Fabrication (Чистая выдумка или чистое синтезирование). Суть в выдуманном
объекте. Такой себе принцип-хак. Но без него никак. Аналогом может быть шаблон
Service(сервис) в парадигме DDD.
Иногда, сталкиваемся с таким вопросом: “Какой объект наделить ответственностью, но
принципы информационный эксперт, высокая сцепленность не выполняются или не
подходят?”. Использовать синтетический класс который обеспечивает высокую сцепленность.
Тут без примера точно не разобраться.
Итак – ситуация. Какой класс должен сохранять наш объект Sale в базу данных? Если
подчиняется принципу “информационный эксперт”, то Sale, но наделив его такой
ответственностью мы получаем слабую сцепленность внутри него. Тогда можно найти выход,
создав синтетическую сущность – SaleDao или SaleRepository, которая будет сильно сцеплена
внутри и будет иметь единую ответственность – сохранять Sale в базу.
Так как мы выдумали этот объект а не спроектировали с предметной области, то и он
подчиняется принципу “чистая выдумка”.
7)Indirection (Посредник.) Можно столкнутся с таким вопросом: “Как определить
ответственность объекта и избежать сильной связанности между объектами, даже если один
класс нуждается в функционале (сервисах), который предоставляет другой класс?”
Необходимо наделить ответственностью объект посредник.
Например возвратимся опять же MVC. UI логике на самом деле нужен не контроллер, а
модель, доменная логика. Но мы не хотим? чтобы UI логика была сильно связанна с моделью,
и возможно в UI мы хотим получать данные и работать с разной предметной логикой. А
связывать UI слой с бизнес логикой было бы глупо, потому что получим код который будет
сложный для изменений и поддержки. Выход – вводим контроллер как посредника между
View и Model.
Так что распределяйте ответственности своим объектам ответственно (с умом).
8)Protected Variations (Сокрытие реализации или защищенные изменения). Как
спроектировать объекты, чтобы изменения в объекте или объекта не затрагивали других? Как
избежать ситуации когда меняя код объекта придется вносить изменения в множество других
объектов системы?
Кажется мы такое обсуждали уже. И пришли к выводу что нужно использовать low
coupling или dependency injection. Именно! Но суть в принципа немного в другом. Суть в том
чтобы определить “точки изменений” и зафиксировать их в абстракции (интерфейсе). “Точки
изменений” – не что иное как наши объекты, которые могут меняться.
То есть суть в принципа, чтобы определить места в системе, где поведение может
изменится и выделить абстракцию, на основе которой и будет происходить дальнейшее
программирование с использованием этого объекта.
Все это делается для того чтобы обеспечить устойчивость интерфейса. Если будет много
изменений связанных с объектов, он, в таком ключе, считается не устойчивым и тогда нужно
выносить его в абстракцию от которой будем зависеть, либо распределять обязанности и
ответственность в код иным образом
9) Polymorphism (Полиморфизм). Тоже знакомо, не так ли? Так вот это об том же
полиморфизме, который мы знаем из ООП. Если заметить то достаточно много паттернов GoF,
да и вообще паттернов, построено на полиморфизме. Что он дает?Он дает возможность
трактовать однообразно разные объекты с одинаковым интерфейсом (спецификацией).
Давайте вспомним такие паттерны как Strategy, Chain of Resposibility, Command… – их много. И
все по своей суть основываются на полиморфизме.
Полиморфизм решает проблему обработки альтернативных вариантов поведения на
основе типа. Тут яркий пример это шаблон GoF – Strategy (Стратегия).
Например, для реализации гибкого функционала для шифрования можно определить
интерфейс IEncryptionAlgorithm с методом Encrypt, и объект создатель, который вернет
IEncryptionAlgorithm, создав внутри себя актуальную реализацию этого интерфейса.

Создание в производном классе метода с таким же именем что и имя метода


родительского класса, называется переопределением метода. Суть переопределения метода
— производный класс в переопределяемом методе делает похожее, но отличающееся
действие, чем действие метода родительского класса.

Интерфейс (interface) - представляет собой обычный абстрактный класс, но только в нем


не может быть свойств, и, конечно, не определены тела методов. Фактически некоторый
интерфейс указывает лишь список методов, их аргументы и модификаторы доступа (обычно
только protected и public). Допускается также описание констант внутри интерфейса
(ключевое слово const).
Класс, реализующий некоторый интерфейс, обязан содержать в себе определения всех
методов, заявленных в интерфейсе. Это объясняет, почему в мире ООП интерфейс часто
называют контрактом: любой класс, "подписавшись в контракте", обязуется "выполнять" его
"условия". Если хотя бы один из методов не будет реализован, вы не сможете создать объект
класса: возникнет ошибка.
Главное достоинство интерфейсов заключается в том, что класс может реализовывать
интерфейсы независимо от основной иерархии наследования. Более того, класс может
реализовывать сразу несколько интерфейсов.

Начиная с версии 5.4, в PHP введен дополнительный инструмент для повторного


использования кода в классах — трейты. В отличие от интерфейсов, трейты содержат не
абстрактные методы, а общие фрагменты классов.

Вам также может понравиться