[Alg] Collections / Business Entities

Pagina: 1
Acties:
  • 101 views sinds 30-01-2008
  • Reageer

  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
Ik zat me net ff af te vragen: welk 'ontwerp' is eigenlijk beter als het gaat om bv. business objecten die een (of meerdere) collections hebben.

Stel voorbeeld a:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyCustomerDomainObject
{
     ...
     private IList  _orders;

     public void AddOrder( Order o )
     {
         _orders.Add (o);
     }

     public Order[] GetOrders() 
     {
         return _orders.ToArray();
     }

}


voorbeeld b:
code:
1
2
3
4
5
6
7
8
9
class MyCustomerObject
{
     private IList _orders;

     public IList Orders
     {
         get{ return _orders; }
     }
}


Wat is eigenlijk best practice ?
In voorbeeld a scherm je die collectie veel beter af dan in voorbeeld b, maar in voorbeeld a verlies je dan wel weer wat flexibiliteit.

Als je een domein-class hebt met veel collecties, tja, dan ga je - als je voorbeeld a toepast - natuurlijk een helehoop Adddit en Adddat, Removedit, etc... methods gaan hebben.

https://fgheysels.github.io/


  • djc
  • Registratie: December 2001
  • Laatst online: 08-09-2025

djc

Als ik even onbehulpzaam mag zijn: ik vind het allebei lelijk. In andere talen zou je het zo kunnen doen dat je .orders min of meer transparant toegankelijk maakt, terwijl je de mogelijkheid openlaat dat je op een later moment de .orders access gaat afvangen zodat je extra functionaliteit kan toevoegen zonder dat de calling code hoeft te veranderen.

Rustacean


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyCustomObjectCollection
{
     private IList  _orders;

     public void Add( MyCustomObject o )
     {
         _orders.Add (o);
     }

     public MyCustomObject[] ToArray() 
     {
         return _orders.ToArray();
     }
}


Dit vind ik de mooiste oplossing. Dus eigelijk zoals jij al aangaf, voorbeeld A.
Manuzhai schreef op dinsdag 06 september 2005 @ 20:53:
Als ik even onbehulpzaam mag zijn: ik vind het allebei lelijk. In andere talen zou je het zo kunnen doen dat je .orders min of meer transparant toegankelijk maakt, terwijl je de mogelijkheid openlaat dat je op een later moment de .orders access gaat afvangen zodat je extra functionaliteit kan toevoegen zonder dat de calling code hoeft te veranderen.
Dit zou je kunnen oplossen door je bijvoorbeeld MyCustomObjectCollection uit te bereiden met Events. Op deze events kun je dan weer reageren. Ook kun je aan MyCustomObjectCollection bijvoorbeeld de method GetTotalPrice toevoegen of misschien GetOpenOrders die alle open orders uit de collection terug geeft.

  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
questa schreef op dinsdag 06 september 2005 @ 22:57:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyCustomObjectCollection
{
     private IList  _orders;

     public void Add( MyCustomObject o )
     {
         _orders.Add (o);
     }

     public MyCustomObject[] ToArray() 
     {
         return _orders.ToArray();
     }
}


Dit vind ik de mooiste oplossing. Dus eigelijk zoals jij al aangaf, voorbeeld A.
Niet helemaal; in jouw voorbeeld heb je het over een 'CustomCollection', terwijl het bij mij eerder een business object is; bv. 'Customer', die een collection heeft.
Manuzhai schreef op dinsdag 06 september 2005 @ 20:53:
Als ik even onbehulpzaam mag zijn: ik vind het allebei lelijk. In andere talen zou je het zo kunnen doen dat je .orders min of meer transparant toegankelijk maakt, terwijl je de mogelijkheid openlaat dat je op een later moment de .orders access gaat afvangen zodat je extra functionaliteit kan toevoegen zonder dat de calling code hoeft te veranderen.
Ik volg je niet helemaal. :?

[ Voor 29% gewijzigd door whoami op 07-09-2005 08:52 ]

https://fgheysels.github.io/


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

whoami schreef op woensdag 07 september 2005 @ 08:51:
[...]

Niet helemaal; in jouw voorbeeld heb je het over een 'CustomCollection', terwijl het bij mij eerder een business object is; bv. 'Customer', die een collection heeft.
Dan heeft je Customer object een public propertie Order van het type OrderCollection.

Het lijkt dan het dus op voorbeeld B.

