[OOP] Omgang met Containers en Componenten

Pagina: 1
Acties:

  • Mars Warrior
  • Registratie: Oktober 2003
  • Laatst online: 08:32

Mars Warrior

Earth, the final frontier

Topicstarter
Ik zit nu in een project waar de teamleden Spring.NET hebben ontdekt en hiermee lekker aan de slag zijn gegaan.

Er wordt driftig gebruik gemaakt van de config file en van Containers en Componenten. De Componenten zijn hierbij Container-aware en de Container heeft een lijst van de Componenten. Het toevoegen van een Component aan de Container gaat middels container.Add(component) en het zetten van de Container gaat middels een property op de Component: de Container property.

Tot zover is alles identiek.
Nu blijkt dat een ieder zijn eigen manier heeft om om te gaan met Containers en Componenten als het gaat om het verbinden van deze 2. Let op dat de Componenten prototypes zijn, en dus niet automatisch door Spring.NET worden geladen:

1.
a. De Container wordt gedefinieerd in de config file
b. De Componenten ook, waarbij middels DI de Container property wordt gezet
c. De Container heeft een init method die vanuit Spring wordt aangeroepen en die de Componenten laadt.
d. De Container roept per Component zelf zijn this.Add(component) method aan

2.
Als 1, maar vanaf d. gaat het anders:
d. De Component roept zelf vanuit zijn Container set property de method container.Add(this) aan om zichzelf aan de lijst toe te voegen.

3.
a. De Container wordt gedefinieerd in de config file
b. De Componenten ook, echter zonder DI van de Container
c. De Container heeft een init method die vanuit Spring wordt aangeroepen en die de Componenten laadt.
d. De Container roept per Component zelf zijn this.Add(component) method aan
e. De Container zet per Component de Container property naar zichzelf

4.
Als 3, maar het binden vindt BUITEN de Container plaats, nl in een init method van het hoofdprogramma.

5.
Een andere aanpak:
a. Deze persoon heeft al zijn objecten die "automatisch" aangemaakt moeten worden in een aparte sub-context ("AutoLoad" genaamd) gezet
b. Een aparte method laad ALLE objecten binnen deze context, dwz doet een GetObject() van alle objecten.
c. Er wordt gebruik gemaakt van DI om de Container property te zetten en van het feit dat als deze wordt gezet, het Component zelf de container.Add(this) method aanroept

Problemen:
a. Het probleem bij 1 en 2 is dat de binding niet gegarandeerd is, immers de Container die het Component laadt, hoeft niet dezelfde te zijn als waarvan in de config file de Container middels DI is gedefinieerd, oftewel de Container kan een Component in zijn lijst hebben staan, maar de Component wijst naar een andere Container...
b. Bij 3 en 4 treedt dit probleem niet op, maar is het binden weer volledig handwerk en wordt het nut van Spring / DI weer minder
c. Bij 5 is alles geautomatiseerd EN klopt altijd de wederzijdse verbinding tussen Container en Component.

Ik streef naar 1 werkmethode, en vind methode 5 wel elegant, maar vraag me af of dit nu ook de beste is, oftewel hoe doen anderen dit??

PS. Er is dus geen gebruik gemaakt van het feit om bij de Container ook de Componentenlijst te definieren. Dit blijkt teveel werk te zijn en te foutgevoelig, zeker als het om honderden objecten gaat!

[ Voor 3% gewijzigd door Mars Warrior op 16-07-2006 23:32 ]

Material 3 Thema's voor HA | Swiss Army Knife custom card voor HA | AmoebeLabs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

De components horen in 99% van de gevallen niet af te weten van Spring. Singleton beans definieer ik altijd in de app context en ik injecteer ook alle dependencies vanuit de app context in deze components. Het is in 99% van de gevallen verboden om een component met de appcontext te laten communiceren. Het gevolg van deze verboden aanpak is dat je componenten 2 verantwoordelijkheden krijgen:
1 core verantwoordelijkheid voor zijn basis functionaliteit
2 ophalen van zijn dependencies

De kracht van spring zit hem juist in het feit dat je die 2e verantwoordelijkheid legt bij de appcontext en niet meer bij het component.

