Ola,

Op advies van enkelen van jullie leek het me een goed idee om van iedere service een apart object te maken wat je vervolgens toevoegt aan een container. Dus we hebben zeg maar een service met wat instellingen en die voegen we toe aan een container.

<?php
$container->add(new Service($instellingen, 'foo'));
$container->add(new Service($instellingen, 'bar'));
?>
Als ik dan een service nodig heb, doe ik:

<?php
$foo = $container->get('foo');
?>
Omdat ik met losse Service objecten werk, weten die niet van elkaars bestaan af. En daar komt mijn "probleem". Stel nu dat de service 'foo' gebruik maakt van de service 'bar', hoe krijg ik dat dan voor elkaar?

Het lijkt mij dan dat het service object 'foo' toegang moet hebben tot de container waar het object in zit. Houdt dit dan in dat ik op het moment dat ik een service object toevoeg aan de container, ik de container als parameter moet meegeven aan het service object, dus zoiets:

<?php
$container->add(new Service($instellingen, 'foo', $container));
?>
Of is er een betere oplossing waardoor de service objecten gebruik kunnen maken van elkaar?
Ja, ik begrijp wel wat je wilt doen, maar...

- je kunt iets dat uit twee stappen bestaat soms beter uit twee lagen opbouwen en

- je hebt soms een singleton nodig terwijl je hebt gelezen dat je dit nooit mag gebruiken ;-)

>> Op het moment dat ik de foo service aanroep, moet er dus een instance worden aangemaakt.

Precies, tenzij je al een foo had en de logica gebiedt dat er maar één foo mag zijn.
Maar de voor mij belangrijkste vraag is op dit moment wat die losse service objecten (die je toevoegt aan de container) behoren te doen. Maken die losse objecten daadwerkelijk zelf de service/instance aan, of bevatten ze alleen de definitie en maakt de container de service/instance aan?
Beide, maar daarom zou ik het ook splitsen en er twee lagen van maken. Eventueel zelfs drie of vier als je bijvoorbeeld een cache gebruikt.

Vereenvoudigd:

- Je hebt bedrijfskritieke services die je áltijd nodig hebt. Die kun je alvast instantiëren.

- Je hebt services die je niet altijd nodig hebt maar die wel kritiek zijn. Daarvan wil je op afroep een instantie hebben.

- Je hebt services die moeten kunnen worden hergebruikt. Die horen in een cache.

- Je hebt services die niet kritiek zijn maar "gewoon handig". Die horen op een extra laag die de andere services niet in gevaar brengt.


Ward, thanks... maar nog niet het antwoord op mijn vraag. De vraag is heel simpel. Ik ga het nog een keertje uitleggen.

Stel we hebben een Ward service met als class => Ward en als parameters name => Ward en status => Put.

Deze gegevens stoppen we in een apart object(X). Dit object stoppen we vervolgens weer in een container(Y), zodat ik de Ward service kan ophalen uit de container op het moment dat ik daar behoefte aan heb. Dus op het moment dat ik de Ward service nodig heb, spreek ik de container aan en krijg ik een Ward object terug: $ward = $container->get('Ward');

Mijn enige vraag is nu... wie gaat (op basis van de class-naam en de parameters) het Ward object aanmaken? Maakt het losse object(X) dit aan, of maakt het container object(Y) dit aan?
>> Maakt het losse object(X) dit aan, of maakt het container object(Y) dit aan?

Dat mag je zelf bepalen. 't is jouw code, er zijn geen regels, er is geen OO wetboek. Je probeert opnieuw te zoeken naar regels en je wordt opnieuw duizelig omdat je ontdekt dat 2 mensen het op 2 verschillende manieren aanpakken. Ik kan je vertellen, haal er een 3de persoon bij en je hebt 3 plannen van aanpak.
Wouter, thanks. Hoe zou jij het zelf dan doen? Maakt bij jou de container of het losse object de instance aan? En stel dat het losse object de instance zou aanmaken, hoe krijgt het losse object dan toegang tot de container? Heb je daar een idee over?
Ik zou een ServiceProcessor class maken die doormiddel van de ServiceDefinition en de Container een service aanmaakt:
<?php
class Container
{
// ...
public function get($id)
{
if (isset($this->instances[$id])) {
return $this->instances[$id];
} elseif (isset($this->services[$id])) {
$service = $this->serviceProcessor->process($this->services[$id], $container);

if ($this->services[$id]->isShared()) {
$this->instances = $service;
}

return $service;
} else {
throw new UnknownServiceException::serviceNotAvailable();
}
}
}
?>
Ah, thanks Wouter! En die serviceProcessor geef je die dan mee als parameter aan de constructor van de container?
Ik zou iets als dit hanteren:
<?php

class Container
{
protected $serviceProcessor;

public function __constuct(ServiceProcessor $processor = null)
{
$this->serviceProcessor = $processor ?: new ServiceDefinitionProcessor();
}
}
?>
Op deze manier kun je een custom service processor gebruiken, maar default je tot een processor voor service definitions.
Ah oké... ik snap 'm. Thanks :)

Reageren