[ Voor 14% gewijzigd door pjvandesande op 07-09-2005 08:55 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-02 11:06

Janoz

Moderator Devschuur®

!litemod

Ikzelf gebruik altijd een List met getter + setter. Door enkel een add en een to array te gebruiken kun je geen gebruik maken van de andere functionaliteiten van de List. Mogelijk nadeel is inderdaad dat er buiten het domein object om van alles kan worden verandered omdat ik de list zelf doorgeef.

@questa:
Het gaat heir niet om een wrapper voor een list, maar om bijvoorbeeld een klant object waarbij meerdere orders horen.

@Manuzhai:
Dat is toch precies wat in voorbeeld B gebeurt?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

Janoz schreef op woensdag 07 september 2005 @ 09:06:
@questa:
Het gaat heir niet om een wrapper voor een list, maar om bijvoorbeeld een klant object waarbij meerdere orders horen.
Daarom return je niet een Array, maar een Collection object die Events bevat waar de Owner dan op kan reageren.

Mochten er nou echt berekingen plaatsvinden dan zou ik de Collection inderdaad al een Array terug geven en me Owner uitbereiden met AddMelp en RemoveMelp.

[ Voor 22% gewijzigd door pjvandesande op 07-09-2005 09:24 ]


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-02 11:06

Janoz

Moderator Devschuur®

!litemod

Ik interpreteerde je 'public property' wat verkeerd (veel .net hier terwijl ik met java werk), maar als je daar een private variabele met getters en setters mee bedoeld dan praten we inderdaad over hetzelfde :D

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

Janoz schreef op woensdag 07 september 2005 @ 09:24:
Ik interpreteerde je 'public property' wat verkeerd (veel .net hier terwijl ik met java werk), maar als je daar een private variabele met getters en setters mee bedoeld dan praten we inderdaad over hetzelfde :D
Dan bedoelen we hetzelfde ;)

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

questa schreef op woensdag 07 september 2005 @ 09:21:
[...]

Mochten er nou echt berekingen plaatsvinden dan zou ik de Collection inderdaad al een Array terug geven en me Owner uitbereiden met AddMelp en RemoveMelp.
Melp?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

Melp, Blaat, Iets, Order.. geef het een naam ;)

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

questa schreef op woensdag 07 september 2005 @ 10:05:
[...]


Melp, Blaat, Iets, Order.. geef het een naam ;)
Ooo, op die manier. Ik dacht Mixed Excitation Linear Prediction

[ Voor 13% gewijzigd door jelmervos op 07-09-2005 10:07 ]

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 17-12-2025

curry684

left part of the evil twins

Allernetste is natuurlijk om in BusinessObjectCollection zelf ook IList te implementeren zodat je gegarandeerd alle functionaliteit aanbiedt, en gedwongen bent op iedere modificatie de correcte side-effects en checks uit te voeren, waarmee je Janoz' probleem omzeilt dat er ongemerkt wijzigingen kunnen plaatsvinden.

Ik ben zelf meestal ook lui though en pass gewoon de list door ;)

Professionele website nodig?


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 03-02 12:37

pjvandesande

GC.Collect(head);

curry684 schreef op woensdag 07 september 2005 @ 10:09:
Allernetste is natuurlijk om in BusinessObjectCollection zelf ook IList te implementeren zodat je gegarandeerd alle functionaliteit aanbiedt, en gedwongen bent op iedere modificatie de correcte side-effects en checks uit te voeren, waarmee je Janoz' probleem omzeilt dat er ongemerkt wijzigingen kunnen plaatsvinden.
Dat vind ik persoonlijk de mooiste oplossing. Als je dan toch bezig bent zou ik weer niet voor een IList kiezen omdat je daarbij een Object kunt toevoegen, ik zou dan een wrapper er omheen gooien waarbij je alleen Melp kunt toevoegen.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 17-12-2025

curry684

left part of the evil twins

questa schreef op woensdag 07 september 2005 @ 10:13:
[...]


Dat vind ik persoonlijk de mooiste oplossing. Als je dan toch bezig bent zou ik weer niet voor een IList kiezen omdat je daarbij een Object kunt toevoegen, ik zou dan een wrapper er omheen gooien waarbij je alleen Melp kunt toevoegen.
True that :)

Professionele website nodig?


  • EfBe
  • Registratie: Januari 2000
  • Niet online
whoami schreef op dinsdag 06 september 2005 @ 19:13:
Ik zat me net ff af te vragen: welk 'ontwerp' is eigenlijk beter als het gaat om bv. business objecten die een (of meerdere) collections hebben.

Stel voorbeeld a:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyCustomerDomainObject
{
     ...
     private IList  _orders;

     public void AddOrder( Order o )
     {
         _orders.Add (o);
     }

     public Order[] GetOrders() 
     {
         return _orders.ToArray();
     }

}


voorbeeld b:
code:
1
2
3
4
5
6
7
8
9
class MyCustomerObject
{
     private IList _orders;

