html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Твердые объектно-ориентированные принципы. SOLID


Снова у нас впереди серия постов про зияющие глубины ООП-программирования. На этот раз представляю первый пост из этой новой серии «Твердые объектно-ориентированные принципы».

Очередной зубодробительный пост на моём Блогераторе, так уж у нас повелось, что мы тут попеременно то веселимся, то думаем над чертовски серьёзными вещами.

Это перевод серии одноименных статей от  известного PHP-гуру, входящего в команду разработчиков Core PHP Team — Д. Кита Кейси (D. Keith Casey). И посвящен он важнейшим понятиям объектно-ориентированного дизайна — SOLID-принципам.

PHP oop ооп  объектно-ориентированное программирование

Хотелось бы верить, что известных понятий «слабая связность, высокая связность» достаточно, но когда вы действительно погружаетесь в эти концепции, вам становится ясно, что они носят скорее описательный, чем предписывающий характер.

Если вы хотите знать как применять их на практике изо дня в день в вашей разработке, вы должны будете погрузиться в SOLID-принципы, которые описывают 5 важных аспектов «хорошего» объектно-ориентированного дизайна.

Принцип единой ответственности

Во-первых, это принцип единой ответственности или SRP (Single Responsibility Principle).

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

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

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

В нашем образцовом открытом проекте web2project есть класс Link со следующими методами:

class CLink extends w2p_Core_BaseObject {
    public function __construct() { }
    public function loadFull(CAppUI $AppUI, $link_id) { }
    public function check() { }
    public function delete(CAppUI $AppUI) { }
    public function store(CAppUI $AppUI) { }
    public function hook_search() { }
}

На первый взгляд можно сказать, что большинство из этих методов реализуют обычные CRUD-операции и взаимодействуют непосредственно только с объектом CLink .

К сожалению, у нас есть еще один метод в данном классе:

public function getProjectTaskLinksByCategory _
(CAppUI $AppUI, $project_id = 0, $task_id = 0, _
$category_id = 0, $search = '') { }

Да, к сожалению, это настоящее имя метода... При взгляде на этот метод, одно лишь его имя уже говорит нам о том, как много всего здесь происходит.

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

Если эти объекты когда-нибудь изменятся, мы, в конце концов, придем к антипаттерну «shotgun surgery», когда маленькое изменение в одной части кода вызывает небольшие изменения повсюду.

Такой код болезненно поддерживать даже короткое время.

Принцип «Открыто/Закрыто»

Далее, существует еще один принцип: Открыто/Закрыто или OCP (Open/Closed Principle).

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

Возможно, вы слышали другую его формулировку: «Не хакай ядро». На практике этот принцип обеспечивается путем чрезвычайно избирательного использования ключевых слов «private» и «final».

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

Если вы размышляете, пометить ли что-либо как «private», остановитесь и переосмыслите свои цели. Вы просто пытаетесь ограничить использование сущности за пределами класса, или это действительно Единственно Верный Путь для выполнения вашей задачи?

Если первое, то возможно стоит использовать ключевое слово «protected». Это позволит расширить ваш класс и перегрузить методы в случае необходимости.

Принцип замещения Лискоу

Далее, у нас есть принцип замещения Лискоy или LSP (Liskov Substitution Principle) и, если честно, это наиболее сложная вещь для моего понимания.

Если коротко, то идея состоит в том, что объекты в данной иерархии классов могут быть заменены на их подтипы без нарушения корректности системы.

Примечания переводчика:

Есть также более строгие формулировки этого метода, например:

Формулировка № 1: eсли для каждого объекта o1 типа S существует объект o2 типа T, который для всех программ P определен в терминах T, то поведение P не измениться, если o1 заменить на o2 при условии, что S является подтипом T.

Формулировка № 2: подтипы должны быть заменяемы базовыми типами.

В характерных терминах это означает, что предопределенные условия метода/класса не могут быть усилены, постусловия не могут быть ослаблены, все возбуждаемые исключения должны быть в равной степени заменяемыми, и сигнатуры методов должны быть полностью совместимы.

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

Примечания переводчика:

Поясню на примере. Если для какой-нибудь функции родительского класса справедливо:

* пред-условие: item != null
* пост-условие: count = oldCount + 1

То для дочернего класса можно использовать:

* пред-условие: -
* пост-условие: count = oldCount + 1 && is_changed = true

