[OO] Constructor alle data voeren of alleen db key?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Crayne
  • Registratie: Januari 2002
  • Laatst online: 17-03 13:41

Crayne

Have face, will travel

Topicstarter
Misschien dat ik mezelf nu onsterfelijk belachelijk maak, maar ik krijg het antwoord op de nu volgende vraag niet makkelijk gevonden.

Als ik een class instance maak kan ik twee dingen doen. Ik kan in de aanroep van de class alle pertinente data meegeven als parameter voor de constructor (en daarbij haal ik dan de data eerst op uit de database) of ik kan het ID van de betreffende row meegeven en vervolgens de constructor de query uit laten voeren om de nodige variabelen te zetten.

Is hier een best practice voor?

Mijn Library Thing catalogus


Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Over het algemeen is het niet handig als je constructor verantwoordelijk is om zijn eigen gegevens uit de database te halen. Daarmee maak je je class namelijk afhankelijk van de database, wat het testen in isolation moeilijker maakt.

Als je de gegevens uit een database haalt, dan gebruik je over het algemeen een DAO om de gegevens te laden of the bewaren, of een persistence framework zoals bijvoorbeeld Hibernate.

Het is echter niet noodzakelijk om alles in de constructor mee te geven. Je kan bijvoorbeeld ook properties (of in Java: setters) gebruiken. Dat voegt aan de ene kant flexibiliteit toe, aan de andere kant kan het betekenen dat je een property vergeet te zetten.

Acties:
  • 0 Henk 'm!

  • zwippie
  • Registratie: Mei 2003
  • Niet online

zwippie

Electrons at work

Ik zou eerder kiezen voor een constructor zonder parameters en dan een methode fromArray(array) welke je aanroept met een data array die je dus al eerder uit de database hebt gehaald.
In de fromArray methode set je alleen de variabelen die je object ook werkelijk kent/nodig heeft.

De db-logica om een record op te halen zou ik dus zeker niet in de constructor zetten. Zo creëer je alleen maar een extra afhankelijkheid richting db.

Of dit best practice is: geen idee.

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!

Verwijderd

Remus schreef op maandag 24 januari 2011 @ 16:45:
Over het algemeen is het niet handig als je constructor verantwoordelijk is om zijn eigen gegevens uit de database te halen. Daarmee maak je je class namelijk afhankelijk van de database, wat het testen in isolation moeilijker maakt.
Dit ligt er toch maar helemaal aan wat voor class het is, als het gaat om een mode/DAO/active record/ORM achtige class zal dit toch juist wel de bedoeling zijn, of je dan de ID als parameter meegeeft is een tweede natuurlijk.

Wat natuurlijk altijd best practice is, is om je data afhandeling los te koppelen van de applicatie logica, dit is de basis van MVC / PAC of n-tier applicatie design.


@Crayne ... don't worry ... je had je belachelijker gemaakt als je het niet gevraagd had en gewoon maar wat gedaan had ;)

Acties:
  • 0 Henk 'm!

  • Styxxy
  • Registratie: Augustus 2009
  • Laatst online: 15:22
Je kan natuurlijk ook constructor overloading gebruiken om verschillende mogelijkheden van aanmaken te voorzien.

Acties:
  • 0 Henk 'm!

  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Je kan natuurlijk ook gewoon een default constructor gebruiken en dan een intialise die overloaded is zodat je de class op alle manieren die je nodig hebt kan initialiseren.

Constructors horen simpel te zijn en niet te veel werk verrichten dat levert alleen maar poblemen op wanneer er exceptions tijdens contstuctie worden gegenereerd.

Voordeel van de initialise is dat je er ook alles mee kan reseten zonder een nieuw object te hoeven creeeren. Plus een factory hoeft niks van de classes te weten om een instance te creeeren.

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Wat Remus zegt is wel heel belangrijk en moet je goed overwegen, omdat een dependency introduceren de code per definitie complexer maakt. Het is een goede vuistregel om complexiteit sowieso zo veel mogelijk uit de weg te gaan.

Je moet goed nadenken over de verantwoordelijkheid van de class en die niet koppelen aan een dependency die je niet per se nodig hebt. Dat is immers ook een contradictio in terminis: een afhankelijkheid die je niet echt nodig hebt. M.a.w., als de class geen feitelijke afhankelijkheid van de database heeft (bijvoorbeeld: de gegevens kunnen ook ergens anders vandaan komen, zoals fixtures in een unit test) dan moet je die dependency elimineren.

Je kunt dus beter uitgaan van een laag in je applicatie die in staat is records te genereren uit data (bijvoorbeeld via een Builder), dan van een class die "zichzelf" kan opbouwen op basis van een id, omdat dat suggereert dat een object van dat type alleen kan bestaan (en dus kan functioneren) als het een 'id' heeft. Of als het in een database staat. Maar dat is in vrijwel alle gevallen onzin. De database is alleen maar een manier om de data op te slaan, daar heeft de (model) class en de functies die de class meedraagt zelf meestal niets mee te maken. Een goede O/R mapper zal dat ook loskoppelen. Active Record is mede daarom een draak van een pattern en is iets wat je liefst uit de weg moet gaan, omdat dat precies de reden is dat op Active Record gebaseerde business logic heel lastig te testen is.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Remus
  • Registratie: Juli 2000
  • Laatst online: 15-08-2021
Verwijderd schreef op maandag 24 januari 2011 @ 17:06:
Dit ligt er toch maar helemaal aan wat voor class het is, als het gaat om een mode/DAO/active record/ORM achtige class zal dit toch juist wel de bedoeling zijn, of je dan de ID als parameter meegeeft is een tweede natuurlijk.
Over het algemeen staat een DAO los van de class(es) die hij maakt, hetzelfde geld voor ORM: in principe weet de class niets van het bestaan of gebruik van de database*, het ORM framework zorgt voor het laden en opslaan, niet de class zelf.

*) Dit is een te simpele voorstelling: over het algemeen zal bij het ontwerp van een class wel rekening gehouden worden met het feit dat het in of uit een database komt, en soms - JPA/Hibernate - bevat de class annotaties tbv de ORM mapper.

Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
quote: Remus
en soms - JPA/Hibernate - bevat de class annotaties tbv de ORM mapper.
Voor de puristen: Dit kun je ook voorkomen door die mapping in een externe configuratie te doen, dat was de normale gang van zaken voordat annotaties toegevoegd werden aan Java, en als het echt om scheiding van logica gaat is dat nog de logische keuze. Wel meer werk natuurlijk.

@topic, een gelijksoortig topic is eerder langsgekomen, daar kwam ook ongeveer uit dat een model-object (iets dat data bevat) niet zelf verantwoordelijk zou moeten zijn om zichzelf met data te vullen. Een constructor dat alle data ontvangt (via losse parameters, een array met data of anders een builder object of een resultset, evt. een factory method) heeft hierbij de voorkeur. De gehele datastructuur bestaat op zich uit drie delen:

* De datasource
* De models
* De service die de bovenstaande twee aan elkaar koppelt

Een datasource zou in dit geval een SQL abstractielaag kunnen zijn, maar zou ook zomaar een webservice kunnen zijn, een XML parser, of een speech-to-text iets (om maar wat willekeurige voorbeelden te noemen).

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Volgens mij gebruik je normaal gesproken een factory die die dingen aanmaakt en initialiseert. Andere factories kunnen dan de data mogelijk uit een andere source halen. Dat scheidt je applicatie van je data sources.
Pagina: 1