     public IList Orders
     {
         get{ return _orders; }
     }
}


Wat is eigenlijk best practice ?
In voorbeeld a scherm je die collectie veel beter af dan in voorbeeld b, maar in voorbeeld a verlies je dan wel weer wat flexibiliteit.

Als je een domein-class hebt met veel collecties, tja, dan ga je - als je voorbeeld a toepast - natuurlijk een helehoop Adddit en Adddat, Removedit, etc... methods gaan hebben.
Het hangt ervan af wat je ermee wilt doen. Voor je persistence logic is het van belang of change tracking werkt, of hoe het is geimplementeerd.

In beide gevallen bij jou kun jij niet traceren of customer.Orders.Add(myNewOrder) plaatsvindt. Dus ook niet wanneer ik:
OrderEntity myNewOrder = new OrderEntity();
myNewOrder.Customer = myCustomer;

doe, myNewOrder automatisch in myCustomer.Orders wordt toegevoegd, en indien myCustomer niet nieuw is dat myNewOrder.CustomerID gezet wordt met de value myCustomer.CustomerID. Of dat waneer ik hierna myNewOrder.CustomerID = someOtherValue doe, myNewOrder.Customer wordt gedereferenced en myNewOrder weer verdwijnt uit myCustomer.Orders.

Dat hoeft geen problemen te geven, maar in je persistence layer moet je er wel rekening mee houden EN in je GUI kan het problemen geven in master/detail grids bv, wanneer de user een order toevoegt en dan automatisch de customerid gezet wil zien (want die is immers gelijk aan de customerid van de customer associeerd met de nieuwe order). Dat moet je dan met de hand gaan zitten bouwen.

