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

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

очередной пример абсолютного непонимания очередного паттерна.


молоток — зло. им можно больно стукнуть по пальцу. забивайте гвозди головой. ну или по крайней мере отверткой

Так в статье только некоторые доки/гайды критикуются, а не сам паттерн, не?

от части — да, согласен. но такое есть и в других доках/гайдах.
посмотрите как в symfony в доках показывали подвязку БД и вам тоже должно стать нехорошо.
самостоятельно думать никто не отменял. да и в гугле тоже люди работают (посмотрите на angular 1).
автор (не переводчик) сам не особо разобрался, что есть что (репозиторий = ORM?).


как компромисс: автор не совсем понял что на самом деле есть суть паттерна "репозиторий". "споткнулся" на никакущих доках/гайдах. и дидактически коряво пытается объяснить, что там не так

Буду признателен если поделишься своим мнение что такое "Репозиторий"

моё мнение: хватает оригинала
https://martinfowler.com/eaaCatalog/repository.html


там ясно сказано, что это "посредник" между "бизнесом" и (OR)Mapping. учитывая это определение и принципы SOLID, "посредник" между чем-либо не может(не должен) одновременно являться одним из них.


признаки ошибочной реализации паттерна


  • наличие save-функциии/метода в репозитории
  • наличие функционала для работы с атрибутами объектов хранящихся в репозитории

А какие функции/методы там должны быть, для примера?

"должны" быть те, которыми "пользуется" ваш бизнес в данном контексте.
"могут" быть те, которые соответствуют функционалу collection/list. такие как например add, remove, find.
save != add
репозиторий с точки зрения бизнеса это не про то, как "сохранить" данные. с точки зрения бизнеса данные или уже есть в репозитории или их туда можно/нужно добавить.

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

Нет, вы пожалуйста конкретно укажите, что должен быть, например, метод А, В и С. Ну вот у вас были когда-то какие-то репозитории? Какие конкретно там были методы?


репозиторий с точки зрения бизнеса это не про то, как "сохранить" данные.

Так а о чем он? Выглядит так, что ни о чем, соответственно, там никаких методов быть не должно вообще.


с точки зрения бизнеса данные или уже есть в репозитории или их туда можно/нужно добавить.

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

вы пожалуйста конкретно укажите

так я вроде как указал (add, remove, find)?
но для начала стоит, по-моему, разобраться, что означает "бизнес" и что вы понимаете под "сохранить данные".
что-то мне говорит, что у вас "немного" другое понимание значения "репозитория".


С точки зрения бизнеса никакого репозитория не существует

тут само определение паттерна https://martinfowler.com/eaaCatalog/repository.html
в последнем предложениии автор ссылается на Domain Driven Design.
DDD описывает принципы моделирования исключительно с точки зрения бизнеса.
в концепте DDD репозиторий это один из ключевых элементов архитектуры.


и в залючении пример класса репозитория (актуальный проект)


<?php
namespace AgencyPortal\PublicServices;

use Agency\Contract\ContractRepositoryInterface;
use Agency\Contract\Contract;
use Agency\Contract\Specifications\ContractsFilter;
use Agency\Contract\ValueObjects\ContractId;

class ContractRepository implements ContractRepositoryInterface
{

    /**
     * @param ContractId $contractId
     * @return Contract|null
     */
    public function find(ContractId $contractId): ?Contract
    {
    }

    /**
     * @param ContractsFilter|null $filter
     * @return Contract[]
     */
    public function findBy(?ContractsFilter $filter = null): array
    {
    }
}

да, в контексте данного проекта в репозитории отсутствуют методы изменяющие данные в репозитории (добавить, убрать). для этого есть другой "проект"

так я вроде как указал (add, remove, find)?

Чем add отличается от save? Кроме того, add/remove/find делает ОРМ. Тогда с ОРМ репозиторий не нужен?


но для начала стоит, по-моему, разобраться, что означает "бизнес" и что вы понимаете под "сохранить данные".

"Сохранение данных" — это некоторый процесс, после успешного завершения которого те, у кого есть права доступа к этим данным, могут с этими данными ознакомиться.


и в залючении пример класса репозитория (актуальный проект)

Это не репозиторий, это либо кусок ОРМ, либо часть бизнес-логики (зависит от контекста и того, что именно делают указанные методы и как используются).

Ну ORM как бы тоже на место репозитория стать может. Почему нет? Это же не исключающее или. Это может быть репозиторий И орм класс одновременно.
на место репозитория стать
орм класс одновременно.

это будет против SOLID.

Какого именно из?

single responsibility

