Object georienteerd je classes indelen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
Stel je hebt drie classes:
  • MyTable (een tabel)
  • MyTableReader (lees tabel in vanuit een bestand)
  • MyTableWriter (schrijf de tabel weg naar een bestand)
dan vraag ik me af wat de beste manier is om de classes object georienteerd in te delen. De mogelijkheden die ik zie:
  1. De class MyTable zou een super class kunnen zijn van MyTableReader en MyTableWriter. Dit lijkt me niet handig, omdat een reader of writer dan vast zit aan 1 tabel.
  2. De classes MyTableReader en MyTableWriter zouden een member MyTable kunnen hebben. Dit lijk me ook niet handig om bovenstaande reden.
  3. De class MyTable zou een functie read en write kunnen hebben die een reader of writer aanmaakt en aanroept.
  4. Alle classes zijn onafhankelijk en een MyTable is een parameter voor MyTableWriter en MyTableReader.
Ik neig naar de laatste mogelijkheid te gaan, maar ik heb niet het idee dat ik dan erg object georienteerd bezig ben. Ik ben erg benieuwd hoe jullie dit soort classes in zouden delen. :)

edit: En het belangrijkste natuurlijk: Waarom?

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 12-09 23:07
AlainS schreef op vrijdag 13 februari 2009 @ 20:13:
Stel je hebt drie classes:
  • MyTable (een tabel)
  • MyTableReader (lees tabel in vanuit een bestand)
  • MyTableWriter (schrijf de tabel weg naar een bestand)
dan vraag ik me af wat de beste manier is om de classes object georienteerd in te delen. De mogelijkheden die ik zie:

[list=1]• De class MyTable zou een super class kunnen zijn van MyTableReader en MyTableWriter. Dit lijkt me niet handig, omdat een reader of writer dan vast zit aan 1 tabel.
Nee, niet goed, want een Reader leest een table, en een writer schrijft naar een Table.
Een TableReader is geen Table, en een TableWriter is evenmin een table.
• De classes MyTableReader en MyTableWriter zouden een member MyTable kunnen hebben. Dit lijk me ook niet handig om bovenstaande reden.
Mja ...
Daar is toch wat voor te zeggen.
Je geeft aan je Reader of Writer mee van welke table hij moet lezen, dan wel naar schrijven.
• De class MyTable zou een functie read en write kunnen hebben die een reader of writer aanmaakt en aanroept.
Niet goed.
De Table class moet gegevens bewaren. Het is niet de verantwoordelijkheid van de Table class om de gegevens te lezen of te schrijven.
• Alle classes zijn onafhankelijk en een MyTable is een parameter voor MyTableWriter en MyTableReader.[/list]
Da's ook geen slecht idee. Alleen weet ik niet hoe dat lezen en schrijven juist in z'n werk zou gaan.
Deze oplossing betekent dat één instantie van een TableReader verschillende tables kan uitlezen. Echter, moet je ook bijhouden wat je al gelezen hebt uit welke table, etc ?
Ik neig naar de laatste mogelijkheid te gaan, maar ik heb niet het idee dat ik dan erg object georienteerd bezig ben. Ik ben erg benieuwd hoe jullie dit soort classes in zouden delen. :)
wtf is dat nu voor reden.
OO is een middel, en geen doel op zich.
Zorg ervoor dat je classes voldoen aan het SRP principe (ze zijn verantwoordelijk om één ding te kunnen doen, en moeten dat goed doen).
Ik heb een gelijkaardig systeem; maar dan voor csv-files. Ik heb een CsvFile class, en dan een Reader & een Writer. De Reader & Writer hebben een method Open die een CsvFile als argument krijgt, en dan lezen (of schrijven) ze van (naar) die file.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

Hey, interessant topic, hier worstel ik dus ook mee. Met name in combinatie met PHP.

Ik zou overigens eerder een 'superclass' SQL maken en daaronder je subclasses, zoals read en write, als uitbreiding classes onder SQL doen. Ook kan je dan (qua ontwerp) denk ik makkelijker uitbreiden.

Ook op zo'n manier behoud je de mogelijkheid om verschillende tables uit te kunnen lezen.
En, als ik het goed heb, krijg je dan ook de mogelijkheid om een database abstraction layer te maken, tussen je programmeertaal en je uiteindelijke database server software.