[ Voor 5% gewijzigd door EfBe op 07-09-2005 13:06 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
EfBe schreef op woensdag 07 september 2005 @ 13:05:
[...]


Dat hoeft geen problemen te geven, maar in je persistence layer moet je er wel rekening mee houden EN in je GUI kan het problemen geven in master/detail grids bv, wanneer de user een order toevoegt en dan automatisch de customerid gezet wil zien (want die is immers gelijk aan de customerid van de customer associeerd met de nieuwe order). Dat moet je dan met de hand gaan zitten bouwen.
En dat is imo makkelijker te doen met voorbeeld a.
Die 'AddOrder' method moet dan eigenlijk zo zijn:
code:
1
2
3
4
5
AddOrder( Order o )
{
   o.Customer = this;
   orderCollection.Add(o);
}

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
whoami schreef op woensdag 07 september 2005 @ 13:15:
[...]
En dat is imo makkelijker te doen met voorbeeld a.
Die 'AddOrder' method moet dan eigenlijk zo zijn:
code:
1
2
3
4
5
AddOrder( Order o )
{
   o.Customer = this;
   orderCollection.Add(o);
}
Oh, en nu wanneer de orders gebind zijn aan een grid en de user gaat op die lege nieuwe regel staan onderin.

Gaat niet werken. Jouw voorstel is sowieso discutable, want het maakt de Orders collection onderdeel van de Customer, en dat is nog maar de vraag. Want, is Customer.Orders[index].OrderDetails ook onderdeel van Customer? Als daar een veld wijzigt, is Customer dan ook gewijzigd? (in jouw geval: ja).

De ellende waar jij mee zit is primair een gevolg van het gebruik van POCO. In Java is POJO essentieel, daar je EJB-CMP en friends hebt, in .NET heb je die niet en is een transparantie mbt je base class eerder een nadeel dan een voordeel, immers je moet veel zelf bouwen, en dat voor iedere entity opnieuw. Ik kan je verzekeren: wat jij aanstipt is slechts het tipje van de ijsberg. Want alleen het databinding verhaal is al genoeg voor weken hoofdpijn. Wat bv wanneer de user een nieuwe order toevoegt aan de orders collection die gebind is aan de grid? En wat wanneer deze ESC drukt ? Wat te doen wanneer Orders leeg is? -> no columns.

[ Voor 54% gewijzigd door EfBe op 07-09-2005 14:37 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
EfBe schreef op woensdag 07 september 2005 @ 14:33:

Oh, en nu wanneer de orders gebind zijn aan een grid en de user gaat op die lege nieuwe regel staan onderin.

Gaat niet werken. Jouw voorstel is sowieso discutable, want het maakt de Orders collection onderdeel van de Customer, en dat is nog maar de vraag. Want, is Customer.Orders[index].OrderDetails ook onderdeel van Customer? Als daar een veld wijzigt, is Customer dan ook gewijzigd? (in jouw geval: ja).
Hoezo ? Ik bedoel: Die Orders zijn toch van die customer, dus is het toch logisch dat die OrderCollection onderdeel is van die Customer class ?
Want alleen het databinding verhaal is al genoeg voor weken hoofdpijn. Wat bv wanneer de user een nieuwe order toevoegt aan de orders collection die gebind is aan de grid? En wat wanneer deze ESC drukt ? Wat te doen wanneer Orders leeg is? -> no columns.
Als mijn CustomCollection(s) IBindingList implementeren, dan heb ik deze problemen toch niet meer ?

https://fgheysels.github.io/


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-02 11:06

Janoz

Moderator Devschuur®

!litemod

curry684 schreef op woensdag 07 september 2005 @ 10:09:
Allernetste is natuurlijk om in BusinessObjectCollection zelf ook IList te implementeren zodat je gegarandeerd alle functionaliteit aanbiedt, en gedwongen bent op iedere modificatie de correcte side-effects en checks uit te voeren, waarmee je Janoz' probleem omzeilt dat er ongemerkt wijzigingen kunnen plaatsvinden.

Ik ben zelf meestal ook lui though en pass gewoon de list door ;)
Maar je introduceert twee nieuwen (mwah, anderhalf). Ten eerste kan je dan maar 1 collection in je buisness object hebben. Het anderhalfde punt is hier lichtelijk aan gerelateerd. De methodenamen dekken niet geheel de lading. Je verwacht een addOrder() ipv een add().

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
Janoz schreef op woensdag 07 september 2005 @ 19:13:
[...]


Maar je introduceert twee nieuwen (mwah, anderhalf). Ten eerste kan je dan maar 1 collection in je buisness object hebben.
Hoezo ?

https://fgheysels.github.io/


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13-02 11:06

Janoz

Moderator Devschuur®

!litemod

De List interface geld maar voor 1 lijst. Wanneer je in je buisness object meerdere lijsten hebt kun je niet twee keer dezelfde methodes implementeren.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 09-12-2025
Janoz schreef op woensdag 07 september 2005 @ 20:01:
De List interface geld maar voor 1 lijst. Wanneer je in je buisness object meerdere lijsten hebt kun je niet twee keer dezelfde methodes implementeren.
curry684 had het dan ook over BusinessObjectCollection, een aparte class die je dan gebruikt in de andere domein class.

Noushka's Magnificent Dream | Unity


  • EfBe
  • Registratie: Januari 2000
  • Niet online
whoami schreef op woensdag 07 september 2005 @ 19:03:
[...]

Hoezo ? Ik bedoel: Die Orders zijn toch van die customer, dus is het toch logisch dat die OrderCollection onderdeel is van die Customer class ?
Nee, want die order is ingegeven door een employee, en een employee entity heeft DEZELFDE order objects (en andere) in zijn orders collection. Bij wie hoort een zekere order nu? :)
[...]
Als mijn CustomCollection(s) IBindingList implementeren, dan heb ik deze problemen toch niet meer ?
Jawel, want je moet IEditableObject implementeren, die CancelEdit uitvoert in de collection, en wanneer deze een CancelEdit voor zn kiezen krijgt op een nieuwe, door databinding gecreeerde entity, moet DIE worden verwijderd.

Verder kun jij zonder factory IBindingList.AddNew() niet implementeren, en bij een lege collection wil je wel columns hebben, dus ITypedList is noodzakelijk.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 17-12-2025

curry684

left part of the evil twins

Michali schreef op woensdag 07 september 2005 @ 20:08:
[...]


curry684 had het dan ook over BusinessObjectCollection, een aparte class die je dan gebruikt in de andere domein class.
^^^^ :)

Je creert dus indien een object 2 collections heeft voor beide collections een intermediate class die de correcte interface exposed. Alleanderhalf je probleem zijn daarmee dus opgelost ;)

Professionele website nodig?


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
curry684 schreef op woensdag 07 september 2005 @ 20:47:
[...]

^^^^ :)

Je creert dus indien een object 2 collections heeft voor beide collections een intermediate class die de correcte interface exposed. Alleanderhalf je probleem zijn daarmee dus opgelost ;)
Je bedoelt dat je dan 2 'customcollection' classes maakt ?

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:35
RotSchop :+

Ik doe het nu zo:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Order
{
   private List<OrderLine> orderLines = new List<OrderLine>();

   public void AddOrderLine( OrderLine ol )
   {
     ol.Order = this;
     orderLines.Add (ol);
   }

   public ReadOnlyCollection<OrderLine> OrderLines
   {
      get
      {
           return orderLines.AsReadOnly();
      }
   }
}


Hiermee heb je :
- gecontroleerde access tot je collection
- kan je direct over je collection iteraten.

https://fgheysels.github.io/

Pagina: 1