Никак не нарушает, имхо. Какой нибудь ОРМ класс для доступа к данным вполне может являться одновременно и репозиторием, так как у них обоих может быть одна причина для изменения. Я бы даже сказал что какой нибудь DAO это частный случай репозитория. Обратное неверно.
Впрочем даже если и нарушает — не стоит забывать что SOLID, DRY и прочее это не абсолютные законы, а рекомендации, которые вполне можно и нарушить.

single responsibility это не про "одна причина для изменения".
это про "кто отвечает за данный кусок системы"
https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html


This principle is about people.
When you write a software module, you want to make sure that when changes are requested, those changes can only originate from a single person, or rather, a single tightly coupled group of people representing a single narrowly defined business function.

с последним согласен. хотя, имхо, чтобы позволить себе нарушать такие рекомендации, нужно быть достаточно уверенным в том, что делаешь. то есть уметь абсолютно объяснить отклонение от "правил" (нет, это не законы)


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

это про «кто отвечает за данный кусок системы»

Спорно, под кто отвечает — нередко имеется в виду какой нибудь бизнес процесс или что то вроде того, а не человек.

Почему ORM класс не может выступать репозиторием если с т.з. бизнес логики от репозитория требуется только уметь сохранить и получить данные? Есть условный интерфейс DataRepository, и его ORM класс имплементит.
а не человек

вы, похоже, не стали смотреть, кого я цитировал. это поправки и разъяснение к пониманию принципа от самого "изобретателя". так что тут ничего "спорного" быть, по-моему, не может.


если вы не разрабатываете очередной phpMyAdmin, то (повторюсь), с точки зрения бизнеса в подавляющем большинстве случаев нет логики "сохранить какие-либо данные". само слово "сохранить" неуместно.


конечно, вы можете ОРМ класс сделать одновременно и репозиторием для бизнеса. но тогда вы нарушаете single responsibility.


но ваш аргумент с интерфейсом поддержу:
согласен, этот интерфейс (DataRepository) определяет функционал необходимой бизнесу. но могу вас уверить, что у вас возникнут проблемы, как только вы захотите имплементировать поиск по данным.
паттерн репозитория предусматривает для поиска данных использование паттерна specification


Client objects construct query specifications declaratively and submit them to Repository for satisfaction

но для разных типов конкретного "хранилища" (бд, файл, in-memory) Specification или нужно пилить самому или это уже сделали, но заточенный под конкретную технологию (например Criteria by Doctrine). все это уместить в один толковый (строго типизированный) интерфейс будет сложно.


ну и опять таки оригинал


A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection

то есть репозиторий это нечто между двумя слоями.

от самого «изобретателя». так что тут ничего «спорного» быть, по-моему, не может.

Некоторые высказывания изобретателя вполне спорные. И лично по мне S принцип в его массовой трактовке более логичен чем в трактовке дядюшки Боба.

По остальным пунктам в принципе соглашусь.

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

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

Чегойта? А как же "сохранить содержимое корзины когда клиент закрывает сайт"?

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


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


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

а теперь вы. но не забывайте, пожалуйста, и о таких нюансах, как:


  • скоропортящиеся продукты
  • популярные или дорогие продукты, которые хотелось бы все таки продать

Почему-то меня не покидает ощущение, что в ваших глазах "подавляющее большинство" бизнеса — это что-то в духе деревенского магазина, ну или некий бизнес, который принципиально ничего не хочет иметь общего с информационными технологиями, но при этом с какого-то перепуга имеет штат программистов. Нет, ИТ уже давным-давно проникло грубоко в повседневную жизнь, везде (да, даже в деревнях). Если у бизнеса есть сайт, то для них фраза "когда клиент закрывает сайт" является абсолютно нормальной — потому что сохранение корзины клиента, когда он покидает магазин, вне контекста сайта-магазина не только глупо, но и напрямую вредит бизнесу, так как убирает товар с полок. А если бизнесмен — не квадратный мужик с золотой цепью 70+ лет возрастом, то он, представьте себе, может даже сам разбираться в ИТ хотя бы на уровне, когда сможет сообразить, что его делу нужен сайт, и какой именно. Да и среди квадратных мужиков разбирающихся теперь тоже немало. В общем, перестаньте натягивать свои аналогии на глобус.

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

Ненормально это как-то с Вашей стороны — делать утверждения в духе "с точки зрения бизнеса само слово сохранить неуместно", а потом ещё говорить будто это я указываю бизнесу, как ему работать.
К слову сказать, не вижу вообще ничего плохого в том, чтобы, найдя взаимоисключающие параграфы при анализе ТЗ, программисты забили тревогу, и тем самым указали бизнесу на дыру в его же процессах.


ИТ-фразы становятся нормальными. И было бы вообще супер, если бизнес по-настоящему понимал, что они означают.

Зачем им это? Чтобы кто-то по-настоящему понимал, как это работает и что означает, они Вас наймут, а уж вы им объясните всё как есть.


"сайт" ничто иное как лишь еще один из каналов сбыта товара?

Нет, не "лишь". Принципы торговли через сайт или Интернет в целом достаточно отличны от обычного прилавка, чтобы отделять их друг от друга.

Чем add отличается от save

add = добавить. в данном случае в список/коллекцию
save = сохранить. в данном случае persist. в каком-либо (долгосрочном) накопителе. например БД, файл итд.


add/remove/find делает ОРМ

ОРМ по определению "трансформирует" данные из одного вида (строка из файла или БД) в другой (объект класса).
например:
mysql: created_at TIMESTAMP -> php: $createdAt = new DateTime()

в данном случае

Ну то есть по факту — только названием.


ОРМ по определению "трансформирует" данные из одного вида (строка из файла или БД) в другой (объект класса).

ORM — это object relation mapping, не structure relation mapping. Т.е. ОРМ, по определению включает вещи вроде find/add/remove (т.к. это вещи, которые задают поведение объекта, к которому вы, собственно, сущность из бд приводите), а если не включает — это не орм. Вы не путайте орм с дата маппером у Фаулера — это разные вещи.


это будет против SOLID.

Не будет, у них же одна ответственность.

только названием

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


не путайте орм с дата маппером у Фаулера

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


ваша аргументация наталкивает на мысль, что у вас понимание "relation" в ORM и соответственно ralational database иное.

Однако, на мой взгляд, если вы будете использовать в своем проекте этот паттерн, вы гарантированно увязнете в грязном спагетти-коде.


Прям верхний абзац статьи. А вообще, репозиторий — это такая штука, для которой решение об использовании / не использовании принимается для каждого проекта раздельно. Автор же привел пример откровенно плохой реализации, якобы в виде доказательства своего мнения.
Я не андроид разработчик. Но, в принципе, согласен. Как по мне, так в репозитории должна быть только «2 группа» и точно не должно быть третьей. И это все еще не ОРМ ибо репозиторий не обязан вам маппить иерархии обьектов, хотя и не возбраняется.
И да, проблема решается введением еще одно слоя «бизнесс логика» со всякими менеджерами или доменными агрегатами.

Тут стоит говорить о нескольких уровнях проблемы: и один из этих уровней — это нейминг. То, что Фаулер и Эванс имели в виду под словом репозиторий, и то, что в мире Андроид, называют репозиторием — это две большие разницы. Ханнес, хорошо написал об этом тут

Имхо, не учтены размеры проекта. Этот подход вполне нормальный когда бизнес логики почти что нет. Тогда можно отдать ее на откуп репозиторию (как раз вот эти вот «завершить задачу», «удалить задачу»), а во вью модели только логику отображения иметь и обработку действий пользователя.
Репозиторий это шаблон который скрывает реализацию конкретного источника данных (т.е. бд) и предоставляет высокоуровневую абстракцию. Можно ли назвать REST api источником данных? Можно, но только при одном условии — то что мы туда «ложит» то и «забирает», исключение — справочные данные.
Имхо тут всё проще. Смотрим на картинку от гугла и спрашиваем: ок, чуваки, а где тут будет жить бизнес-логика? И сразу видим, что места для неё и не предусмотрено:
— размещать логику в Presenter/ViewModel — так себе вариант, хотя бы потому, что нет возможности её повторно использовать из других мест
— размещать логику в репозитории (то есть, по факту, в CRUD-механизме) ещё смешнее.

А так как логика всё-таки обычно нужна, то и сразу становится видна необходимость дополнительного слоя. В clean это use cases/interactors, в ribots (https://bit.ly/3iBclap) — это Data Managers, один-в-один, как тот, что сверху. В разных архитектурах такой слой всегда явно выделяется, и не важно, как он там называется.

Пост из разряда — "да вы ребята в гугл вообще не шарите, я программирую пару месяцев и знаю больше вас, и все ваши рекомендации ни о чем...."

Подождите, репозиторий это часть слоя Model — где мы получаем данные из сети/бд, и можем складывать куда-нибудь в кэш и возвращаем все это дело в Domain слой. Use cases это уже часть слоя Domain, в них как раз и есть бизнес логика. Да, для мелких проектов это, конечно, излишнее, но в крупных проектах без этого никуда. На этом и построена «Чистая архитектура». В чем антипатерн-то? Что в конкретном проекте создали огромный один репозиторий? И опять же ViewModel это все таки слой Presenter, в нем тоже не рекомендуется бизнес логику размещать.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий