Pull to refresh
149
0
Игорь Миняйло @maghamed

Lead Architect, Magento an Adobe

Send message
Так, давайте еще раз. А то, как-то все смешалось.

1. Это связано с жирным конструктором таким образом, что мы решили строить Service Layer для того, чтобы у нас была возможность всегда вносить изменения (читай рефакторить) конкретные реализации. Данный фрагмент конструктора является конкретной реализацией, и программисты кастомизаторы не должны на него зависеть, для этого у них есть публичные интерфейсы и механизмы их расширения (плагины, событийная модель, предоставление собственной реализации по контракту). Поэтому рефакторинг конкретно этого класса (да, сейчас он выглядит не идеально и нарушает принцип единой ответственности) стал менее приоритетным по сравнению с введением публичных контрактов модуля Catalog, в котором он находится.

По-хорошему, кастомизатору и любому не core Magento программисту в него смотреть вообще не имеет смысла. Поэтому рефакторинг этого класса есть в наших планах, но далеко не в ближайших.

2. По поводу Service Locator. Я как раз под DI не понимаю Service Locator, читайте внимательней. Service Locator это шаблон, который использовался в первой версии Magento, где все внешние зависимости создавались по месту их использования с помощью методов Mage::getModel(), Mage::getSingleton(). DI появился во второй версии мадженто и заменил собой Service Locator
вот было бы неплохо такую же только по второй версии, заодно перечислить различия, с которыми вы столкнулись. было бы интересно
Вы не внимательно прочитали мой ответ. Прочитайте еще раз.
Single Responsibility принцип это хорошо, и по возможности нужно ему следовать. Но, мы говорим о проекте с более чем 2к классами и огромным числом зависимостей.
Когда DI приходит в такой проект — он обнажает много проблем. Часть из которых более важны, часть — менее.
Если кинуться и исправлять весь код и приводить в соответствие с SOLID это приведет к огромным трудозатратам, но в итоге мы все равно прийдем к проблеме, которая была в Мадженто 1. Когда у нас все классы являлись контрактами для расширения, и в итоге мы никогда не можем изменять их (менять названия методов, удалять методы, менять сигнатуры), потому что это поломает чей-то код. Код, который расширяет через наследование, например. Поэтому та же Мадженто 1 обросла PhpDoc @depricated, чтобы показывать, какие методы мы хотим исключить из контрактов.

Service Layer призван решить эту проблему и зафиксировать интерфейсы взаимодействия с 3rd party программистами.

Я искренне благодарен вам за то, что вы даете такие ценные советы с чем мне стоит разобраться, но вы сами абсолютно не разобравшись в вопросе, просто достаете какой-то фрагмент кода и пытаетесь ловить лулзы. Что выглядит странно и не профессионально. Более того, уверен, что вы даже не нашли этот конструктор самостоятельно, т.к. в этом случае вам бы пришлось посмотреть код, разделение ответственностей, API и т.д. А нашли ссылку на этот конструктор в твиттере, которая ходила пару месяцев назад.

я уже ответил на это ниже, никто не спешил.
На самом деле это намного лучше Symfony. В Мадженто DI для классов сущностей нигде не передается DI контейнер (ObjectManager в терминологии Мадженто), только сущности, которые необходимы конкретному классу. DI контейнер используется только в фабриках, но фабрики в Мадженто это автогенерируемые сущности, поэтому в 90% случаев вам не прийдется их писать руками. Поэтому любая сущность в Мадженто (Модель, Блок, Контроллер) легко покрывается юнит тестами. Достать один из классов и показывать его конструктор — это не интересно и абсолютно не показательно. Более того, когда в Мадженто 1 данная модель содержала в себе все те же зависимости, но использовала внутри себя Service Locator для их инстанциации этого никто не замечал и все с этим жили. DI показал много проблем в зависимостях у классов и модулях, между которыми не должно быть этих зависимостей. Более того, то что вы показываете (модель продукта) это имплементация модели, Мадженто 2 предоставляет Service Layer набор публичных API интерфейсов у каждого из модулей, и именно эти интерфейсы предполагаются будут использованы и расширены (плагинизированы) 3rd party программистами. Эти интерфейсы считаются стабильными, и Мадженто обязуется не менять их без очень острой нужды. И соответственно если такая нужда возникает, то апгрейдится мажорная версия модуля (aka семантическое версионирование). Поэтому зависимости на имплементацию, т.е. в данном случае на модель продукта считается не верными, т.к. Мадженто не гарантирует, что имплементация не будет меняться (даже правильней сказать, что гарантировано, что они будут меняться). Собственно сервис леер и вводился для того, чтобы скрыть имплементация, и всегда иметь возможность провести нужный рефакторинг, не влияя на существующие расширения и контракты. Как и в данном случае, за счет того, что у модуля Catalog есть свои API, предполагается, что программисты будут использовать их, а конкретно эту модельку мы всегда можем отрефакторить, и никто от этого не пострадает
Это называется непониманием базовых принципов ООП и SOLID, а именно — LSP (принцип подстановки Барбары Лисков), который гласит, что объекты классов-наследников, расширяющих базовый класс, могут использоваться вместо экземпляров базового класса без каких-либо изменений желательных свойств этой программы.

