Moet repository ook child models deleten?
Een product kan product attributen hebben. (Zoals kleur, maat, gewicht...)
Een ProductAttribute kan aan meerdere producten worden gekoppeld. Het is eigenlijk de definitie van een product attribuut.
ProductAttributeRelation maakt de link tussen een Product en een ProductAttribute.
De ProductAttributeRelation heeft dan ook o.a. de volgende velden: product_id, attribute_id en value.
De value is dan de waarde die geldt voor het attribuut voor dat specifieke product.
Ik gebruik het repository design pattern voor alle data. Ik heb een Product repository en een ProductAttribute repository, maar géén ProductAttributeRelation repository.
Nu wil ik in de Product repository een functie implementeren om een product te verwijderen. Ik vraag me af of ik in die repository dan ook de verwijdering van de ProductAttributeRelation's moet implementeren, of dat dat daar niet hoort. Namelijk, als een product wordt verwijderd, moeten natuurlijk ook de relaties tussen dat product en attributen worden verwijderd, want deze ProductAttributeRelation's stellen dan niets meer voor en zouden dan voor altijd zwerven. Dus: dát die relaties moeten worden verwijdered is zeker, maar zou ik dat dan in die product repository moeten doen, of zou ik toch een aparte repository moeten maken voor ProductAttributeRelation?
De ProductAttributeRelation models zijn eigenlijk meer iets voor achter de schermen van de datalayer, ze representeren voornamelijk de database structuur en niet zo zeer de business models/classes structuur.
Zoals een product in de business logic code voorkomt, heeft deze class gewoon een array met zijn ProductAttribute instances die op hun beurt de juiste waarde hebben die voor het product geldt. De class ProductAttributeRelation wordt eigenlijk dus niet gebruikt in de business logic.
Dus mijn vraag: moet in de product repository ook gewoon zorg worden gedragen om de relaties netjes te verwijderen, of zou er toch een aparte repository moeten komen? Dus dat de business layer de taak heeft om de product repository aan te roepen "verwijder dit product" en daarna de ProductAttributeRelation repository aan te roepen "verwijder attribuut relaties die bij product X horen".
Niks "moet", tenzij er sprake is van een beveiligingsrisico. Je vraag zou je dan ook beter kunnen stellen als "wat is handig" of "wat is logisch" of "wat werkt prettig". Volgens mij gebruik je een custom werkwijze waaraan je zelf een invulling hebt gegeven. Ik zou de vraag dan ook vooral aan jezelf stellen. Wat lijkt jou zelf handig? Waar vind jij dat de relaties verwijderd moeten worden? Hou je niet teveel vast aan het idee dat iets "moet".
Mark Hogeveen op 02/05/2023 19:05:27:
Dus mijn vraag: moet in de product repository ook gewoon zorg worden gedragen om de relaties netjes te verwijderen?
Ja, dat MOET. ;-)
Als je een stapje terug zet om wat afstand te nemen van de concrete implementatie, zie je dat deze consequentie logisch volgt uit je model. In een entity-attribute-value-model (EAV-model) kan er onmogelijk een relatie bestaan tussen een entiteit en een attribuut als de entiteit niet meer bestaat. Zonder producten hebben de eigenschappen van die producten geen betekenis.
Kijk je wel naar de concrete implementatie, dan vind je daarin nog een technische reden: het is efficiënter om in één keer met een ON DELETE CASCADE alle aan een entiteit gerelateerde data te verwijderen.
Daarmee heb je twee goede redenen, een theoretische en een praktische, waarom het MOET. Toch zou ik het anders oplossen, om twee andere goede redenen.
Ten eerste is het in oplossingen voor product information management (PIM) ongebruikelijk om producten te verwijderen. Daarvoor bestaan onder andere juridische redenen (zoals productaansprakelijkheid en garantie) en marketingtechnische redenen: je wilt weten wanneer en liever nog waarom rode widgets beter verkopen dan blauwe, dus producten én hun attributen verwijder je niet.
Ten tweede is het verwijderen van 'child models' — of eigenlijk: value objects —helemaal niet de taak van een repository. Een repository is middleware die dit delegeert aan databasefaciliteiten zoals factories en mappers. In domain-driven design (DDD) gebruik je repositories daarom eigenlijk alleen voor aggregate roots, dus in jouw geval voor producten.
Kortom, je verwacht concreet dat de repository ergens een DATETIME laat opslaan die "dit product was leverbaar tot en met ..." betekent.
Gewijzigd op 03/05/2023 09:41:42 door Ward van der Put
Dank jullie wel voor de reacties!