Als je prototype beans wilt maken, dan werk je dus gewoon via een factory. Een standaard design pattern waarmee je de verantwoordelijkheid object constructie uit een component kunt halen. De factory bean lijm je gewoon op in Spring als een standaard bean en injecteer je vanuit de app context in alle components die hem nodig zijn.

Ik ben verder niet bekend met Spring.NET maar ik neem aan dat het niet veel anders is dan de Java versie En kijk verder even naar een goed boek, wellicht dat Spring in Action aardig voor jullie is. Als je wilt mag je hier anders ook wel een stuk code + config file plaatsen, dan zal ik even kijken of ik de tijd heb om kritiek erop te geven.

[edit]
1) waarom wil je een component list?
2) ik neem aan dat je die ook aan de app context kunt vragen

[ Voor 20% gewijzigd door Alarmnummer op 17-07-2006 06:42 ]


  • Mars Warrior
  • Registratie: Oktober 2003
  • Laatst online: 08:32

Mars Warrior

Earth, the final frontier

Topicstarter
Alarmnummer schreef op maandag 17 juli 2006 @ 06:20:
De components horen in 99% van de gevallen niet af te weten van Spring. Singleton beans definieer ik altijd in de app context en ik injecteer ook alle dependencies vanuit de app context in deze components. Het is in 99% van de gevallen verboden om een component met de appcontext te laten communiceren. Het gevolg van deze verboden aanpak is dat je componenten 2 verantwoordelijkheden krijgen:
1 core verantwoordelijkheid voor zijn basis functionaliteit
2 ophalen van zijn dependencies

De kracht van spring zit hem juist in het feit dat je die 2e verantwoordelijkheid legt bij de appcontext en niet meer bij het component.
Helder. Eigenlijk keur je hiermee alle 5 manieren af als ik het zo even kort evalueer ;)
Als je prototype beans wilt maken, dan werk je dus gewoon via een factory. Een standaard design pattern waarmee je de verantwoordelijkheid object constructie uit een component kunt halen. De factory bean lijm je gewoon op in Spring als een standaard bean en injecteer je vanuit de app context in alle components die hem nodig zijn.
Tja, geef een ontwerper/programmeur (en dan ook nog eens onervaren) iets nieuws en ze willen alles met dat nieuwe doen. Een factory ben ik in de code niet tegengekomen, terwijl spring dat toch zeker ondersteund :(
Ik ben verder niet bekend met Spring.NET maar ik neem aan dat het niet veel anders is dan de Java versie En kijk verder even naar een goed boek, wellicht dat Spring in Action aardig voor jullie is. Als je wilt mag je hier anders ook wel een stuk code + config file plaatsen, dan zal ik even kijken of ik de tijd heb om kritiek erop te geven.
Spring.NET is inderdaad niet veel anders (soms helaas, soms prettig) dan Spring for Java. Ut loopt wat achter al heeft het wel ondersteuning voor C# generics en de boontjes zijn vervangen door objecten ;)
Het boek houdt ik even in gedachten. Het probleem is dat het om een kortlopend project gaat waar een ervaren Spring.NET man op zat die en mensen moest opleiden en de architectuur moest bepalen maar die is plotseling iets anders gaan doen. En wat ik nu constateer is dat diegene in beide punten niet is geslaagd! Ik mag nu de pijnpunten gaan aanpakken, maar zit dus niet mega-diep in Spring's Do's and Don'ts om zonder meer te kunnen 'hakken' en refactoren gezien de tijd ook mogelijk geen optie is 8)
[edit]
1) waarom wil je een component list?
2) ik neem aan dat je die ook aan de app context kunt vragen
Er worden om meerdere redenen containers gebruikt die inderdaad oa fungeren als componenten lijst, maar ook een stuk verantwoordelijkheid over die componenten hebben (de te injecteren factory zijn ze alleen vergeten ;)) en daarbij de code een stuk eenvoudiger/duidelijker moeten maken. En of je dat nu ziet als Container, Manager of Broker, da's een naampje denk ik dan maar:
a) Beheer en aanmaken van componenten (soms tot 80.000 in aantal)
b) Afhandeling en filtering van events en rerouten van events naar afnemers (tis natuurlijk veel eenvoudiger om dat aan een container dat te vragen voor alle objecten in 1 keer, dan alle 80.000 objecten af te moeten lopen bijv...)
c) De componenten mogen elkaar niet kennen, maar sommige functies gaan over componenten heen. Voor deze functies wordt of de container gebruikt, of zit de functie in de container zelf
d) Concreet kun je denken aan een kast (== container) met I/O kaarten (== component voor de kast, maar ook weer een container voor -->) met op die I/O kaarten sensoren (== componenten). Valt er nu een kaart in storing, dan onderdrukt deze de foutmeldingen van de sensoren en invalideert tevens richting afnemers de data van de sensoren, waarbij hij ook een trigger geeft aan de kast dat deze een storing heeft...

