[alg] groeperen functionaliteit of uitbreidbaarheid.

Pagina: 1
Acties:

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik heb al een tijd het volgende probleem. Ik heb een typesysteem en daarin zitten Type objecten en functies zoals isEqualType en isSubType. Ik kan bij de types deze functionaliteit onderbrengen door 2 methodes isEqualType en isSubType aan te maken. Deze aanpak geeft echter een aantal problemen.
*alle functionaliteit van 1 functie ligt verspreid over een hele class hierarchie. Ik vind dit in dit geval een ware onderhoudsnachtmerrie.
*je zit vast aan de functionaliteit zoals geimplementeerd in die methodes. Wil je bv dezelfde Types hanteren, maar een ander soortige functionaliteit dan heb je een probleem. Stel dat je een variant van dit typesysteem nodig bent waarin een boolean een subtype is van een integer, dan kan je dit niet mooi oplossen.
*als je een nieuwe functie wilt, zul je dit bij alle type objecten moeten implementeren.

Deze manier van aanpak heeft wel een voordeel: je kan eenvoudig nieuwe types aan het systeem toevoegen. Je hoeft alleen maar de methodes te implementeren en je bent klaar.

Een andere manier van werken is dat je een module (class bv) gaat maken waarin alle functionaliteit zit. Je kan bv werken met een visitors om te gaan dispatchen. Helaas kleeft hier ook een groot nadeel aan:
*het is niet uitbreidbaar. Stel dat ik een nieuw type toevoeg die interessant is voor een of andere toepassing van dat systeem maar niet voor andere toepassingen. Dan zal ik in deze module extra afhandeling moeten plaatsen alleen voor dit type, oftwel: mijn generiek typesysteem wordt besmet met specifieke functionaliteit.

De voordelen zijn wel dat ik bv eenvoudig een andere subtype functionaliteit aan het systeem kan koppelen, door gewoon die module te verwisselen (bv via een Abstract Factory de implementatie verwisselbaar maken). Het super inzichtelijk omdat alle functionaliteit in 1 module te hebben. En nieuwe functionaliteit toevoegen is een kwestie van een nieuwe module op te zetten.

Ik zit dus een beetje in een impasse. Ik wil graag dat functionaliteit modulair is maar ik wil dat het systeem ook uitbreidbaar is. Wat voor tips kunnen jullie mij geven om dit probleem op te lossen.

[edit]
*moet nog ff naar die lastige bridge pattern kijken*

[ Voor 10% gewijzigd door Alarmnummer op 04-03-2004 15:25 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Volgens mij staat hier iets over in "Modern C++ Design", een template visitor + policies.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Even checken of ik de kwestie helemaal snap: je hebt dus op runtime een collectie instances waar je een soortement van class-hierarchy mee vormt?

Oftewel, je hebt een class Instance en een class Type, en Type bevat de naam, ancestor Type en layout van de Instance oid?

Professionele website nodig?


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
curry684 schreef op 04 maart 2004 @ 16:34:
Even checken of ik de kwestie helemaal snap: je hebt dus op runtime een collectie instances waar je een soortement van class-hierarchy mee vormt?

Oftewel, je hebt een class Instance en een class Type, en Type bevat de naam, ancestor Type en layout van de Instance oid?
Het is puur een compiletime aangelegenheid.

Ik heb een bepaalde class hierarchie (van types in dit geval). Deze classhierarchie is onderdeel van een of andere generieke type-library. Ik wil aan deze library nieuwe types (dus nieuwe elementen aan de class hierarchie) toevoegen. Deze nieuwe types zijn toevallig alleen interessant bij een Prolog implementatie en ik wil die generieke library niet met die types besmetten (dus geen prolog specifieke type sources in mijn generieke library).

Als ik had gewerkt met polymorfisme, had ik eenvoudig die 2 methodes kunnen toevoegen aan de nieuwe Types en dan was ik klaar geweest. Maar ik wil niet werken met polymorfisme, omdat die functionaliteit dan helemaal verspreid ligt over die class hierarchie (dus overal een klein beetje isSubType en isEqualType code). En verder is een bepaalde isSubType en isEqualType functionaliteit nu hard gecodeerd in de type-classes. Ik kan dus die functionaliteit niet even makkelijk uitwisselen. Dit laatste is voor mij erg belangrijk omdat je bv bij de ene taal (waar het typesysteem in gebruikt wordt) behoefte hebt aan een structurele equals, en bij de andere in een equals op basis van identiteit.

Ik wil dus uitbreidbaarheid van types, maar ook functionaliteit uitwisselbaar maken.

[ Voor 7% gewijzigd door Alarmnummer op 04-03-2004 17:15 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Zoijar schreef op 04 maart 2004 @ 16:08:
Volgens mij staat hier iets over in "Modern C++ Design", een template visitor + policies.
Ik zal even in mijn ebook versie kijken.

[edit]
*gaat nu naar huis en weet niet wanneer hij weer kan reageren*.

[edit2]
Er schiet me ook nog iets te binnen over uitbreidbare visitors... Dat stond geloof ik ergens op de Nice site.

[ Voor 41% gewijzigd door Alarmnummer op 04-03-2004 17:31 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mja, in C++ is het makkelijk op te lossen mbv templates. Die kun je ook specialiseren, en dat maakt ze ook goed uitbreidbaar.

Voorbeeldje:
C++:
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
// checks if T and U are the same
template <class T, class U> struct type_isequal
{
     enum { value = false };
};

template <class T> struct type_isequal<T, T>
{
    enum { value = true };
};

// checks if T can be converted to U
template <class T, class U> struct type_isconvertible
{
private:
    struct biggerthanchar { char c[1024]; };
    static T makeT ();
    static char test (U);
    static biggerthanchar test (...);

public:
    enum { value = (sizeof (test (makeT ())) == 1) };
};

// checks whether T is a subtype of U
template <class T, class U> struct type_issubtype
{
    enum { value = type_isconvertible<const T *, const U *>::value };
};


meer info over type_isconvertible staat ook in Modern C++ design

Maar stel nu dat je idd een Boolean en een Integer klasse hebt, die onderling geen relatie hebben, en je wilt aangeven dat Boolean een subtype van Integer is, dan maak je gewoon een explicit specialization voor die combinatie:

C++:
1
2
3
4
template <> struct type_issubtype<Boolean, Integer>
{
    enum { value = true };
};


Maar ja, zoals gezegd is dit wel enorm C++ only, en dus niet echt een algemene oplossing :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Als je bang bent dat bepaalde implementatie code verspreidt komt te liggen over vele classes/files, dan moet je Aspects gebruiken. Voor een aantal talen zijn die al geimplementeerd. Dan kan je bepaalde code over vele klassen lokaal bij elkaar houden. Alleen ik heb geen idee hoe je wat aan het implementeren bent, dus misschien kan je het helemaal wel niet gebruiken.

"Beauty is the ultimate defence against complexity." David Gelernter


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Macros schreef op 04 maart 2004 @ 20:02:
Als je bang bent dat bepaalde implementatie code verspreidt komt te liggen over vele classes/files, dan moet je Aspects gebruiken. Voor een aantal talen zijn die al geimplementeerd. Dan kan je bepaalde code over vele klassen lokaal bij elkaar houden. Alleen ik heb geen idee hoe je wat aan het implementeren bent, dus misschien kan je het helemaal wel niet gebruiken.
Check mijn sig hoe ik over aspects denk ;) Helaas kan ik dat hier niet gebruiken omdat ik java + generics gebruik en aspectj ondersteunt nog niet de nieuwe 1,5 syntax.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
.oisyn schreef op 04 maart 2004 @ 17:59:

Maar ja, zoals gezegd is dit wel enorm C++ only, en dus niet echt een algemene oplossing :)
Idd.

Ik zat zelf te denken aan een extendable TypeVisitor. Je maakt in een functionaliteits-module een double dispatch voor types en daarin implementeer je bv al een hele reeks met combinaties (alle combinaties voor die generieke visitor) In het specifieke gedeelte ga je dan een nieuwe visitor maken die de generieke extend. En dan ga je een nieuwe dispatchmodule maken die de oude extend en dan hoef je alleen nog maar de nieuwe combinaties te overriden.

[ Voor 6% gewijzigd door Alarmnummer op 05-03-2004 10:03 ]

Pagina: 1