Acties:
  • 0 Henk 'm!

  • Paitor
  • Registratie: Maart 2001
  • Laatst online: 18-01 12:37

Paitor

rages doen :P

Hoe goed ben je met UML? Met een class diagram zou je wellicht grafisch kunnen uitbeelden wat je in programmeertaal probeert uit te drukken. In zo'n geval zie je al eerder dat je eerste voorbeeld niet werkt, een TableReader of TableWriter is geen speciale instantie van een MyTable en dus is MyTable geen superclasse van die twee.

Ik heb er zelf altijd veel baat bij als ik programmeerproblemen eerst helemaal uitteken alvorens ik het ga programmeren, omdat ik zelf dan veel meer overzicht heb.

Live Life to the Max | Kom op konijntje doe maar huppele wiebele


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 12-09 23:07
GJtje schreef op vrijdag 13 februari 2009 @ 20:40:
Hey, interessant topic, hier worstel ik dus ook mee. Met name in combinatie met PHP.

Ik zou overigens eerder een 'superclass' SQL maken en daaronder je subclasses, zoals read en write, als uitbreiding classes onder SQL doen. Ook kan je dan (qua ontwerp) denk ik makkelijker uitbreiden.
Lijkt me geen goed idee te zijn.
Wat doet die 'superclass' SQL ? Wat zijn z'n verantwoordelijkheden ?
Een reader en een writer erven dan over van dezelfde base-class ? Op den duur heb je te maken met classes die veel te veel verantwoordelijkheden hebben.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
Bedankt voor de input. :)
wtf is dat nu voor reden.
OO is een middel, en geen doel op zich.
Je hebt gelijk. Ik probeer een beeld te krijgen hoe OO in de praktijk toegepast wordt. Ik heb niet veel applicatie's gemaakt voor PC's, maar deze methode doet me erg veel denken aan C.
Zorg ervoor dat je classes voldoen aan het SRP principe (ze zijn verantwoordelijk om één ding te kunnen doen, en moeten dat goed doen).
Duidelijk.
Ik heb een gelijkaardig systeem; maar dan voor csv-files. Ik heb een CsvFile class, en dan een Reader & een Writer. De Reader & Writer hebben een method Open die een CsvFile als argument krijgt, en dan lezen (of schrijven) ze van (naar) die file.
Misschien moet ik die kant ook uitgaan. Mijn gedachte speelt dat een programma 1 of meerdere tables aan kan maken en met 1 (of meer) reader(s) en 1 (of meer) writer(s) moet kunnen lezen en schrijven. Ik vind het moeilijk om een afweging te maken in hoeverre ik classes universeel toepasbaar moet maken.
Ik heb het op school weleens gehad. Ik teken mijn ideeen meestal wel uit (met pen en papier).

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

  • CH4OS
  • Registratie: April 2002
  • Niet online

CH4OS

It's a kind of magic

whoami schreef op vrijdag 13 februari 2009 @ 20:52:
Lijkt me geen goed idee te zijn.
Wat doet die 'superclass' SQL ? Wat zijn z'n verantwoordelijkheden ?
Een reader en een writer erven dan over van dezelfde base-class ? Op den duur heb je te maken met classes die veel te veel verantwoordelijkheden hebben.
Ik zie het allemaal eerder als een soort mappen structuur:
code:
1
2
3
4
5
6
7
root
  hoofdgroep1
    subgroep1.1
    subgroep1.2
  hoofdgroep2
    subgroep2.1
    subgroep2.2
Nu ik het zo schematisch weergeef, zie ik dat die root ook weer niet echt nodig is.

[ Voor 7% gewijzigd door CH4OS op 13-02-2009 21:59 ]


Acties:
  • 0 Henk 'm!

  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Wat betreft het vraagstuk:
- Maak ik een parent class met een bepaalde basisfunctionaliteit die ik subclass en specialiseer?
tegenover:
- Maak ik een gespecialiseerde class die basisfunctionaliteiten van een andere class gebruikt?

In dat geval kun je enig houvast hebben aan de volgende vuistregel: "Favor composition over inheritance".

Wat inhoudt dat als je keuze hebt uit beide mogelijkheden zoals hier, je de tweede optie prefereert. Natuurlijk zijn er genoeg gevallen waarin overerving wel een goede keuze is, maar als je zoals in dit geval er naar zit te kijken en denkt: hm, het zou allebei wel kunnen, dan kun je deze vuistregel gebruiken.

Het idee er achter is dat
There's a tight coupling between the base class and the subclass, because of the implicit context in which the subclass code I plug in will be called. Composition has a nicer property. The coupling is reduced by just having some smaller things you plug into something bigger, and the bigger object just calls the smaller object back.
Ik weet het zelf even niet beter te formuleren.

How much can you compute with the "ultimate laptop" with 1 kg of mass and 1 liter of volume? Answer: not more than 10^51 operations per second on not more than 10^32 bits.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Als je je MyTableReader en -Writer niet aan MyTable wilt koppelen, dan kun je het ook generaliseren of abstraheren. Echter moet je hierbij wel goed nadenken of de extra moeite het wel loont. Je moet dit pas doen, zodra je het echt nodig hebt, en niet eerder.

Je zou bijvoorbeeld generieke classes Writer en Reader kunnen maken, en interfaces (of eventueel een superclasses) Readable en Writable, die MyTable dan implementeert.

Uit de mogelijkheden die je hierboven presenteert zou ik idd. ook voor de member of parameter van de reader en writer gaan. Dit is logisch bekeken gewoon het beste.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
@zwippie: Bedankt voor de input. :)
Michali schreef op maandag 16 februari 2009 @ 16:08:
Je zou bijvoorbeeld generieke classes Writer en Reader kunnen maken, en interfaces (of eventueel een superclasses) Readable en Writable, die MyTable dan implementeert.
Ik vind dit ook wel een hele aardige voor de toekomst. Ik heb het nu nog niet nodig, maar ik heb nu voor een aantal probeersels allemaal aparte readers en writers die in de basis hetzelfde doen. :)

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

Verwijderd

AlainS schreef op maandag 16 februari 2009 @ 19:16:
@zwippie: Bedankt voor de input. :)


[...]


Ik vind dit ook wel een hele aardige voor de toekomst. Ik heb het nu nog niet nodig, maar ik heb nu voor een aantal probeersels allemaal aparte readers en writers die in de basis hetzelfde doen. :)
Gebruik DI. De table reader en writer zijn verschillende functionaliteiten. Maak dus een Repository class die in zijn constructor een TableReader en een TableWriter krijgt.

In de code van de Repository maak je twee functies die de gevraagde functionaliteit uitvoeren op de of de TR of de TW.

(hint: maak interfaces van de TW en TR zodat die inwisselbaar worden).

Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
Waarvoor zou die repository class dan dienen? Wat doet die anders dan de read of een write op een TableReader, danwel TableWriter?

Dat ik interfaces van de reader en writer moet maken is me duidelijk, maar wat die repository class zou doen is me niet duidelijk.

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

Verwijderd

AlainS schreef op zondag 22 februari 2009 @ 17:54:
Waarvoor zou die repository class dan dienen? Wat doet die anders dan de read of een write op een TableReader, danwel TableWriter?

Dat ik interfaces van de reader en writer moet maken is me duidelijk, maar wat die repository class zou doen is me niet duidelijk.
Normaal gesproken regel je nog wel meer in je repository. Maar goed in dit geval is het ook al handig daar je die repository in je code kunt gebruiken; 1 klasse ipv 2. Hij dient daarmee als een facade voor je peristency (concerns).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 12-09 23:07
Verwijderd schreef op zondag 22 februari 2009 @ 17:37:
[...]


Gebruik DI. De table reader en writer zijn verschillende functionaliteiten. Maak dus een Repository class die in zijn constructor een TableReader en een TableWriter krijgt.

In de code van de Repository maak je twee functies die de gevraagde functionaliteit uitvoeren op de of de TR of de TW.
En wat is het nut / doel van die repository ? En waarom zou die een reader en een writer moeten hebben ?
(hint: maak interfaces van de TW en TR zodat die inwisselbaar worden).
Waarom moeten TW & TR onderling uitwisselbaar zijn ? Ze hebben beiden verschillende functionaliteiten, dus waarom zou je ze dezelfde abstractie moeten laten implementeren ?
Een reader is geen writer, net zoals een writer geen reader is.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
whoami schreef op zondag 22 februari 2009 @ 23:26:
Waarom moeten TW & TR onderling uitwisselbaar zijn ? Ze hebben beiden verschillende functionaliteiten, dus waarom zou je ze dezelfde abstractie moeten laten implementeren ?
Een reader is geen writer, net zoals een writer geen reader is.
Ik raak een beetje verward. Ik dacht aan zoiets:

MyDefaultTableReader
MyDetailedTableReader

zijn interfaces van MyTableReader, die alleen een MyTable inleest en de inhoud overlaat aan de implementatie van MyDefaultTableReader en MyDetailedTableReader.

Ik zie net als jou niet in hoe je daar een writer van kan maken en dat was ook niet mijn bedoeling. :)

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Vervang table, tablereader, tablewriter eens door termen als...euh... auto, monteur en verkoper.
Zie je nu het probleem?

Een auto heeft niets van doen met een monteur; een monteur maakt auto's maar is geen (afgeleide van) een auto en een verkoper werkt, net als een monteur, wel met auto's maar is geen auto en ook geen monteur.

Een tablewriter class heeft geen zak van doen met table anders dan dat 'ie de table wegschrijft. De tablereader heeft geen zak van doen met de tablewriter en het enige wat 'ie met een table doet is er 1 maken/teruggeven.

[ Voor 28% gewijzigd door RobIII op 23-02-2009 23:00 ]

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


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
AlainS schreef op maandag 23 februari 2009 @ 22:43:
[...]


Ik raak een beetje verward. Ik dacht aan zoiets:

MyDefaultTableReader
MyDetailedTableReader

zijn interfaces van MyTableReader, die alleen een MyTable inleest en de inhoud overlaat aan de implementatie van MyDefaultTableReader en MyDetailedTableReader.

Ik zie net als jou niet in hoe je daar een writer van kan maken en dat was ook niet mijn bedoeling. :)
Wat jij voorstelt kan ook wel. Je spreekt dat van je abstractie, namelijk MyTableReader (bijvoorbeeld), en je concrete implementaties of realisaties daarvan.

Maar dat heeft niet zo veel te maken met de inwisselbaarheid van een reader en een writer. Je kunt namelijk (in de meeste gevallen, misschien een zeer uitzonderlijk geval) geen writer gebruiken om iets te readen.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Alain
  • Registratie: Oktober 2002
  • Niet online
Wat je zegt is precies wat ik ervan begrijp. Als ik het verkeerd omschreven heb dan sorry en waar precies?
Michali schreef op maandag 23 februari 2009 @ 23:08:
[...]

Wat jij voorstelt kan ook wel. Je spreekt dat van je abstractie, namelijk MyTableReader (bijvoorbeeld), en je concrete implementaties of realisaties daarvan.
Ik heb vandaag eerst de software van de PLC generiek gemaakt. Nu eens kijken hoever ik kom met een generiek object om de PLC uit te lezen cq naar de PLC te schrijven. :)

You don't have to be crazy to do this job, but it helps ....


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
AlainS schreef op maandag 23 februari 2009 @ 23:36:
[...]


Wat je zegt is precies wat ik ervan begrijp. Als ik het verkeerd omschreven heb dan sorry en waar precies?
Ah nee, dan begreep ik jou schijnbaar dus verkeerd. Ik dacht dat lezen je dat onderscheid niet helemaal begreep.

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


Acties:
  • 0 Henk 'm!

Verwijderd

Je zou voor de grap eens kunnen kijken hoe java en/of C# dat aanpakken. Aangezien ik wat meer in C# zit dan in Java, klein voorbeeldje hoe je bijv. een bestand uit leest (niet zeuren over using statements enzo alsjeblieft ;-))

Textreader tr = new StreamReader("bestand.txt");
string regelUitBestand = tr.ReadLine();
tr.Close();

Zoals je ziet wordt er een instantie van een reader aangemaakt (de 'new streamreader'). Als parameter voor de constructor van het object wordt de bron meegegeven. Vervolgens kan je de reader vragen om een regel uit het bestand (ReadLine()). Als je klaar bent sluit je de reader af, en geef je de resources vrij.

De reden dat deze aanpak gekozen is, is volgens mij omdat je te maken hebt met zogenaamde unmanaged resources. Het bestand wat gelezen wordt bestaat in de grote boze buitenwereld buiten de .net omgeving, dus hier is geen 100% controle over. Door het in te pakken in een object zorg je ervoor dat deze afhankelijkheid maar op één plek voorkomt.

Dit lijkt overigens sterk op jouw oplossing 2, als ik het zo even snel bekijk.

PS: als ik het niet goed vertel, corrigeer me gerust ;-)
Pagina: 1