enne opvragen aan de app context betekent dat ik op heel veel plekken afhankelijk wordt van Spring, iets wat geloof ik niet de bedoeling is O-)

Dan als laatste nog even een vraag:
Als we gebruik maken van factories, en de prototype objecten definieren in de config file, worden deze objecten dan automatisch aangemaakt door de factory aan te roepen, of moet daar vanuit de software actie worden ondernomen?

Material 3 Thema's voor HA | Swiss Army Knife custom card voor HA | AmoebeLabs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Mars Warrior schreef op maandag 17 juli 2006 @ 13:09:
Er worden om meerdere redenen containers gebruikt die inderdaad oa fungeren als componenten lijst, maar ook een stuk verantwoordelijkheid over die componenten hebben (de te injecteren factory zijn ze alleen vergeten ;)) en daarbij de code een stuk eenvoudiger/duidelijker moeten maken. En of je dat nu ziet als Container, Manager of Broker, da's een naampje denk ik dan maar:
a) Beheer en aanmaken van componenten (soms tot 80.000 in aantal)
b) Afhandeling en filtering van events en rerouten van events naar afnemers (tis natuurlijk veel eenvoudiger om dat aan een container dat te vragen voor alle objecten in 1 keer, dan alle 80.000 objecten af te moeten lopen bijv...)
c) De componenten mogen elkaar niet kennen, maar sommige functies gaan over componenten heen. Voor deze functies wordt of de container gebruikt, of zit de functie in de container zelf
d) Concreet kun je denken aan een kast (== container) met I/O kaarten (== component voor de kast, maar ook weer een container voor -->) met op die I/O kaarten sensoren (== componenten). Valt er nu een kaart in storing, dan onderdrukt deze de foutmeldingen van de sensoren en invalideert tevens richting afnemers de data van de sensoren, waarbij hij ook een trigger geeft aan de kast dat deze een storing heeft...
Als ik meer tijd heb zal ik hier nog even naar kijken. Als andere spring pro's hier antwoord op weten, dan hier aub ff naar kijken.
enne opvragen aan de app context betekent dat ik op heel veel plekken afhankelijk wordt van Spring, iets wat geloof ik niet de bedoeling is O-)
Afhankelijkheid naar spring is idd vervelend. Maar de extra verantwoordelijkheid van het object, beperkt ook zijn inzetbaarheid.
Dan als laatste nog even een vraag:
Als we gebruik maken van factories, en de prototype objecten definieren in de config file, worden deze objecten dan automatisch aangemaakt door de factory aan te roepen, of moet daar vanuit de software actie worden ondernomen?
voorbeeld zegt meer dan 1000 woorden.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class FruitFactory{

    private String naam;

    public void setNaam(String naam){
        this.naam = naam;
    }
    Fruit create(){return new Fruit("naam"));
}

class Fruitschaal[
    int aantal;
   List fruitList = new LinkedList();

   public void setAantal(int aantal){
       this.aantal = aantal;
   }

   public void setFruitFactory(){
        this.fruitFactory = fruitFactory;
   }

   public void vul(){
       fruitList.clear();
       for(int k=0;k<aantal;k++){
           Fruit fruit = fruitFactory.create();
           fruitList.add(fruit);
       }
   }
}

<bean id="fruitFactory" class="FruitFactory">
     <property name="naam" value="peer"/>
</bean>

<bean id="fruitschaal" class="FruitSchaal">
    <property name="aantal" value="15"/>
    <property name="fruitFactory" ref="fruitFactory"/>
</bean>

  • Mars Warrior
  • Registratie: Oktober 2003
  • Laatst online: 08:32

Mars Warrior

Earth, the final frontier

Topicstarter
Alarmnummer schreef op maandag 17 juli 2006 @ 18:38:
[...]

Als ik meer tijd heb zal ik hier nog even naar kijken. Als andere spring pro's hier antwoord op weten, dan hier aub ff naar kijken.

[...]
Ik vergat natuurlijk weer ff dat je een Java man bent, dus mogelijk dat dit verhaaltje (dat ook naar Fowler refereert) ff wat meer zegt waarom Containers/Componenten een beetje popi zijn in .NET.
voorbeeld zegt meer dan 1000 woorden.
Bijna zou ik zeggen ;)
Ik lees hieruit het volgende:
1. De factory is een singleton en wordt dus vanuit Spring aangemaakt door GetContext() aan te roepen.
2. Hetzelfde geldt voor de FruitSchaal
3. Echter de FruitSchaal moet wel worden ge-Get() en vervolgens moet de vul() method worden aangeroepen om de schaal ook te vullen...

Er is hier (zo lijkt het) behoeft aan het automatisch vullen van eea. Ik denk echter dat dit stom eenvoudig te bereiken is met dit voorbeeld door vanuit de constructor van de FruitSchaal (al dan niet optioneel middels een constructor argument) de vul() method aan te roepen om de wens van het volledig automatisch aanmaken van singleton en prototype objecten voor elkaar te krijgen, en dat op 1 duidelijke manier (tegen de 5 die ik nu al ben tegengekomen...), of zit ik helemaal mis :X

Material 3 Thema's voor HA | Swiss Army Knife custom card voor HA | AmoebeLabs


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Mars Warrior schreef op maandag 17 juli 2006 @ 20:31:
Ik vergat natuurlijk weer ff dat je een Java man bent, dus mogelijk dat dit verhaaltje (dat ook naar Fowler refereert) ff wat meer zegt waarom Containers/Componenten een beetje popi zijn in .NET.
Ik had geen tijd/zin om het door te lezen en om erover na te denken. En van fowler heb ik wel eens iets gehoord.. schijnt dat hij boeken schrijft.
Bijna zou ik zeggen ;)
Ik lees hieruit het volgende:
1. De factory is een singleton en wordt dus vanuit Spring aangemaakt door GetContext() aan te roepen.
getContext? Die factory is op alle plekken geinjecteerd waar het nodig is en je hoeft daarom dus niet zelf ook nog eens het object te op te halen om het in een bepaald object te plaatsen (dat is de taak van de app context).
2. Hetzelfde geldt voor de FruitSchaal
zie mijn vorig verhaal. Uiteindelijk zal je wellicht je top level objecten (je service laag objecten) wellicht op moeten halen omdat niet alle objecten opgebouwd kunnen worden in spring.
3. Echter de FruitSchaal moet wel worden ge-Get() en vervolgens moet de vul() method worden aangeroepen om de schaal ook te vullen...
Een fruitschaal is bv een dependency van een tafel, dus de tafel heeft weer een dependency die gezet kan worden vanuit de app context (en die zelf dus ook opgelijmt kan worden op die plek).
Dus in principe hoeft niemand te getten... En die vul.. tja.. ligt aan het context waarin het gebruikt gaat worden. Misschien koppel je er wel een timer aan vast die iedere dag de fruitschaal vult. Dit kan je ook volledig oplijmen vanuit spring. Dus niemand moet de appcontext aanspreken met get (in de meeste gevallen).

