Het service locator pattern
In deel 1 van deze serie hebben we gekeken hoe we door handmatige dependency injection de bovenstaande code beter kunnen laten voldoen aan de SOLID principes en beter kunnen testen.
We hebben hier gezien dat we door handmatige dependency injection maar deels in staat zijn om de code beter losgekoppeld te krijgen. Uiteindelijk is er een plek in de code waar je de concrete implementaties van objecten moet meegeven en dat maakt dat deze manier van werken bij een echte applicatie vaak al snel niet meer werkt doordat er een hele boom aan afhankelijkheden moet worden doorgegeven.
Voldoen aan het Inversion Principle door een service locator
Om dit probleem te omzeilen kan gebruik worden gemaakt van het service locator pattern. Als je informatie over dit pattern inzamelt op internet dan zul je zien dat het een veelbesproken pattern is en dat het voor nieuwbouwprojecten eigenlijk altijd als anti-pattern wordt benoemd. Dat neemt niet weg dat het in legacy projecten soms de enige werkbare manier is om verbeteringen in de code door te voeren. Door het implementeren van een service locator zijn de classes wederom niet afhankelijk van elkaar. In het bovenliggende voorbeeld geeft de servicelocator simpelweg een instantie terug van een object. Dit komt het dichtst in de buurt van legacycode waarin overal nieuwe instanties worden aangemaakt.
Voordeel van het service locator pattern
- We zijn nu in staat om de Presentation en Service objecten eenvoudig te unit testen.
- De Presentation en Service objecten zijn niet afhankelijk van concrete implementaties, maar van interfaces, dus we kunnen verschillende implementaties ondersteunen zonder deze objecten aan te passen.
- We hoeven afhankelijkheden niet mee te geven, deze worden opgehaald bij de Service Locator en hierdoor hoef je niet in je code rekening te houden met allerlei afhankelijkheden die lagergelegen in de code nodig zijn (zoals bij het handmatig injecteren in het vorige artikel).
- Voor legacy projecten komt dit pattern vaak het dichtst in de buurt bij de huidige implementatie en is daardoor vrij eenvoudig door te voeren.
Nadeel
- Er ontstaat in je code een afhankelijkheid van de service locator, waar je niet meer zo eenvoudig van af komt.
- De service locator zal normaal gesproken geen lifecycle management van objecten uitvoeren waardoor je soms teveel instanties van objecten genereert (dit speelt vooral in projecten waar de architectuur al SOLID is opgezet en de service locator eerder in de weg zit dan iets toevoegt). In principe kun je natuurlijk je Service Locator uitbreiden (een hoop IOC-frameworks bieden ook een service locator pattern optie) maar in die gevallen is het aan te raden om volledig op een IOC-framework manier van werken over te gaan.
In het volgende artikel zal ik toelichten hoe je met IOC-frameworks kunt werken om in nieuwbouw maximale ontkoppeling tussen objecten te bereiken zonder de nadelen van het service locator pattern.
Auteur: Menno Jongerius, Bergler Competence Center 2017