[VB6] "OO" ontwerp bedenken

Pagina: 1
Acties:

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
Ik heb een applicatie in VB6 (helaas) en daarin wil ik een paar veranderingen aanbrengen. Helaas kan ik niet goed bedenken hoe ik dat in VB6 (zonder inheritance dus) kan realiseren.

Het probleem is als volgt:
Op een set gegevens moeten verschillende berekeningen worden uitgevoerd. Er is een class (Walker) die de verschillende sets gegevens ophaalt en aanbied aan verschillende verwerkings classes (classes die IGenerator implementeren). Nadat de gegevens verwerkt zijn gaat de Walker alle resultaten verzamelen via een method in IGenerator.

Tot zover niets aan de hand, dit werkt allemaal. Helaas bevatten de Generators nogal wat dubbele code, omdat VB6 natuurlijk geen echte inheritance bied. Nu moet er wat functionaliteit aan alle generators worden toegevoegd (een filter om bepaalde sets gegevens wel of niet te laten verwerken door de betreffende Generator) en ik heb weinig zin om die code in alle Generators te gaan toevoegen.

Ik heb een class gemaakt: FilterGenerator, die IGenerator implementeert en alle calls delegeert aan een interne Generator (een soort decoration pattern dus), ongeveer zo:
Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
Implements Generator

Private m_G As Generator

' Klein stapeltje methods die gedelegeerd worden aan m_G

Private Sub Generator_Process(r As DAO.Recordset)
    ' Doe wat filtering en zet dan de boolean Process

    If Process Then m_G.Process r
End Sub


Elke soort generator heeft nog een paar extra methods om de resultaten op te halen. Afhankelijk van de class van die Generator zal de Walker bij het ophalen van de resultaten 1 of andere method aanroepen om een class specifiek resultaat op te halen. Dat is nu die FilterGenerator ertussen zit natuurlijk niet meer mogelijk, aangezien de Walker alleen een instance van FilterGenerator zien en niet meer de onderliggende Generator.

Hoe krijg ik het nu zo dat die Walker bij het ophalen van de resultaten nog weet wat voor soort Generator er onder die Filter (en eventueel andere decorations) zit en daar methods op kan aanroepen als hij vind dat dat nodig is?

[edit]
Ik zou natuurlijk een method GetRealGenerator kunnen toevoegen aan IGenerator. Dan moeten alle decorations hun onderliggende Generator returnen en alle Generators moeten zichzelf returnen. Is dat een mooie oplossing, want ik vind het namelijk niet zo prettig om binnen al die Generators code te gaan toevoegen die geen ander doel heeft dan het voldoen aan die gewijzigde interface.

[ Voor 11% gewijzigd door Gerco op 21-06-2006 11:39 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 22-12-2025

PhysicsRules

Dux: Linux voor Eenden

Ik zat vanochtend met een vergelijkbaar probleem (VBA). Bij de oplossing die ik gevonden heb voeg je een helper class toe die alle generieke code implementeert. De subclasses verwijzen hier allemaal naar.

Wat betreft de verschillende resultaat methods. Als ik je goed begrijp bepaalt Walker op basis van een eerste resultaat van een Generator welke methods hij moet aanroepen. Dit klinkt niet echt als mooi polymorfisme. Kun je een voorbeeld geven hoe het eruit ziet?

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
Mooi polymorfisme is het ook niet. Het gaat momenteel ongeveer zo:
Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  Dim G As Generator
  Dim MOG As MOGenerator
  Dim HPG As HPGenerator

  For Each G in Generators
    ' Doe iets generieks met elke generator

    Select Case G.Class
      Case "MO":
        Set MOG = G
        MOG.DoeIetsSpeciaals

      Case "HP":
        Set HPG = G
        HPG.DoeIetsAnders

    End Select
  Next G


Waarbij Generator.Class een Function is die voor elke Generator een string teruggeeft waarmee de verschillende Genertors onderscheiden kunnen worden. Niemand zei dat het mooi was en ik heb de mogelijkheid om het ontwerp helemaal om te gooien als het moet. Ik kan alleen niet goed verzinnen hoe ik dat in VB6 anders/mooier moet realiseren.

[ Voor 4% gewijzigd door Gerco op 21-06-2006 14:26 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 14:43

mulder

ik spuug op het trottoir

Ik kan alleen niet goed verzinnen hoe ik dat in VB6 anders/mooier moet realiseren.
Niet. Bespaar je de moeite. Je kunt heel leuke dingen doen met VB6 en het is best krachtig, maar wat je nu wilt kan VB6 gewoon niet.

oogjes open, snaveltjes dicht


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 22-12-2025

PhysicsRules

Dux: Linux voor Eenden

Gerco schreef op woensdag 21 juni 2006 @ 14:26:
Mooi polymorfisme is het ook niet. Het gaat momenteel ongeveer zo:
Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  Dim G As Generator
  Dim MOG As MOGenerator
  Dim HPG As HPGenerator

  For Each G in Generators
    ' Doe iets generieks met elke generator

    Select Case G.Class
      Case "MO":
        Set MOG = G
        MOG.DoeIetsSpeciaals

      Case "HP":
        Set HPG = G
        HPG.DoeIetsAnders

    End Select
  Next G


Waarbij Generator.Class een Function is die voor elke Generator een string teruggeeft waarmee de verschillende Genertors onderscheiden kunnen worden. Niemand zei dat het mooi was en ik heb de mogelijkheid om het ontwerp helemaal om te gooien als het moet. Ik kan alleen niet goed verzinnen hoe ik dat in VB6 anders/mooier moet realiseren.
Ik heb het dus ook zo aangepakt :).

Kun je niet één algemene public method maken en die per generator een andere speciale functionaliteit laten aanroepen.

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
PhysicsRules schreef op woensdag 21 juni 2006 @ 15:38:
Kun je niet één algemene public method maken en die per generator een andere speciale functionaliteit laten aanroepen.
Helaas, dat gaat niet lukken. De ene specifieke method returnt een Klant object, de andere een heel ander object en er moet met die objecten ook wat anders gebeuren. Ze moeten namelijk in een rapportage komen en in verschillende lijsten geplaatst worden (op papier).

Op deze manier werkt het ook wel, ik zal alleen een GetRealGenerator method moeten toevoegen die door de decorations de verschillende soorten Generators aan de Walker returnt. Op die manier kan ik veel gedupliceerde functionaliteit als decoration/filter implementeren en kan ik dat uit de Generators weghalen.

Jammer dat VB geen polymorfisme ondersteund, anders had het vast mooier gekund (visitor pattern oid).

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Ik snap nog niet helemaal wat het probleem is ... je zegt telkens dat VB6 geen polymorfisme( of bedoel je overloading? ) ondersteunt maar je kunt toch meerdere interfaces implementen? ( Het klinkt een beetje alsof een je een specifieke interface in je 'basisklasse' wilt hebben )

Hoe zou je dit probleem in de taal van jouw keuze?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
Ik vind die "Class" method smerig. De class moet een string teruggeven om te vertellen wat het is? Dat is gewoon vies. Het liefst zou ik werken met een soort "instanceof", zoals in Java. Echt mooi is het dan nog steeds niet, maar een oplossing daarvoor kan het visitor pattern zijn. Dan moet ik echter mijn logica gaan herschrijven en in de visitor implementeren en dat vind ik een beetje teveel werk.

For now zou ik al tevreden zijn met zoiets:
Visual Basic:
1
2
3
4
5
6
7
8
9
  For Each Generator G In Generators
    ' Doe iets generieks met elke generator

    If G instanceof MOGenerator Then
      ((MOGenerator)G).DoeIets
    Else If G instanceof HPGenerator Then
      ((HPGenerator)G).DoeIetsAnders
    End If
  Next G


Eigenlijk wil ik een oplossing waarbij de Walker niet hoeft te weten welke Generators er allemaal zijn, maar dan zou ik de logica om het resultaat van de Generator in het rapport te schrijven, in de Generator moeten zetten. Ik wil ook niet dat de Generator weet dat hij in een rapportage gaat verschijnen, die moet alleen zijn berekening hoeven uitvoeren. Hij moet namelijk zowel in een rapportage als in de database en een XML file komen.

[ Voor 28% gewijzigd door Gerco op 21-06-2006 22:46 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Ok dan :) Ik weet niet maar misschien dat voor jouw tussenoplossing TypeOf bruikbaar is? (Alhoewel dat onderwater ook op reflection uitkomt dacht ik )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
TypeOf kende ik nog niet... reflection zit ik niet mee, als ik maar niet zo'n gore "zeg wat voor object je bent" method hoef te hanteren ben ik al grotendeels tevreden. Nu zou ik eigenlijk nog een manier willen hebben om type-specifieke methods aan te roepen op een instance, zonder die aan een tijdelijke variabele toe te kennen.


Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  Dim G As Generator
  ' Deze twee DIMs wil ik dus weghebben. Nu moet ik voor elke soort Generator een variabele bij de hand hebben om methods erop te kunnen aanroepen.
  Dim MOG As MOGenerator
  Dim HPG As HPGenerator

  For Each Generator G In Generators
    ' Doe iets generieks met elke generator

    If TypeOf G Is MOGenerator Then
      Set MOG = G
      MOG.DoeIets
    Else If TypeOf G Is HPGenerator Then
      Set HPG = G
      HPG.DoeIetsAnders
    End If
  Next G


Bestaat er in VB6 een soort cast zoals in Java of zoals CType() in VB.NET ?

[ Voor 24% gewijzigd door Gerco op 22-06-2006 08:16 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • Vedett.
  • Registratie: November 2005
  • Laatst online: 19-02 19:21
Om te beginnen: Ik ken niets van VB6. Ik wist zelfs niet dat je met interfaces kon werken.

Maar als het toch gaat. Dan zou je aan je methode van IGenerator een IExtraBehaviour waarde kunnen doorgeven (vermoed ik)

Maak dan een aantal klassen die daarvan overerven, en geef de correcte klasse door aan je methode.

bijvoorbeeld
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
DontHaveExtraBehaviour : IExtraBehaviour
{
   public void DoExtraBehaviour(IGenerator){
        //Methode doet niets want ik heb geen extra behaviour
   }
}


DoHaveExtraFilerBehaviour : IExtraBehaviour
{
   public void DoExtraBehaviour(IGenerator){
        //Check de extra filters die je wilt controleren op IGenerator
   }
}


Dit is iets in de vorm van het strategy design pattern. Alleen gebruiken we interfaces ipv Abstracted methods omdat dit dus niet mogelijk is in VB6.

Het komt er dus op neer dat je aan elke generator een specifieke actie geeft met behulp van een interface. Die interface kan dan geïmplementeerd worden door verschillende klassen. Op die manier kun je extra behaviour toevoegen, en toch de beheviour maar één keer programmeren.

Ik hoop dat ik het duidelijk heb uitgelegd.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Misschien met een Variant

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PhysicsRules
  • Registratie: Februari 2002
  • Laatst online: 22-12-2025

PhysicsRules

Dux: Linux voor Eenden

Wat in .Net gebruikt wordt zijn Format Classes. Je zou iets vergelijkbaars kunnen doen. Voor elk soort Generator resultaat/rapport bouw je een Format class (iets van MOGeneratorFormatter en HPGeneratorFormatter). De Generators kennen hun eigen formatter en Walker hoeft die alleen aan te roepen.:

Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
  Dim G As Generator
  Dim F as Formatter
  Dim R as Result
  
  For Each G in Generators
   
    Set F = G.GetFormatter
    Set R = G.GetResult

   F.FormatData(R)

  Next G

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Je kunt je object ook "as Object" dimensioneren en dan met TypeOf kijken welk type object het is. Ik zou in ieder geval ver uit de buurt van een Variant blijven. Wat dat voor gedrocht is weet niemand eigenlijk echt :P

Als je late binding gebruikt kunt je dus gewoon:

code:
1
2
3
4
If TypeOf(dinges)=Something
  MyObject.DoeIets
Else
  MyObject.DoeIetsAnders


doen

[ Voor 29% gewijzigd door RobIII op 22-06-2006 10:14 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
@RobIII:
"Dim As Object" vind ik bijna net zo vies als een Variant gebruiken (en ik heb inderdaad geen idee wat dat nu precies is, het komt ongeveer neer op "variabele"). Late binding wil ik het liefst niet gebruiken, aangezien ik dan natuurlijk gelijk mijn compiletime typesafety gedag kan zeggen.

@PhysicsRules:
Ik ga die Format classes eens proberen, ik denk dat ik er daarmee wel uit ga komen. Bij het aanmaken van de Generators weet ik uiteraard wel wat ik er uiteindelijk mee ga doen, dus dan kan ik er ook de goede Formatter aan knopen. De Walker hoeft die dan alleen nog maar aan te roepen.

[ Voor 26% gewijzigd door Gerco op 22-06-2006 10:28 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Gerco schreef op donderdag 22 juni 2006 @ 10:27:
@RobIII:
"Dim As Object" vind ik bijna net zo vies als een Variant gebruiken (en ik heb inderdaad geen idee wat dat nu precies is, het komt ongeveer neer op "variabele"). Late binding wil ik het liefst niet gebruiken, aangezien ik dan natuurlijk gelijk mijn compiletime typesafety gedag kan zeggen.
"As Object" is idd ook vies, maar wel zo'n beetje de enige manier om een klein beetje OO (zoals bovenstaand voorbeeld) te kunnen benaderen zonder allerlei rare (enge) constructies te moeten gebruiken. En daar komt (helaas) dan ook late binding bij kijken ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Variant / Object ... wat is het verschil als de Variant een Object bevat ? Tis gewoon een union die een flag meedraagt die vertelt wat voor een soort ding erin zit...niets speciaals.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
Nou, een variant kan ook een primitief type bevatten bijvoorbeeld. Als een Variant een Object bevat, is het inderdaad hetzelfde als een Object. Waarom dan ook geen Object gebruiken, dan weet je tenminste zeker dat er ook een Object in zit.

Eigenlijk zijn ze beiden vies, ik zie geen reden om late binding te moeten gebruiken voor objecten die alleen binnen je eigen applicatie zitten. Voor externe ActiveX objecten kan ik het me nog wel een beetje voorstellen, maar ook liever niet.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • sopsop
  • Registratie: Januari 2002
  • Laatst online: 10:17

sopsop

[v] [;,,;] [v]

Hier op zich wel een aardig artikel over OO in VB classic:
http://en.wikibooks.org/w...ject_Oriented_Programming

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Gerco schreef op donderdag 22 juni 2006 @ 13:07:
Nou, een variant kan ook een primitief type bevatten bijvoorbeeld. Als een Variant een Object bevat, is het inderdaad hetzelfde als een Object. Waarom dan ook geen Object gebruiken, dan weet je tenminste zeker dat er ook een Object in zit.

Eigenlijk zijn ze beiden vies, ik zie geen reden om late binding te moeten gebruiken voor objecten die alleen binnen je eigen applicatie zitten. Voor externe ActiveX objecten kan ik het me nog wel een beetje voorstellen, maar ook liever niet.
Ik ben het helemaal met je eens maar er werd gesuggereerd dat een Variant itt een Object een 'gedrocht' is. Het zijn gewoon beide gedrochten ( met hun eigen syntax/keywords, een van de grote zwakke punten van VB )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
En hoewel ik het daar helemaal mee eens ben, is de TS "opgescheept" met VB6 en zal er dus toch gebruik gemaakt moeten worden van 1 van beide "gedrochten" (of, idd zoals de TS al aangeeft, van een "strong-typed" object). The way I see it is dat er dan niet gejammerd moet worden maar geploeterd om er maar het beste van te maken ;)

[ Voor 15% gewijzigd door RobIII op 23-06-2006 18:33 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
RobIII schreef op vrijdag 23 juni 2006 @ 17:59:
En hoewel ik het daar helemaal mee eens ben, is de TS "opgescheept" met VB6 en zal er dus toch gebruik gemaakt moeten worden van 1 van beide "gedrochten" (of, idd zoals de TS al aangeeft, van een "strong-typed" object). The way I see it is dat er dan niet gejammerd moet worden maar geploeterd om er maar het beste van te maken ;)
Mja ook mee eens. Ik denk dat het een pijnlijk verhaal gaat worden als je met VB6 volgens 'pure' OO concepten wil gaan werken. Het is er niet voor gebouwd, dus ik zou niet proberen om dat te forceren.
( Zelf zou ik in VB eerder kiezen voor een select case die onderhouden moet worden dan een constructie die vervolgens alle objecten gaat late binden )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 03:31

Gerco

Professional Newbie

Topicstarter
farlane schreef op zaterdag 24 juni 2006 @ 00:10:
Mja ook mee eens. Ik denk dat het een pijnlijk verhaal gaat worden als je met VB6 volgens 'pure' OO concepten wil gaan werken. Het is er niet voor gebouwd, dus ik zou niet proberen om dat te forceren.
( Zelf zou ik in VB eerder kiezen voor een select case die onderhouden moet worden dan een constructie die vervolgens alle objecten gaat late binden )
Dat met die Format classes lijkt aardig te werken, ik ben er nog niet helemaal, maar zo te zien hoef ik noch Select Case, noch Object te gebruiken. Wanneer ik het werkend heb, post ik wel wat en hoe.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:38
Gerco schreef op zaterdag 24 juni 2006 @ 11:39:
Dat met die Format classes lijkt aardig te werken, ik ben er nog niet helemaal, maar zo te zien hoef ik noch Select Case, noch Object te gebruiken. Wanneer ik het werkend heb, post ik wel wat en hoe.
Ben benieuwd

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1