Volgens mij is dit jouw grote probleem.
Er is hier (zo lijkt het) behoeft aan het automatisch vullen van eea. Ik denk echter dat dit stom eenvoudig te bereiken is met dit voorbeeld door vanuit de constructor van de FruitSchaal (al dan niet optioneel middels een constructor argument) de vul() method
als je om een of andere reden die fruitschaal wilt verversen (bv iedere dag, of omdat de pest uitgebroken is in de buurt) dan wil je wel bij die vul methode kunnen komen. Je wilt dus niet automatisch die vul methode alleen aan kunnen roepen bij die constructor.
aan te roepen om de wens van het volledig automatisch aanmaken van singleton en prototype objecten voor elkaar te krijgen, en dat op 1 duidelijke manier (tegen de 5 die ik nu al ben tegengekomen...), of zit ik helemaal mis :X
[/quote]
Volgens mij heb je het nog mis. De meeste 'belangrijke' objecten lijm je op in spring. In een ideale wereld zou je alle belangrijke objecten oplijmen, maar je zit helaas vast aan wat boostrapping crap. Dus vandaar dat je soms wel eens een appcontext.get zult moeten aanroepen. Maar realiseer je wel dat dit een uitzondering is en niet een normale manier van werken. Ik ben trouwens niet bekend met spring.net dus ik weet niet hoe vaak je daar een appcontext.get moet doen. Maar het lijkt me niet al te vaak omdat je dan gewoon veel te hard aan de spring container bent gekoppeld en dat is niet goed.

  • Mars Warrior
  • Registratie: Oktober 2003
  • Laatst online: 08:32

Mars Warrior

Earth, the final frontier

Topicstarter
Alarmnummer schreef op maandag 17 juli 2006 @ 20:49:
Ik had geen tijd/zin om het door te lezen en om erover na te denken. En van fowler heb ik wel eens iets gehoord.. schijnt dat hij boeken schrijft.
* Mars Warrior kijkt in zijn boekenkast en ziet ze tot zijn verbazing iets bij de "F" staan...
Volgens mij heb je het nog mis. De meeste 'belangrijke' objecten lijm je op in spring. In een ideale wereld zou je alle belangrijke objecten oplijmen, maar je zit helaas vast aan wat boostrapping crap. Dus vandaar dat je soms wel eens een appcontext.get zult moeten aanroepen. Maar realiseer je wel dat dit een uitzondering is en niet een normale manier van werken. Ik ben trouwens niet bekend met spring.net dus ik weet niet hoe vaak je daar een appcontext.get moet doen. Maar het lijkt me niet al te vaak omdat je dan gewoon veel te hard aan de spring container bent gekoppeld en dat is niet goed.
Ik denk dat het nog wel meevalt en dat ik het niet erg goed heb uitgelegd ;)

1. In het hoofdprogramma wordt eenmalig:
code:
1
          IApplicationContext ctx = ContextRegistry.GetContext();
uitgevoerd, verder nergens...

2. Er wordt een ctx.GetObject() gedaan van het ApplicationState object om hierop uiteindelijk de Start() method aan te roepen zodat de services (en dus alles wat daaraan hangt) starten...
In principe wordt verder nergens een afhankelijkheid van spring gecreeerd, enkel dus deze 2 calls...
3. Er wordt zoveel mogelijk gebruik gemaakt van het lijmen van de objecten dmv spring dat goed werkt zolang het om singletons gaat. Deze zijn verder met DI zeer goed te configureren, te wijzigen en dus ook te testen (mockups). En man-o-man, wat scheelt dat toch een uren programmeerwerk :9
4. De programmeurs hebben blijkbaar problemen met het gebruik van prototype objecten (de 5 manieren) waarvoor jij met je fruit voorbeeld een mooi alternatief hebt aangegeven waar dus totaal niet aangedacht is. En of deze fruitschaal nu automatisch gevuld wordt, of zoals je aangeeft middels een timer of andere dingen, was voor mij even niet zo relevant: mijn 'ontdekking' (door jou voorbeeld _/-\o_ ) dat ze totaal geen gebruik maken van factories was voor mij even het belangrijkste gemis... En ik was blijkbaar zo afgeleid door het Container/Componenten verhaal dat ik het basisprincipe hoe maak ik objecten aan even totaal vergat |:(

Komende week eens kijken hoe ik dit injecteer in de hoofden van de programmeurs O-)

Material 3 Thema's voor HA | Swiss Army Knife custom card voor HA | AmoebeLabs

Pagina: 1