Картинка прилагается:
image
В PHP тоже есть Reflection и он с успехом используется для написания DI контейнеров. Например, в ZF2, Symfony 2, Magento 2
Посмотрите реализацию DI для Magento 2 github.com/magento/magento2/tree/master/lib/Magento/ObjectManager
Он соответствует вашим критериям DI, а именно в конфигурации DI просто говорится какому интерфейсу соответствует какая реализация, а клиентский код напрямую с DI контейнером вообще не работает, просто указывает все сови зависимости в конструкторе. DI контейнер же, узнает о всех зависимостях через декларацию конструкторов и создает объекты либо на лету, либо по разанее «скомпилированной» декларации. Как-то так github.com/magento/magento2/blob/master/lib/Magento/ObjectManager/Factory/Factory.php
Здесь не вопрос Модно-Немодно.
Выбор конкретного подхода Active Record vs Data Mappers + Repository должен вытекать из бизнес задач.
Дело в том, что Active Record является фактический неотъемлемой частью RAD (rapid application development), и цель его быстро развернуть уровень доменных моделей (читай бизнес логики) по существующей схеме базы (как правило, небольшой). Фактически все RAD проекты строятся по принципу «Database First» — т.е. мы вначале проектируем схему БД, как-то ее декларируем (Json, Yaml, SQL, ini) и через эту декларацию фреймворк генерирует нам доменные модели с уже реализованым CRUD функционалом через механизм scaffolding-a.
Это хорошо работает на маленьких-средних проектах с небольшими зависимостями. Если же проект большой и людей, которые работают на нем много, и чтобы поддерживать все в рабочем состоянии эти люди хотят покрывать код тестами, то тут начинаются проблемы…
Поэтому в последнее время такую большую популярность и обрел DDD (Domain driven design), который декларирует одним из своих основных принципов persistence ignorance и «Code First». При этому мы получаем все те плюшки, которые автор описал в статье (SOLID, доменные модели не знают вообще, что их куда-то сохраняют, поэтому становятся тонкими и содержат только бизнес логику). Развивая идею дальше мы приходим к тому, что в таком виде можно легко реализовать Unit of Work паттерн, и разгрузить слой приложения (читай контроллеров) от обязанностей сохранять и контролировать что модели сохраняются и обновляются корректно. А эта обязанность переходит в инфраструктурный уровень. Но при этом, да, сложность проекта становится выше.
По поводу профайлинга в MySQL я как-то писал статью на хабре
http://habrahabr.ru/post/39818/
Без соли. Они у них без соли используются, просто SHA-1
www.theverge.com/2012/6/6/3067523/linkedin-password-leak-online
В этом релизе появился новый алгоритм PLN (Price Layered Navigation).
К существующим двум:
1. Manual (в котором явно задается шаг, и максимальное число интервалов)
2. Automatic (Equalize price ranges), который автоматически разбивал множество на интервалы, но выбирал при этом шаг равный степени 10. И останавливался, когда число интервалов становилось большим либо равным двум.

добавился
3. Automatic (Equalize product count), в котором используя статистические данные по выборке строится распределение. В данном случае интервалы будут содержать приблизительно одинаковое число продуктов.

И этот новый метод действительно работает медленней, чем предыдущий (2) на выборках до 100к продуктов. В первую очередь из-за накладных расходов в связи с дополнительными запросами к базе данных.
Если используется Solr данная разница едва ли заметна.
Проверял на 5.5.18 результат был тот же
это очень плохой стиль. И этого нужно стараться всячески избегать. Более того, при правильно сформированном SQL запросе и актуальной статистике индексов (периодическом выполнении Analyze table, что более актуально для MyISAM и менее для InnoDB). У вас такие проблемы будут возникать достаточно редко.
и я тоже не верил. Пока не проверил на 5.0.37, 5.1, 5.5.18 версиях
Вторая особенность как раз выглядит логичной, чего не скажешь о первой.
я просто совсем недавно открыл для себя интересные особенности работы оптимизатора при работе с константными выражениями, поэтому и здесь поспешил отписаться.

А особенности такие:

запрос у которого в where выражение из констант (правая часть выражения) проигрывает запросу, у которого в правой части константа

WHERE
( e.website_id = '1' ) AND ( e.customer_group_id = 0) AND (e.min_price >= ((3089.24 — 0.005) / 1))

хуже, чем

WHERE
( e.website_id = '1' ) AND ( e.customer_group_id = 0) AND e.min_price >= 3089.235

зато
такой запрос:

WHERE
(e.min_price >= 1999.995) AND (e.min_price < 2999.995) AND
(e.min_price >= 1999.995) AND (e.min_price < 5999.995) AND
(e.min_price >= 999.995) AND (e.min_price < 10999.995) AND
(e.min_price >= 2694.235) AND (e.min_price < 2999.995);

выполняется по времени аналогично такому

(e.min_price >= 2694.235) AND (e.min_price < 2999.995);
не успел отписаться, что я не увидел OR :-)
Прошу прощения, конечно я не прав
не уверен, что на стадии оптимизации запроса часть 1=1 не будет удалена и таким образом не повлияет на ход выполнения
Запрос был исключительно для примера, и я склонен с вами согласиться, но все же если пофантазировать, то индекс по col2 может быть выгодней, чем по col1 в случае если Cardinality индекса col1 очень большая. Например это поле цвет.

Information

Rating
Does not participate
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity