Колекции и реалност

Нека си представим, че имаме система, която работи непрекъснато, има достатъчно памет и е само за един потребител. С този вид система можем да имаме всички обекти в колекции от памет и всичко да е блестящо. Колекциите от памет са достатъчни - те ни позволяват да съхраняваме, получаваме и премахваме обекти.

Но реалният свят е различен. Обикновено създаваме уеб приложения с живот на заявка-процес-отговор.

Трябва да заредим обекти от постоянна памет като база данни, да работим с тях и да ги запазим отново, докато процесът приключи. Това не отразява реалността, в която всичко работи непрекъснато, този подход не е удобен за домейни.

Хранилище

Цялата идея е, че продължаваме да се преструваме, че имаме колекции. Умни и постоянни колекции, така наречените репозитории. Изглежда, че домейн слоят живее непрекъснато.

Хранилището, подобно на колекцията, носи отговорност за добавяне на обект, получаване на обекти по идентификатор или сложни критерии и евентуално премахване на обект. Има и случаи на използване, които изискват агрегиране като Колко обекта има в системата, Общо количество на всички продукти в склада. За тези случаи на употреба хранилището може да предостави методи за директно агрегиране, така че да не се налага неефективно да извличаме много обекти.

Хранилищата са създадени само за агрегати, защото агрегатите са нашите градивни елементи, нашите единици. Те също винаги работят с целия агрегат, не само с вътрешна част, не с частичен агрегат, винаги с целия агрегат.

Хранилището е внедрено в домейн слоя, тъй като работи с домейн обекти. Но в слоя на домейна не би трябвало да имаме представа за каквато и да е база данни, нито за съхранение, така че хранилището е просто интерфейс.

Постоянство Отговорност

Хранилището може да бъде отговорно за запазването на обекти. Би имало някакъв смисъл да има метод за запазване, който моментално запазва обект.

Но няма такъв случай на използване с колекции от памет, така че ще трябва да въведем инфраструктурни изисквания в домейна. Ако имаше персистираща операция, щяхме да имаме проблеми с транзакциите — един обект се запазва, а вторият причинява изключение, докато продължава, и какво сега?

Решението е просто. Устойчивостта на обекта не е отговорност на хранилището. Някой друг е отговорен за постоянството. Можем да обвием случаите на използване на домейна в слой, който е отговорен за устойчивостта.

Когато използваме усъвършенстван инструмент за постоянство, той обикновено се справя с постоянството чрез изчистване на обектен мениджър. Но все пак е възможно да запазим препратки към обекти, които сме използвали, и да ги изчистим в хранилище, след като случаят на използване на домейна приключи. Тази система също ни позволява да използваме транзакции, ако системата за постоянство ги поддържа.

Конкретно изпълнение

Можем да съхраняваме обекти на домейн в релационна база данни, в база данни с документи, във външна система, свързана чрез API или във всичко друго, което можем да си представим. Всички тези системи са инфраструктура за домейна, така че внедряването на хранилището е в инфраструктурния слой.

Инверсия на зависимостта

В модел на активно запазване на записи и подобни модели домейнът зависи от инфраструктурата. Но ние създадохме интерфейс за хранилище на домейни и внедряването е инфраструктурата. Слоят на домейна все още е независим. За тези, които харесват SOLID, всичко гладко пасва заедно.

Внедряване на паметта

Най-лесният и най-поучителен е внедряването на паметта. Реализация, която просто запазва обектите по време на живот и изобщо не ги запазва.

Внедряването на паметта е полезно за сложни тестове на компоненти или модули. Ние интегрираме повече системни части заедно, но не използваме реалната реализация на хранилището. Тъй като всичко е в паметта, тестовете са бързи и ние все още тестваме целия компонент или модул.

Тест на интерфейса

Можем да пишем тестове за внедряването на паметта и когато интегрираме хранилище на база данни, можем да пишем тестове за интегрирането на базата данни. Но тези тестове могат да бъдат доста сходни, така че можем да мислим за тестване само на интерфейса на хранилището.

Основната идея е, че тестът очаква внедряване на интерфейс. Отговорността на теста не е да се създаде тестваният обект. Тъй като тестът не е отговорен за създаването на обект, той може да стане по-прост.

Най-отдалеченото, което разбирам, е, че тестът е абстрактен клас и тестът за изпълнение разширява абстрактния тест. Бих предпочел да имам един тест с няколко доставчици на внедряване, но не намерих начин да внедря този стил. Ако имате по-добра идея, моля, споделете коментар.

Методът на промиване допълва устойчивостта и започва нов живот на процеса. Реализацията на паметта не го използва и е подготвена за истинско постоянно хранилище.

TL;DR

Репозиториите са постоянни колекции и ни позволяват да се преструваме, че системата е в паметта. Хранилището работи с пълен агрегат и е интерфейс в домейн слоя. Конкретното изпълнение се извършва от инфраструктура, която използваме. Могат да се пишат тестове за интерфейса на хранилището.

Следващия път ще внедрим хранилище на база данни, използвайки Доктрината.

Препратки

КЛЕМСЪН, Тоби. Стратегии за тестване в микросервизна архитектура [онлайн]. 2014 [2018–01–11]. Налично: https://martinfowler.com/articles/microservice-testing/

Еванс, Ерик. Дизайн, управляван от домейн: справяне със сложността в сърцето на софтуера. Бостън: Addison-Wesley, 2004 г. ISBN 0–321–12521–5.

ВЪРНЪН, Вон. Внедряване на дизайн, управляван от домейн. Upper Saddle River, NJ: Addision-Wesley, 2013. ISBN 978–0–321–83457–7.

Пълен код

https://github.com/simara-svatopluk/cart/

Контакт

Проектирате ли архитектура и харесвате DDD подхода? Наемете ме, мога да ви помогна — svatasimara.cz