Перечитал/пересмотрел много мнений. Но про многих "авторов" я бы сказал "заставь дурака богу молиться он и лоб расшибет". Но в целом все в голове устаканилось (даже статью на хабре нашел где как резюме - все емко написано и соответствует моему пониманию в результате всех измышлений) Осталось только одно: Принцип единственной ответственности . Чтобы пояснить мои сомнения более-менее конкретно. Привожу прямо примеры из понравившейся статьи Автор предлагает по этом принципу из кода PHP: class Order { public function calculateTotalSum(){/*...*/} public function getItems(){/*...*/} public function getItemCount(){/*...*/} public function addItem($item){/*...*/} public function deleteItem($item){/*...*/} public function printOrder(){/*...*/} public function showOrder(){/*...*/} public function load(){/*...*/} public function save(){/*...*/} public function update(){/*...*/} public function delete(){/*...*/} } на PHP: class Order { public function calculateTotalSum(){/*...*/} public function getItems(){/*...*/} public function getItemCount(){/*...*/} public function addItem($item){/*...*/} public function deleteItem($item){/*...*/} } class OrderRepository { public function load($orderID){/*...*/} public function save($order){/*...*/} public function update($order){/*...*/} public function delete($order){/*...*/} } class OrderViewer { public function printOrder($order){/*...*/} public function showOrder($order){/*...*/} } Но понятие единая ответственность очень абстрактна. Например здесь разбиваем на части навеянные MVC. Но ведь можно остановиться на этапе "Этот класс имеет единственную ответственность: реализовать логику работы с заказом" и дальше уже не "дробить".... А если уж начали дробить, почему тогда на добавлять OrderTotalCounter, а getItemsCount вообще выкинуть в OrderItemCollections. Т.е. если "захотеть" то углубляться можно до состояния: один класс - один метод Вот интересно у кого какие мысли про этот принцип? --- Добавлено --- Пожалуй, еще один, остался для меня не то, что бы сомнительным, но где я не до конца понимаю границу. Принцип открытости/закрытости (Open-closed) Тут, мне кажется, надо делать примечание, что "с учетом причины изменений". Тут, правда на уровне "чую подвох". т.к. реальный пример не приходит в голову. Но допустим (рассматривая пример в статье - там класс работы с БД через PDO) такой экстремальный случай в PDO нашли жесточайшую проблему (ведь на месте этого класса может быть другой - от менее крутого вендора). Да так, что теперь обязательно надо в fetchObject передавать еще один параметр (не важно какой - пусть текущий год ). Разве тут стоит добавлять еще один класс, переписывать тесты, менять по проекту старый класс на новый? Хотя, ведь, с другой стороны, а может наш проект использовал тот самый баг как фичу?
Ну так я и не про жесткость стандарта, мне интересно, кто как к этому относиться и подходит. Ведь тут дело не только в красоте. Вот от этого как раз и надо уходить. Я не первый год в профессии Причем принимал в работу проекты и где вссе "просто с боку прифигачено" и где SOLID слишком буквально (как мне кажется) был понят.
Думаю каждый делает так как ему удобно. Автор просто показал как можно разделить обьязаности одного класса на несколько обьектов. В один поместил бизнес логику, второй использует как хранилище, а третий отображение. К примеру в своих проектах зачастую использую следующий подход для работы с данными. Контроллер > Сервис > Репозиторий > Модель
Я пока, для себя, пришел к выводу, что надо отталкиваться от объема логики. Например. если, те же чтение/сохранение это код в одну строку, то нет смысла разделять. А если там необходима сложная логика - то уже есть смысл.
Это зависит от уровня декомпозиции. Где-то я встретил сравнение с Центром Управления Полётом. По идее у ЦУП только одна задача: управление полётом, внезапно™ Но если присмотреться, то он состоит из множества служб, некоторые весьма далеки от полётов. --- Добавлено --- И ещё есть разные точки зрения на одно и то же. Например типичный офисный работник может быть важным винтиком в некотором производственном процессе. А с т.з. системы документооборота он просто производитель документов. Для канцелярской промышленности он потребитель товаров. И т.д. Когда мы отображаем реальный мир на объектную модель, мы берем только какой-то один срез. И эта система будет хороша до тех пор, пока она справляется с поставленной задачей. Если скорректируется задача — возможно посыплются и частные построения внутри. Но в любом случае, чем проще и понятнее "кирпичики", тем быстрее можно будет её перестроить. Как в Lego.
Согласен. Тут, пожалуй, весь вопрос как раз и есть в объективно необходимом уровне декомпозиции. Если просто "мне кажется, что это другая ответственность" (ну типа MVC "требует" разделения на "три компонента") - то это не правильно. Так как профита можно не получить совсем: - удобство чтения кода - придется осуществлять переход в другой файл, если потребуется. А это лишнее телодвижение. - скорость, да мизер, но все же обращение к автозагрузчику , чтение еще одного файла, накладные расходы на создание объекта, стека для метода и т.п. И, если, все "сохранение в хранилище" это file_put_contents то это будет неоправданно. Остается только "а вдруг мы захотим сменить хранилище".... Но таких "авдруг" можно на каждый чих нафантазировать.
Я сейчас так для себя формулирую годность классов: если их удобно тестировать, если легко сформулировать требования, которым они отвечают, значит они нарезаны неплохо. А идеала нет. --- Добавлено --- Даже если покрытия тестами нет, само стремление к годности для тестирования делает код лучше, более управляемым.
Один интерфейс - множество классов - метод. Да. Особенно если надо что-то менять по проекту. Смысл как раз-таки в том, чтобы меняя реализацию ничего не ломалось. И везде все заводилось. ORM ведь строит свои sql'ки к примеру, в зависимости от используемого драйвера. Как боженька.