Как стать автором
Обновить

Комментарии 38

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

А не проще использовать старые добрые контролеры с DI конструктором вместо предложенных в статье UseCase? По мне так одно и то же получается в плане тестирования.
Никогда еще не сталкивался с проектом, в котором сначала бы реализовывалась бизнес-логика, а затем подбирался фрейворк.

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

А не проще использовать старые добрые контролеры с DI конструктором вместо предложенных в статье UseCase?

Тогда не будет изоляции от HTTP. Допустим вы сегодня делаете проект с микросервисами. И решили что бы не тормозить пока связать все обычным REST/HTTP. А завтра у вас уже требования выше, и HTTP заменяется на какой-нибудь ZeroMQ + MessagePack или еще чего такое.

Суть этого подхода — изолировать код, который может в будущем поменяться. Ну то есть если вы на 100% не уверены в том, нормальное это решение или нет, то проще изолировать это решение, что бы потом можно было "передумать". В этом суть "гибких" архитектур, всегда можно все поменять относительно безболезненно.

Да и скажу так, оверхэда от введения UseCase (обычно все же юзают Command) ооочень мало. А введение вещей вроде CQRS дает еще целую кучу возможностей и пространства для моневра для изоляции будущих изменений.

Конечно же когда мы выбираем тот или иной подход, и в особенности в от эти "сложности" с изоляцией это должно быть не просто так, а потому что ситуация того требует. Для большинства проектов это не нужно. У доброй половины проектов можно спокойно логику по контроллерам размазывать и все будет хорошо. Но вот если вам попадется серьезный проект, где есть такие вот потребности в духе "сегодня так а завтра подругому" — то не имея опыта с подобными концепциями вы рисуете быстро проиграть.
Оно конечно по дефолту рассматривается конкретный фреймворк, но в зависимости от нефункциональных требований все может поменяться.

Как уже упомяналось в комментах на хабре, и PHP может завтра внезапно самоудалиться с тырнета, и компьютеры могут исчезнуть с планеты, может тогда сразу на шестеренках реализовывать?

Но вот если вам попадется серьезный проект, где есть такие вот потребности в духе «сегодня так а завтра подругому»

Ну что вы все термином "серьезности" оперируете? Что же серьезного в проекте, у которого завтра может все поменять? Гибкость это хорошо, но я к тому, что гибкость, как и закостенелось, может быть очень вредной, еси не уметь вовремя остановится. Предложенное в статье решение мне кажется примером излишней гибкости. Еще немного, и процесс создания нового сервиса в системе будет аналогичен написанию всей этой системы, а ведь есть еще и тесты, которые надо поддержать, и документация, и новички на проекте, которые будут месяцами вдуплять в эту необычную архитектуру, а это для "серьезного проетка" куда важнее, чем возможность завтра поменять всю архитектуру приложения путем замены двух строчек кода (почему бы и не поутрировать?).
Как уже упомяналось в комментах на хабре, и PHP может завтра внезапно самоудалиться с тырнета, и компьютеры могут исчезнуть с планеты, может тогда сразу на шестеренках реализовывать?

Повторюсь — помимо вашего популярного фреймворка, есть не не такие популярные библиотеки которые сейчас нужны а завтра их могут сломать, на них могут забить и т.д. Ну то есть надо оценивать вероятность. Да и потом, сегодня вы юзаете библиотеку A из-за какой-то фичи, а завтра вам может понадобиться библиотека B потому что там эта фича реализована безопаснее. Ну и т.д.

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

Что же серьезного в проекте, у которого завтра может все поменять?

Да собственно все. Сегодня пользователи хотят фичу А, завтра фичу Б, через месяц окажется что фича Б им таки не нужна была, и надо ее выпиливать… типичный стартап.
Повторюсь — помимо вашего популярного фреймворка, есть не не такие популярные библиотеки которые сейчас нужны а завтра их могут сломать, на них могут забить и т.д.

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

Вся суть в том, что бы то что может поменяться было отделено от всего остального

Думаю это всем прекрасно известно, но я говорю о другом. Гибкость столь же опасна как закостенелость, потому обращаться с ней нужно так же осторожно. Меня даже немного удивляет, почему есть шаблоны для повышения гибкости, но нет шаблонов для повышения закостенелости приложения? Довольно часто встречаюсь с убийством времени на "гибконизацию" части системы, которая может и будет меняться, но очень не скоро. Другими словами, если вы собираетесь срубить дерево, не надо ножом выпиливать из его ствола щепки параллельно думая, чем же лучше это сделать, двуручно- или бензопилой. Лучше отложить это занятие на денек другой, определиться с архитектурой будущего приложения и уже потом начинать.

Да собственно все. Сегодня пользователи хотят фичу А, завтра фичу Б, через месяц окажется что фича Б им таки не нужна была, и надо ее выпиливать… типичный стартап

А при чем здесь фреймворк и библиотека? Если вам в стартапе не хватает фичи Б, берете и реализовываете ее, если для этого не хватает инструмента, добавляете зависимость в composer. При чем тут реализация бизнес логики до определения архитектуры и фреймворка?
У меня сейчас такой. Пишу код, который должен функционировать или под Magento 1, или под Magento 2. В первом случае в качестве DI я использую Zend'овский (Magento 1 обошлась без DI), во втором — собственно Magento'овский. Ну и еще по мелочи.
Хороший пример, к слову.

У меня чуть другая ситуация. У меня есть проекты, которые написаны на Angular1 из расчета, что через месяца 3 мы перейдем на Angular2.
А есть проект на Angular и через пару месяцев вы переведете его на BackboneJS? У меня есть. Только вот какой гибкой архитектуру в этом случае не делай, все равно все решения, которые были написаны под Angular придется переписывать под BackboneJS, потому что меняется архитектура. В вашем случае изменения архитектуры малы.

Можно сказать так:
Если вы не можете выбрать между двумя версиями одного фреймворка, это повод задуматься об увеличении гибкости бизнес-логики.
Если вы не можете выбрать между двумя разными фреймворками (читать — архитектурами), это повод отложить разработку, провести пару заседаний, выбрать архитектуру, а уже затем начинать работу.
Если вы не можете выбрать между двумя разными фреймворками потому что оба популярные и вам хотелось бы их попробовать, то вы не разрабатываете "серьезный проект", а в этом случае не стоит усложнять его излишней гибкостью, иначе он никогда не родится.
То есть вы не можете выбрать между двумя фреймворками, потому что в одном есть некий пакет, а в другом его нет? Тогда вопрос — а зачем вообще рассматривается Magento 1? Второй вопрос — а разве DI у Zend и DI у Magento2 как то изменят архитектуру приложения? Другими словами, используя первый DI вы будете перечислять зависимости в конструкторе, а используя второй DI в xml файле или что?

Я считаю фреймворк архитектурой проекта. Если встает выбор между фреймворками из за их библиотечной составляющей, то вы выбираете не фреймворки, а инструменты. Почему бы вам не выбрать архитектуру, а потом собрать ее из пакетов разных фреймворков, если уж возникают такие проблемы?
Не я, клиент :) У Magento 1 гораздо большее кол-во расширений. Для него это важно.

разве DI у Zend и DI у Magento2 как то изменят архитектуру приложения?

Моего расширения — нет. Но если бы я не ввел DI Zend'а, то — да.

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

Я делаю расширения к уже существующим приложениям и встраиваюсь в них. Они и диктуют "правила игры". Может завтра клиент решит в OroCRM или WordPress встроиться — я ж не знаю :)
У Magento 1 гораздо большее кол-во расширений

Мы об архитектуре говорим, не о пакетах и библиотеках.

Но если бы я не ввел DI Zend'а, то — да

То есть от выбора той или иной DI архитектура не меняется, меняется она если вообще не использовать DI? Как же тогда автор предлагает писать бизнес-логику, если заранее не известно будет в вашем фреймворке использоваться DI или не будет? Представляете какой космический корабль городить придется чтобы это обойти )

Они и диктуют «правила игры»

Ну так значит архитектура уже давно определена. Ваше дело выбрать пакет и с его помощью решить 1 задачу, а не изменять архитектуру. Тут тем более не нужно заботится о выборе фреймворка. Я надеюсь, вы не заменяете фреймворк в приложении, только потому что в текущем фреймворке нет 1 нужного вам пакета?
если заранее не известно будет в вашем фреймворке использоваться DI или не будет?

шел 2016-ый год, есть composer, какая разница что там есть в фреймворке, если это чуть что можно добавить?

Вообще вся соль в dependency inversion а не в dependency injection. Помимо DI есть еще и другие варианты, хоть фабрики юзать.

Ну так значит архитектура уже давно определена.

Типичное заблуждение что фреймворк диктует архитектуру приложения. Как правило все существующие фреймворки диктуют только архитектуру слоя презентационной логики и немножко как отделяется приложение и UI. Так же они предоставляют способы более удобного проектирования приложения (ORM-ки, тот же DI или IoC для удобной организации сервисного слоя). Инфраструктура.

Все эти решения важные. А хорошая архитектура должна позволить нам в случае ошибки (а предугадать все нереально) быстро исправить ситуацию.
Вообще вся соль в dependency inversion а не в dependency injection. Помимо DI есть еще и другие варианты, хоть фабрики юзать

Тем более к чему этот пример с Magento и Zend?

Типичное заблуждение что фреймворк диктует архитектуру приложения

Давайте тогда порассуждаем об архитектуре приложения. Возьмем, к примеру, скелетон для ZF2. Без него ZF2 не более чем библиотека пакетов, а вот собранный с их помощью скелетон определил будущую архитектуру проекта, а именно принцип разделения бизнес-логики на модули, способы взаимодействия этих модулей и обязательные компоненты (класс Module). Теперь расскажите мне, как вы будете писать бизнес-логику без этих условностей?
Я не очень знаком с ZF2 но просмотрев скелетон — он не задает архитектуру приложения. Да есть пример с декомпозицией через модули, но это не более чем структура проекта. Меня никто этой структурой не ограничивает ни в чем. Я могу вынести бизнес логику в отдельную директорию (Domain), реализовать все там на plain php с интерфейсами, которые уже буду реализовывать в модулях и т.д. Или там могу отказаться от ORM и использовать event sourcing, cqrs и т.д.

Фреймворк в этом случае даст мне определенный костяк и какую-то дефолтную структуру. Но как я буду пользоваться этой структурой — решать мне. И что и как я буду использовать из фреймворка — так же решать мне.
Естественно вы можете установить ZF2 (или любой другой фреймворк) и использовать архитектуру вопреки предлагаемой этим фреймворком, но это значит, что ZF2 не определяет архитектуры. К примеру ZF2 предлагает реализовывать взаимодействие между модулями с помощью событий. Вы можете реализовать у себя другой тип взаимодействия, но тогда возникает вполне резонный вопрос — а зачем тогда вы используете ZF2 с подключенной логикой взаимодействия модулей через события? Другими словами ставя скелетон ZF2 (важно, что именно скелетон, а не фреймворк), вы соглашаетесь с тем, что в этом скелетоне поключаются те или иные пакеты фреймворка, следовательно вы соглашаетесь их использовать (иначе зачем они подключаются?). Это и определяет архитектуру.
Говорю же, мне сложно что-то тут возражать и т.д. поскольку я не работал с ZF2 и понятия не имею о чем вы говорите, это надо разбираться. Но мне кажется вот этот момент с модулями и событиями — это не столь страшно. Если нам это ненадо — мы можем сделать свой скелетон. Если нас это устраивает — то почему бы и нет. Это "архитектура" на все еще довольно высоком уровне, и мы все еще вольны выбирать какую угодно архитектуру в пределах конкретных модулей (а они могут быть немаленькими).

Я же для себя просто сделал свой скелетон, откуда убрал все лишнее и добавил то что нужно конкретно мне.
Я же для себя просто сделал свой скелетон, откуда убрал все лишнее и добавил то что нужно конкретно мне

Это я и называю фреймворком. Вы возьмете пакеты из состава фреймворка, соберете из них свой фреймворк.
Так и есть, composer вытягивает это дело :)

Как же тогда автор предлагает писать бизнес-логику, если заранее не известно будет в вашем фреймворке использоваться DI или не будет

Я создавал у себя в приложении обертку, если фреймворк предоставляет DI — использую его, нет — использую Zend'овский. Ну а классы с бизнес-логикой вообще не интересует, кто и как в них заинжектил нужные зависимости.
Ну а классы с бизнес-логикой вообще не интересует, кто и как в них заинжектил нужные зависимости

Повторю вопрос вам — так к чему этот пример с Magento и Zend? Вы выбираете между двумя одинаковыми пакетами, что (каким то неведомым для меня образом) вылилось в выбор между двумя фреймворками.
Никогда еще не сталкивался с проектом, в котором сначала бы реализовывалась бизнес-логика, а затем подбирался фрейворк.

к этому.
Я не знаком с вашей задачей подробно, но на сколько я понял из ваших слов, вы пытались выбрать между двумя фреймворками для выбора между двумя пакетами. Это конечно меня удивляет, но не относится к моему опыту. DI это один пакет. Да, он влияет на архитектуру, в зависимости от того, подключен он или не подключен, но он не влияет на архитектуру в вашем случае. Как уже сказал выше товарищь Fesor, DI это скорее для dependency inversion. Другими словами если вы уж решили следовать пути dependency inversion, то вы уже определили архитектуру проекта, и не важно DI вы будете пользовать или что то другое.

Учитывая это, представьте как нужно будет вывернуться для реализации бизнес-логики, поддерживающей dependency inversion и не поддерживающей онное )
но на сколько я понял из ваших слов, вы пытались выбрать между двумя фреймворками для выбора между двумя пакетами

из моих слов:

У Magento 1 гораздо большее кол-во расширений.

Здесь "расширение" не равно "пакет". В одном случае в конечной системе требуется поддержка helpdesk'а, в другом — мультисклад. Вот у Magento 1 гораздо больше таких вот расширений, чем у второй версии. Никто не знает, будут ли эти расширения портированы на М2 через полгода. Если будут — завернемся на вторую версию, если нет — на первую.
А что мешает портировать их самостоятельно или просто выбрать аналогичное решение и приустановить сбоку с помощью того же composer?
То, что Magento 1 из до'composer'овской эпохи.
Ну не с помощью composer, какая разница?! Прикрутить сбоку можно и руками.
Можно и штаны через голову надеть, при должном усердии.
Вы думаете что "правильные решения" должны подключаться только с помощью "правильного менеджера"? )
Нет. Я думаю, что в сложных вопросах бывает более одного правильного решения, оптимальность каждого из которых зависит от критериев оценки.
Виталик кстате не плохо говорит на русском.
Если фреймворк перестал разрабатываться, всегда можно продолжит разрабатывать и дорабатывать его самостоятельно. Как правило, любой хороший фреймворк написан профессионалами своего дела и довольно прост в изучении. Никогда не понимал, почему люди не думают об этом. Если проект действительно важный и большой, допилить что-то в самом фреймворке — это же вообще не проблема.

По основной теме статьи… Как же всё сложно) Столько работы, и это лишь создание абстракции. Сколько месяцев придётся пилить эту гостевую книгу, если следовать такой методологии?)
Если Symfony2 вдруг перестанет разрабатываться, осилите продолжение разработки небольшой командой? :)
Так не надо ведь там вообще всё перелопачивать. В теории, если при проверке вашего сервиса на устойчивость к взлому, если в работе фреймворка найдут дыру безопасности (как-будто дыр безопасности не существует без фреймворков. Скорее опять же, фреймворк — это наименее потенциальное место для дыр, ибо его там по 10 раз перепроверяют профессионалы) — то вы эту дыру не сможете чтоли найти и залатать?

Далее, говоря о «продолжении разработки» — я не имел ввиду полноценную разработку, клонирование репо, информирование сообщества об этом, и так далее. Я имел ввиду, что можно где-то чуток изменить логику самого фреймворка чисто в своём конкретном проекте, если это вдруг понадобится. Это не так уж и сложно. Тем более, сейчас уже многие фреймворки перешли на использование контрактов, что сильно облегчает замену компонентов. По сути, это как собираются же сейчас модульные телефоны продавать. Захотел — поменял процессор, или оперативку. Также и фреймворки сейчас пишут. Захотел изменить какую-то подсистему — пожалуйста, реализуй свой класс, который будет удовлетворять условиям контракта, и ставь его вмето оригинального класса фреймворка.

В общем, всё это вполне решаемо, нет чего-то нереального. Я лично в проект на Кохане затащил некоторые классы из Laravel 5, коллекции, некоторые хелперы. Потому что они удобные, почему нет? И эти классы вполне себе нормально живут вне ларавел. Считай, немного изменил Кохану в угоду нашего конкретного проекта. Также мы расширили ORM, добавив ему некоторые полезные функции, добавили возможность получения из БД текстовых данных объектов на текущем активном языке. Этого ведь не было в основном коде фреймворка. И, кстати, авторы Коханы вообще изначально там предполагали, что разработчики проектов будут расширять их классы, они даже изначально все основные классы свои сделали таким образом, что можно легко переопределить и расширить любой класс. Автор статьи писал о том, что он использовал Кохану, думаю, он поймёт, о чём я.

Поэтому я и не вижу на самом деле особых проблем в зависимости от какого-то фреймворка. Всё это решаемо)
Вот как раз с сф такого не случиться, как с комьюнити фрейморвками.
Если фреймворк перестал разрабатываться, всегда можно продолжит разрабатывать и дорабатывать его самостоятельно.

В долгосрочной перспективе это дороже чем сменить фреймворк.

Как правило, любой хороший фреймворк написан профессионалами своего дела и довольно прост в изучении.

Не стоит забывать о том что к "фреймворку" относятся все сторонние либы, бандлы, а не только ваш любимый laravel/yii/ci/etc. Изоляция позволяет нам быстро адаптироваться в случае нарушения BC у важного обновления и т.д. Увы мы не застрахованы от того, что какой-то вася пупкин сломал BC где-нибудь в важном месте, но нам вот очень нужен именно этот релиз. Я много раз с подобным сталкивался. Так что по поводу "профессианалов", если расширить смысл слова "фреймворк", я бы засомневался.
1) ни слова о пирамиде тестирования
2) ни слова о сокращении цикла обратной связи
3) ни слова о моках
4) ни слова о том, что тесты не должны быть сильно завязаны на реализацию (многие на этом спотыкаются и из-за этого тесты становятся уже не так эффективны)
5) смешение TDD и ATDD (я про интеграционные и e2e тесты)
6) Ни слова о том, что TDD должны направлять разработку, Ни слова о том, что TDD это скорее Test Driven Design чем Development.

Что до концепции юзкейсов, тут интереснее послушать Дядю Боба, который в своих Agility and Architect об этом вещает.
попробую ответить на русском языке

Какие проблемы хочет решит ета "Чистая Архитектура"?

Подумаем во первых о том как мы работаем каждый день, точнее как мы тестируем. В основном процесс такой: Программист задает код, открывает браузер, нажимает Ф5 и контролирует результат. Ето самый простой пример. Есть другие примеры, например несколько форм с кнопкой "далее" в первой форме задаются данные, нажимая на кнопку отркывается следующая форма, может перед проверки нужно ище задать данные в базу.

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

большое время программисты тратят либо на тестирование в ручную, либо читать и копаться в чужом коде и молится богу чтоб на другом, неожиданном месте не что не сломалось.

те, которые заметили что трудно добовлять фичи, в основном начинают использовать автоматичиские тесты, типа с selenium, но в таких тестов появляются другие проблемы, они медленныи, Code Coverage не существует, поменялся HTML тесты сломались.

следующий уровень тесты логике с PHPUnit и тут иже проблемы наченаются, как тестировать мою логику? мой ORM имеет кучу ->where() ->join() и.т.д и если что то в базе данных поменялось то и тест сломался. весь код находится в контроллере, добраться до ево через роутер, View тоже где-то собираетса и в ней иногда "хелперы" которые внутренно следующий ORM используется.

в чистой архитектуре решаются проблемы с Test Driven Design, то есть сперва создаем тест, потом создаем логику для проблемы, ета логика не конкретная, она просто описывает что нам нужно штобы добратся до нашей цели. Типа "ищем дании" "используем сервис А" для передела данных и передаем переделанные в высший слой.
наши тесты создают интерфейсы коториы мы потом имплементируем. если придет новый человек в команду, он не должен теперь всю логику знать, нажатие на кнопку он быстро узнает сломал ли он что нибудь или нет. так же и мы сами, можем не боятся нашего кода.

не зависимость от фреймворка, веб, дб ето естественно тоже плюс, не мало фирм меняют проект с монолита на микро сервис, и не мало фирм меняют или даже мешают несколько базы данных (например MySQL и CouchDB) многие процессы также и нужно на консоль вызывать и в контролере.

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

надеюсь на многие вопросы я смог ответить
Зарегистрируйтесь на Хабре, чтобы оставить комментарий