Обратная связь

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

понедельник, 7 мая 2012 г.

Заменяем QueryFactory на бестелесный IQueryFactory

В статье Проблемный шаблон Repository и судя по комментариям многим не понравилась та часть, где объекты *Query скрываются за IQueryFactory. С первого взгляда кажется, что QueryFactory превращается в очередной god-object.

Я уже отвечал, что это не так, потому что в самой QueryFactory нет логики и она только создает объекты запросы. Теперь я могу дать ссылки на две статьи, где от QueryFactory остался только интерфейс, который реализуется с помощью IoC.

Первая статья моего коллеги Тимура Рахматиллаева совсем недавно выложена на Хабре Получение экземпляра класса запроса по сигнатуре его интерфейса.

Вторая статья моего бывшего коллеги Дмитрия Крючкова была выложена в его блоге Alternative to repository pattern: query objects using Castle Windsor с примеры кода на GitHub'е

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

21 коммент.:

  1. Преимущества всегда очевидны. Дьявол прячется в недостатках.

    Александр, можно вопрос именно к тебе, как к пустившему волну? Ты же придерживаешься принципа SRP при проектировании? Можешь сформулировать responsibility класса LoginCriterion в примере Тимура?

    ОтветитьУдалить
  2. А мне вообще непонятен ажиотаж вокруг этого ServiceLocator-подобного IQueryFactory. Насколько я понимаю, вещь сугубо опциональная. Предпочитаешь явно объявлять зависимости - прокидывай Query напрямую, не любишь прокидывать много зависимостей - прокидывай IQueryFactory, хотя это 1. практически прокидывание IoC контейнера 2. сделает стаббинг/мокинг зависимостей менее интуитивным

    В любом случае, IQueryFactory никак не влияет на достоинства/недостатки Query - он является надстройкой (пусть, на мой взгляд, и сомнительной) над ним.

    ОтветитьУдалить
  3. @Pasha

    Это можно сказать контекст запроса, а фактически DTO для передачи критериев запроса.

    ОтветитьУдалить
  4. @Idsa

    Еще есть один нюанс - уменьшается количество кода. Опять же на любителя.

    ОтветитьУдалить
  5. Александр, ты о каком коде? О тех трех строчках на каждую зависимость:

    privat readonly IQuery1 _query1;

    public SomeType(IQuery1 query1)
    {
    _query1 = query1;
    }

    Да, неприятный момент. Меня напрягает, когда прокидывание зависимостей - портянка на полэкрана. Кажется, Мартин писал, что если больше 3-4 зависимостей, то это уже говнокод, и его нужно рефакторить. Но рефактиронг в сторону IQueryFactory - еще больший говнокод (пусть и удобный). Хм...

    ОтветитьУдалить
  6. @Idsa

    Вот это откуда:

    > О тех трех строчках на каждую зависимость:
    privat readonly IQuery1 _query1;

    public SomeType(IQuery1 query1)
    {
    _query1 = query1;
    }

    ОтветитьУдалить
  7. @Александр

    Это просто пример пробрасывания непосредственно Query, а не QueryFactory

    ОтветитьУдалить
  8. @Idsa

    Так не получится, потому что IQuery* будет очень много.

    ОтветитьУдалить
  9. @Александр

    Их будет столько же, сколько и методов в IQueryFactory.

    ОтветитьУдалить
  10. @Idsa

    В ссылках, которые я привел у IQueryFactory есть только один метод не зависимо от кол-ва объектов Query*

    ОтветитьУдалить
  11. Ну ок. Если отталкиваться от статей, то будет прокидываться не IQuery1, а IQuery<SomeCriterion, SomeResult>.

    ОтветитьУдалить
  12. @Idsa

    Я не понимаю куда это будет прокидываться :)

    Контроллеры, например, будут принимать только IQueryFactory, как и все остальные объекты в системе.

    ОтветитьУдалить
  13. @Александр

    Так я рассматриваю ситуацию, когда QueryFactory нет

    ОтветитьУдалить
  14. @Idsa

    А, когда ее нет слишком много инжектировать придется. Для однотипных объектов всё-таки надо использовать фабрику.

    ОтветитьУдалить
  15. @Александр

    В общем случае ты, наверное, прав. Но так ли много Query будет в одном сервисе/контроллере? 2, 3, 5? Насколько для нас важно явно видеть, от каких запросов зависит сервис (тестировать такие классы все же удобнее)? От ответов на эти вопросы, думаю, зависело бы мое решение, если бы я вдруг собрался переползти с IQueryable+Specifications на Queries.

    ОтветитьУдалить
  16. @Idsa

    Допустим в начала их будет по 3-4 в каждом контроллере, а потом по 10-12. Будешь рефакторить?

    Очевидно же, что кол-во запросов увеличивается с ростом проекта.

    ОтветитьУдалить
  17. >>Будешь рефакторить?

    Скорее всего, да

    >>Очевидно же, что кол-во запросов увеличивается с ростом проекта.

    Количество запросов в целом - да, увеличивается. Количество запросов в конкретном сервисе/контроллере - не факт. По крайней мере их увеличение (как и любых других зависимостей) - отличной повод задуматься о рефакторинге.

    ОтветитьУдалить
  18. @Александр

    Пожалуй, ты меня убедил :)

    ОтветитьУдалить