Hey 
Wellicht dat de titel niet helemaal het correcte beeld vormt over het probleem, maar ik zit nu met het volgende. Het doel van mijn vraag is niet zozeer om tot een geweldige, waterdichte oplossing te komen, maar meer om even te brainstormen en tot nieuwe inzichten te komen.
Inleiding
Beschouw de entiteiten A en B. Beide entiteiten hebben een eigen tabel, waarbij er een relatie 1:n bestaat voor deze entiteiten. Met andere woorden: de rows in tabel B hebben een foreign key naar een row in tabel A. Een entiteit B kan dus niet bestaan zonder een "parent" entiteit A. Een correcte analogie hiervoor is bijvoorbeeld een systeem betreffende een paar huizen met kamers. Een kamer behoort toe aan één huis en kan bovendien niet bestaan zonder een huis. Wanneer je een huis met de grond gelijk maakt, moeten de kamers ook worden verwijderd.
Op de server gebruik ik een arbitraire database-abstractie adapter (bijvoorbeeld PDO) om CRUD-bewerkingen uit te voeren. Ik heb een abstracte klasse geschreven met generieke code en functies waarbij ik één model per entiteit die klasse laat extenden. Dus:
Binnen deze klasse worden de PDO-objecten gecreëerd, worden de mySQL queries gegenereerd en uitgevoerd, enzovoort. Dit is de business logic van mijn applicatie.
Het probleem
Het probleem hier is dat ik enerzijds loosely coupled code wil hebben. De klassen MyProject_Model_EntA en MyProject_Model_EntB functioneren op dit niveau dus compleet los van elkaar.
Echter bestaat er op database-niveau wél een relatie tussen deze twee entiteiten. Ik kan niet zomaar een delete() method aanroepen van de MyProject_Model_EntA klasse, omdat daarbij ook een n-aantal entiteiten B moeten worden verwijderd alvorens het verwijderen van de entiteit A.
Mogelijke oplossingen
• Om bovenstaand voorbeeld door te trekken kan ik simpelweg de benodigde code voor het verwijderen van entiteiten B in de klasse MyProject_Model_EntA gooien, met een aparte functie of iets dergelijks. Dit is echter error-prone en je gaat bestaande, werkende code lopen bewerken.
• Het Observer-pattern gebruiken en zo de code aan elkaar knopen. Dit is mijn huidige oplossing voor het huidige probleem. Echter creëer je hiermee nóg een laag code bovenop de bestaande code, maar blijft je code wel netjes schoon. Een zeer groot voordeel is dat je gemakkelijk functionaliteit kunt toevoegen zonder bestaande code te wijzigen. Echter is mijn bezwaar hiertegen dat het semantisch niet he-le-maal klopt, omdat de code niet meer werkt wanneer je de desbetreffende observer (die verantwoordelijk is voor het verwijderen van children entities) loskoppelt. En laat dat nou precies hetgeen zijn wat het observer-pattern zou moeten oplossen: afhankelijkheden tussen code.
• De foreign keys helemaal verwijderen en alle logic op applicatie-niveau afhandelen.
Graag zie ik wat commentaar op bovenstaande mogelijkheden en wellicht dat er zelfs nog andere wegen naar Rome zijn.
Wellicht dat de titel niet helemaal het correcte beeld vormt over het probleem, maar ik zit nu met het volgende. Het doel van mijn vraag is niet zozeer om tot een geweldige, waterdichte oplossing te komen, maar meer om even te brainstormen en tot nieuwe inzichten te komen.
Inleiding
Beschouw de entiteiten A en B. Beide entiteiten hebben een eigen tabel, waarbij er een relatie 1:n bestaat voor deze entiteiten. Met andere woorden: de rows in tabel B hebben een foreign key naar een row in tabel A. Een entiteit B kan dus niet bestaan zonder een "parent" entiteit A. Een correcte analogie hiervoor is bijvoorbeeld een systeem betreffende een paar huizen met kamers. Een kamer behoort toe aan één huis en kan bovendien niet bestaan zonder een huis. Wanneer je een huis met de grond gelijk maakt, moeten de kamers ook worden verwijderd.
Op de server gebruik ik een arbitraire database-abstractie adapter (bijvoorbeeld PDO) om CRUD-bewerkingen uit te voeren. Ik heb een abstracte klasse geschreven met generieke code en functies waarbij ik één model per entiteit die klasse laat extenden. Dus:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| interface MyProject_Model_Interface { //Interface containing relevant CRUD-methods } abstract class MyProject_Model_Abstract implements MyProject_Model_Interface { //Implementation } class MyProject_Model_EntA extends MyProject_Model_Abstract { //Implementation } class MyProject_Model_EntB extends MyProject_Model_Abstract { //Implementation } |
Binnen deze klasse worden de PDO-objecten gecreëerd, worden de mySQL queries gegenereerd en uitgevoerd, enzovoort. Dit is de business logic van mijn applicatie.
Het probleem
Het probleem hier is dat ik enerzijds loosely coupled code wil hebben. De klassen MyProject_Model_EntA en MyProject_Model_EntB functioneren op dit niveau dus compleet los van elkaar.
Echter bestaat er op database-niveau wél een relatie tussen deze twee entiteiten. Ik kan niet zomaar een delete() method aanroepen van de MyProject_Model_EntA klasse, omdat daarbij ook een n-aantal entiteiten B moeten worden verwijderd alvorens het verwijderen van de entiteit A.
Mogelijke oplossingen
• Om bovenstaand voorbeeld door te trekken kan ik simpelweg de benodigde code voor het verwijderen van entiteiten B in de klasse MyProject_Model_EntA gooien, met een aparte functie of iets dergelijks. Dit is echter error-prone en je gaat bestaande, werkende code lopen bewerken.
• Het Observer-pattern gebruiken en zo de code aan elkaar knopen. Dit is mijn huidige oplossing voor het huidige probleem. Echter creëer je hiermee nóg een laag code bovenop de bestaande code, maar blijft je code wel netjes schoon. Een zeer groot voordeel is dat je gemakkelijk functionaliteit kunt toevoegen zonder bestaande code te wijzigen. Echter is mijn bezwaar hiertegen dat het semantisch niet he-le-maal klopt, omdat de code niet meer werkt wanneer je de desbetreffende observer (die verantwoordelijk is voor het verwijderen van children entities) loskoppelt. En laat dat nou precies hetgeen zijn wat het observer-pattern zou moeten oplossen: afhankelijkheden tussen code.
• De foreign keys helemaal verwijderen en alle logic op applicatie-niveau afhandelen.
Graag zie ik wat commentaar op bovenstaande mogelijkheden en wellicht dat er zelfs nog andere wegen naar Rome zijn.