Более подробно на моем блоге с этим принципом можно ознакомиться вот здесь.

Принцип разделения интерфейса

Следующая концепция это принцип разделения интерфейса или ISP (Interface Segregation Principle).

Формальное определение у него такое: много клиентских специфических интерфейсов лучше, чем один общий интерфейс.

Но с точки зрения непрофессионала, это намного проще. С течением времени и изменением требований наши системы растут. Без тщательного контроля наша иерархия классов растет и становится «грязной». Методы, которые имели смысл в начале проекта, не имеют такового в конце.

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

Взгляните на такой (надуманный) пример:

interface w2p_Interfaces_Authenticator {
    public function authenticate($username, $password);
    public function getUserId();
    public function userExists();
    public function changePassword();
}

Все эти методы связаны с пользовательской валидацией и аутентификацией, поэтому держать их вместе не лишено смысла. Объект, который будет расширять этот интерфейс, будет сильно связным, но посмотрите, например, на такой пример:

interface w2p_Interfaces_Modules_Setup {
    public function install();
    public function upgrade($old_version);
    public function configure();
    public function uninstall();
    public function changeDisplayOrder();
}

Первые 4 метода имеют смысл в интерфейсе Setup и описывают разумный жизненный цикл модуля. Последний метод имеет мало общего с установкой и скорее относится к уровню представления. Что-то здесь не так... Или, другими словами, у нас получился код «с запашком» (так называемый code smell).

Примечания переводчика:

Другая формулировка принципа: клиенты не должны зависеть от методов, которые они не используют

Принцип инверсии зависимостей

И наконец финальная концепция SOLID — принцип инверсии зависимостей или DIP (Dependency Inversion Principle).

В мире компьютерных наук его формальное определение такое: зависеть от абстракций, а не от деталей.

В реальном мере это означает, что когда мы определяем зависимости класса, мы должны расчитывать на максимально широкий спектр возможностей.

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

В web2project часть нашей структуры классов выглядит так:

abstract class w2p_Core_BaseObject {
    public function __construct($table, $key, $module = '') {}
    public function load($oid = null, $strip = true) {}
    public function store($updateNulls = false) {}
    public function check() { }
}
class CProject extends w2p_Core_BaseObject {
    public function __construct() { }
    // load is inherited
    public function store(CAppUI $AppUI) { }
    public function check() { }
}
class CLink extends w2p_Core_BaseObject {
    public function __construct() { }
    // load is inherited
    public function store(CAppUI $AppUI) { }
    public function check() { }
}

Т.к. у нас есть интерфесы, вместо того чтобы сделать наши контроллеры зависимыми от объектов CProject или CLink , мы можем взаимодействовать с w2p_Core_BaseObject например таким образом:

class w2p_Controllers_Base
{
    public function __construct(w2p_Core_BaseObject $object, $delete,
             $prefix, $successPath, $errorPath) { }
}

Наш контроллер может взаимодействовать с любым из этих объектов, и ему все равно какой объект использовать. Это мощный механизм, который позволяет многоразовое использование контроллеров в нашей системе.

PHP oop ооп  объектно-ориентированное программирование SOLID objects объекты принципы

SOLID принципы сами по себе не дадут вам прекрасный OO-дизайн. Существуют обоснованные причины и ситуации когда их лучше не использовать и обойти, но это должно быть осознанное решение, а не прихоть или незнание. У нас может быть собственное мнение о том, когда и где их лучше применять. Мы должны оценить, что с их помощью мы приобретаем и улучшаем.

Нельзя просто взять и отметить чекбокс: «теперь мы поддерживаем SOLID».

~

Продолжение этой статьи читаем здесь, а для всех тех, кто хочет углубиться в принципы SOLID правильно ощущая их великую важность, как всегда выдам прямые ссылки на хороший дополнительный материал по теме. Итак, ссылка раз (просто обалденный медиа-курс SOLID Principle Episodes), ну и более понятная для большинства ссылка два (SOLID: TOP-5 архитектурных принципов).

Также для закрепления темы хорошая презентация на русском:

Важно не забывать и про конкурирующие подходы, например читайте на нашем блоге про принципы GRASP. А пока ешьте больше шоколада (что как известно укрепляет мозг), ну а в перерывах, конечно же, читайте Блогератор.

Читать дальше
Twitter
Одноклассники
Мой Мир

материал с blogerator.ru

11

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • pleshner
          • домен blogerator.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции