За последние 24 часа нас посетили 8742 программиста и 457 роботов. Сейчас ищут 104 программиста ...

Понимание принципов SOLID

Тема в разделе "PHP для профи", создана пользователем voral, 7 июл 2020.

  1. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Перечитал/пересмотрел много мнений. Но про многих "авторов" я бы сказал "заставь дурака богу молиться он и лоб расшибет". Но в целом все в голове устаканилось (даже статью на хабре нашел где как резюме - все емко написано и соответствует моему пониманию в результате всех измышлений)

    Осталось только одно: Принцип единственной ответственности . Чтобы пояснить мои сомнения более-менее конкретно. Привожу прямо примеры из понравившейся статьи

    Автор предлагает по этом принципу из кода
    PHP:
    1. class Order
    2. {
    3.     public function calculateTotalSum(){/*...*/}
    4.     public function getItems(){/*...*/}
    5.     public function getItemCount(){/*...*/}
    6.     public function addItem($item){/*...*/}
    7.     public function deleteItem($item){/*...*/}
    8.  
    9.     public function printOrder(){/*...*/}
    10.     public function showOrder(){/*...*/}
    11.  
    12.     public function load(){/*...*/}
    13.     public function save(){/*...*/}
    14.     public function update(){/*...*/}
    15.     public function delete(){/*...*/}
    16. }
    на
    PHP:
    1. class Order
    2. {
    3.     public function calculateTotalSum(){/*...*/}
    4.     public function getItems(){/*...*/}
    5.     public function getItemCount(){/*...*/}
    6.     public function addItem($item){/*...*/}
    7.     public function deleteItem($item){/*...*/}
    8. }
    9.  
    10. class OrderRepository
    11. {
    12.     public function load($orderID){/*...*/}
    13.     public function save($order){/*...*/}
    14.     public function update($order){/*...*/}
    15.     public function delete($order){/*...*/}
    16. }
    17.  
    18. class OrderViewer
    19. {
    20.     public function printOrder($order){/*...*/}
    21.     public function showOrder($order){/*...*/}
    22. }
    Но понятие единая ответственность очень абстрактна. Например здесь разбиваем на части навеянные MVC. Но ведь можно остановиться на этапе "Этот класс имеет единственную ответственность: реализовать логику работы с заказом" и дальше уже не "дробить".... А если уж начали дробить, почему тогда на добавлять OrderTotalCounter, а getItemsCount вообще выкинуть в OrderItemCollections. Т.е. если "захотеть" то углубляться можно до состояния: один класс - один метод :)

    Вот интересно у кого какие мысли про этот принцип?
    --- Добавлено ---
    Пожалуй, еще один, остался для меня не то, что бы сомнительным, но где я не до конца понимаю границу.


    Принцип открытости/закрытости (Open-closed)
    Тут, мне кажется, надо делать примечание, что "с учетом причины изменений". Тут, правда на уровне "чую подвох". т.к. реальный пример не приходит в голову. Но допустим (рассматривая пример в статье - там класс работы с БД через PDO) такой экстремальный случай в PDO нашли жесточайшую проблему (ведь на месте этого класса может быть другой - от менее крутого вендора). Да так, что теперь обязательно надо в fetchObject передавать еще один параметр (не важно какой - пусть текущий год :) ). Разве тут стоит добавлять еще один класс, переписывать тесты, менять по проекту старый класс на новый? Хотя, ведь, с другой стороны, а может наш проект использовал тот самый баг как фичу? ;)
     
    MouseZver нравится это.
  2. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Ну так я и не про жесткость стандарта, мне интересно, кто как к этому относиться и подходит. Ведь тут дело не только в красоте.
    Вот от этого как раз и надо уходить. Я не первый год в профессии ;) Причем принимал в работу проекты и где вссе "просто с боку прифигачено" и где SOLID слишком буквально (как мне кажется) был понят.
     
  3. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    тема не о том почему такой код появляется ;)
     
  4. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.199
    Симпатии:
    377
    @voral сударь, ваш код прекрасен :)
     
  5. onderbert

    onderbert Новичок

    С нами с:
    24 мар 2019
    Сообщения:
    18
    Симпатии:
    1
    Думаю каждый делает так как ему удобно. Автор просто показал как можно разделить обьязаности одного класса на несколько обьектов. В один поместил бизнес логику, второй использует как хранилище, а третий отображение.

    К примеру в своих проектах зачастую использую следующий подход для работы с данными. Контроллер > Сервис > Репозиторий > Модель
     
    voral нравится это.
  6. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Я пока, для себя, пришел к выводу, что надо отталкиваться от объема логики. Например. если, те же чтение/сохранение это код в одну строку, то нет смысла разделять. А если там необходима сложная логика - то уже есть смысл.
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    10.321
    Симпатии:
    1.033
    Адрес:
    там-сям
    Это зависит от уровня декомпозиции. Где-то я встретил сравнение с Центром Управления Полётом. По идее у ЦУП только одна задача: управление полётом, внезапно™ :) Но если присмотреться, то он состоит из множества служб, некоторые весьма далеки от полётов.
    --- Добавлено ---
    И ещё есть разные точки зрения на одно и то же. Например типичный офисный работник может быть важным винтиком в некотором производственном процессе. А с т.з. системы документооборота он просто производитель документов. Для канцелярской промышленности он потребитель товаров. И т.д. Когда мы отображаем реальный мир на объектную модель, мы берем только какой-то один срез. И эта система будет хороша до тех пор, пока она справляется с поставленной задачей. Если скорректируется задача — возможно посыплются и частные построения внутри. Но в любом случае, чем проще и понятнее "кирпичики", тем быстрее можно будет её перестроить. Как в Lego.
     
  8. voral

    voral Активный пользователь

    С нами с:
    30 ноя 2017
    Сообщения:
    646
    Симпатии:
    104
    Согласен. Тут, пожалуй, весь вопрос как раз и есть в объективно необходимом уровне декомпозиции. Если просто "мне кажется, что это другая ответственность" (ну типа MVC "требует" разделения на "три компонента") - то это не правильно. Так как профита можно не получить совсем:
    - удобство чтения кода - придется осуществлять переход в другой файл, если потребуется. А это лишнее телодвижение.
    - скорость, да мизер, но все же обращение к автозагрузчику , чтение еще одного файла, накладные расходы на создание объекта, стека для метода и т.п.
    И, если, все "сохранение в хранилище" это file_put_contents то это будет неоправданно.

    Остается только "а вдруг мы захотим сменить хранилище".... Но таких "авдруг" можно на каждый чих нафантазировать.
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    10.321
    Симпатии:
    1.033
    Адрес:
    там-сям
    Я сейчас так для себя формулирую годность классов: если их удобно тестировать, если легко сформулировать требования, которым они отвечают, значит они нарезаны неплохо. А идеала нет.
    --- Добавлено ---
    Даже если покрытия тестами нет, само стремление к годности для тестирования делает код лучше, более управляемым.
     
    voral нравится это.