[oop] meningen... wat is goed?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ozzie PHP

Ozzie PHP

08/04/2013 14:50:15
Quote Anchor link
Een eerder topic vandaag heeft mij aan het denken gezet over OOP.

Ik wil graag jullie MENINGEN horen! Dus iedereen die iets doet met OOP, reageer alsjeblieft even.

Stel dat we een class hebben die een auto in elkaar zet. Laten we het simpel houden. Deze class zoekt op basis van het opgegeven model de juiste autobanden, de juiste motor, de juiste carrosserie en het juiste interieur (dashboard, stoelen, bekleding) en installeert en configureert deze zaken vervolgens. Nogmaals, het is even een heel simpel voorbeeld. Het gaat vooral om de gedachte. In mijn vorige topic zei Wouter dat je de methoden in een class gescheiden moet houden van de constructor. En daar kan ik zeker wel inkomen. Je zou dan het volgende krijgen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
$model
= 307; // we gaan een Peugeot 307 maken

$auto = new Auto($model);
$auto->zoekEnInstalleerBanden();
$auto->zoekEnInstalleerMotor();
$auto->zoekEnInstalleerCarrosserie();
$auto->zoekEnInstalleerInterieur();

?>

Voila, we hebben een Peugeot 307 gefabriceerd!

Nu komt de vraag... een auto wordt altijd op dezelfde manier gebouwd met behulp van de bovenstaande 4 functies. Aangezien deze functies altijd moeten worden uitgevoerd om een auto te maken, is mijn vraag de volgende.

Vinden jullie (de OOP gebruikers) het een goed idee om de 4 functies vanuit de constructor aan te roepen. Dan zou je om een Peugeot 307 te maken alleen nog maar dit hoeven te doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$model
= 307; // we gaan een Peugeot 307 maken

$auto = new Auto($model);

?>

En de Peugeot 307 is klaar.

De 4 functies zouden we private kunnen maken, zodat we deze niet van buitenaf kunnen aanroepen. De complete auto wordt dus gemaakt door enkel het model mee te geven aan de constructor.

Graag reacties... wel of geen goed idee? En waarom wel of niet?

Ik ben erachter dat in de OOP wereld er veel sprake is van persoonlijke voorkeur. Dat is niet erg, ik ben gewoon benieuwd naar jullie meningen. Dus wat zouden jullie doen. De functies handmatig aanroepen, of triggeren vanuit de constructor?
 
PHP hulp

PHP hulp

04/02/2023 06:07:48
 
Wouter J

Wouter J

08/04/2013 14:57:48
Quote Anchor link
Ik zou die functies doen zoals in het eerste voorbeeld. Want nu, in het geval van een Peugot 307, zijn dit misschien wel de stappen. Maar als ik een Ferrari laat maken moet ik een extra stap hebben: het erop zetten van een spoiler.

En deze Peugot 307 krijgt nu misschien een simpel motortje, maar wat als ik straks een klant krijg die er een V8 in wilt hebben? Moet ik dan speciaal voor die klant een nieuwe klasse maken met een V8 motor erin?

We gaan nog even verder, er komt een klant aan in mijn winkel en die klant lijkt toevallig bij Pirelli te werken. Die hoeft echt geen banden onder zijn auto, die regelt hij zelf wel. Dan verdwijnt er dus een stap. Moet ik dan een totaal nieuwe klasse, AutoForPirelliGuy, maken?

En we fantaseren door, Peugot heeft een nieuwe auto ontwikkeld die geen motor meer heeft. Hij beweegt volledig door het magnetisch veld van de weg. Hierdoor moeten we een nieuwe carrosserie hebben en kan de motor helemaal weg. Weer een nieuwe stap maken?
Gewijzigd op 08/04/2013 14:58:06 door Wouter J
 
Ozzie PHP

Ozzie PHP

08/04/2013 15:05:30
Quote Anchor link
Thanks Wouter :)

Dit zijn precies de soort voorbeelden waar ik naar op zoek ben, want dat zet mij ook weer aan het denken. En je hebt hier zeker een punt.

Dan kom ik ook gelijk weer met wat tegenargumenten :)

Stel we geven in de constructor mee wat er moet worden geinstalleerd?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php

public function __construct($model, $banden = true, $motor = true, $carrosserie = true, $interieur = true) {

}


?>

Voor de Pirelli guy die geen banden wil doen we nu dit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$model
= 307;

$auto = new Auto($model, false); // de auto krijgt alle opties behalve banden

?>

Ik snap dat dit misschien een beetje een flauwe oplossing is, maar het is wel goed om een besef te krijgen waarom je bepaalde dingen wel of niet zou moeten doen.

Dus... jij bent weer aan zet. Waarom zou jij dus dit doen (voor de Pirelli guy):

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
$model
= 307;

$auto = new Auto($model);
$auto->zoekEnInstalleerMotor();
$auto->zoekEnInstalleerCarrosserie();
$auto->zoekEnInstalleerInterieur();

?>

en niet dit...

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$model
= 307;

$auto = new Auto($model, false);

?>
 
Wouter J

Wouter J

08/04/2013 15:09:56
Quote Anchor link
Je begrijpt hopelijk dat ik niet voor niks 3 voorbeeldjes plaatste.
Pirelli guy is 1 van die 3 voorbeeldjes, probeer nu met jouw code de andere 2 goed werkend te krijgen?
 
Tim S

Tim S

08/04/2013 15:18:42
Quote Anchor link
Ik ben het met wouter eens, ik vindt het erg onoverzichtelijk om veel in een constructor te zetten.

$auto = new Auto($model,false,false,false,false);

Dit ziet er natuurlijk ook niet uit.
 
Bart V B

Bart V B

08/04/2013 15:20:07
Quote Anchor link
Een constructor gebruik je toch alleen maar voor die dingen die je object beslist nodig heeft?
Het ding weet niets, en is afhankelijk van het gene wat hij gebruikt.
Oftewel, het is een blauwdruk van.

Dus waarom zou je dan een constructor gebruiken om die dingen te zetten?
Als meneer geen standaard banden wenst, kan je ze beter setten denk ik.
 
Ozzie PHP

Ozzie PHP

08/04/2013 15:30:30
Quote Anchor link
@Wouter: Ah ja, oké...

Nou stel dus... we hebben een auto zonder motor. Deze Auto class is dusdanig intelligent dat hij aan de hand van het model kan bepalen hoe de auto geassembleerd moet worden. Bij de auto zonder motor weet hij dus dat er geen motor wordt geplaatst.

Wat betreft de V8 motor... die past niet (we gaan er in het voorbeeld vanuit dat er maar 1 passende motor is).

Om de vraag dus wat breder te trekken... de class is zelf in staat om een auto te maken. Hij heeft zelf al die intelligentie in huis. Waarom zouden we dan nog handmatig al die functies gaan aanroepen? Dat is eigenlijk in essentie mijn vraag.

Oké... een heel ander voorbeeld. Stel we hebben een attractie in een pretpark, bijv. een spookhuis. Bij dat spookhuis is een "machinist" haha, hoe noem je zo iemand? Nou ja, in ieder geval iemand die de knoppen bedient. Hij doet de volgende handelingen:

1) Druk op knop A: er gaat een deur open en de bezoekers kunnen naar binnen in de wachtruimte
2) Precies 30 seconden later, druk op knop B: het licht in de wachtruimte gaat uit en de bezoekers zien niks meer
3) Druk op knop C: er worden bliksemschichten afgevuurd
4) Druk op knop D: er komt een treintje aangereden en de bezoekers in de wachtruimte moeten instappen
5) Druk op knop E: de vergrendeling aan de zijkant sluit
6) Druk op knop F: treintje gaat rijden.
7) Druk op knop A: de deur van de wachtruimte gaat weer open en nieuwe bezoekers kunnen naar binnen
8) Druk op knop G: het rijdende treintje wordt stopgezet op een hoog punt
9) Druk op knop H: het stopgezette treintje raast met hoge snelheid naar beneden
10) Druk op knop I: afremmen van treintje
11) Druk op knop J: treintje stopt
12) Druk op knop K: vergrendeling opent en bezoekers stappen weer uit

Dit gaat zo de hele dag door. De uitgevoerde stappen zijn telkens hetzelfde.

Nu de vraag, waarom niet alleen 1 knop Start en de rest gaat vanzelf?
Gewijzigd op 08/04/2013 15:31:07 door Ozzie PHP
 
Bart V B

Bart V B

08/04/2013 15:34:35
Quote Anchor link
Jou laatste vraag is heel simpel te beantwoorden:

Stel het deurtje sluit te vroeg en er zit iemand tussen?
Treintje gaat rijden en de mensen zijn nog niet allemaal ingestapt?
Daarom zitten er meestal meerdere knopjes en controle op. ;)
Gewijzigd op 08/04/2013 15:40:15 door Bart V B
 
Ozzie PHP

Ozzie PHP

08/04/2013 15:40:57
Quote Anchor link
Correct, maar het gaat dus om dingen die altijd hetzelfde zijn... oké, nog globaler dan...
We hebben een class met 3 methods die altijd na elkaar moeten worden uitgevoerd. Als volgt:


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$class
= new FooBar();
$class->doFoo();
$class->doBar();
$class->doFooBar();
?>

Waarom dan niet een constructor maken die deze 3 methods aanroept, zodat je zelf nog alleen maar dit hoeft te doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
new FooBar();
?>
Gewijzigd op 08/04/2013 15:41:34 door Ozzie PHP
 
Wouter J

Wouter J

08/04/2013 15:43:39
Quote Anchor link
Quote:
Om de vraag dus wat breder te trekken... de class is zelf in staat om een auto te maken. Hij heeft zelf al die intelligentie in huis. Waarom zouden we dan nog handmatig al die functies gaan aanroepen? Dat is eigenlijk in essentie mijn vraag.

Dus jij gaat voor elke mogelijke combinatie van een merk (want een Peugot 307 kan meerdere versies hebben, bijv. de sport versie of de stad versie) de klasse weer vullen? Als Peugot een nieuwe auto uitbrengt vul je die hele klasse weer? Je mag er niet zomaar van uitgaan dat 'de klasse intelligent is', de klasse kan niks jij moet hem intelligent maken. En dan komen we bij een basis principe van OO: Isoleer wat verandert
Het geen wat veranderd (hoe een auto in elkaar zit) mag niet in een klasse zitten die vast staat.

Quote:
Nu de vraag, waarom niet alleen 1 knop Start en de rest gaat vanzelf?

Goed nu gaan we heel erg afwijken van het programmeren. Je probeert nu code als real-life dingen te zien, dat is natuurlijk niet waar.
Probeer dus eerst een meer real-use-case scenario te bedenken voor je volgende reactie.

Quote:
Waarom dan niet een constructor maken die deze 3 methods aanroept, zodat je zelf nog alleen maar dit hoeft te doen:

Dat is natuurlijk veel te vaag. OO is niet in elk scenario hetzelfde. Je moet je dus eerst een preciezer voorbeeld geven en dan zul je zien dat er altijd een goede rede is om ze apart aan te roepen.

Jij gaat je voorbeelden steeds vager maken, zodat we je op gegeven moment gelijk moeten geven. Als dat echt zo is dan is er dus 1 conclusie: Jouw techniek is verkeerd, omdat blijkt dat in real-case-scenario's er iets mis is.
Gewijzigd op 08/04/2013 15:46:08 door Wouter J
 
Ozzie PHP

Ozzie PHP

08/04/2013 15:54:20
Quote Anchor link
Wouter J op 08/04/2013 15:43:39:
Dus jij gaat voor elke mogelijke combinatie van een merk (want een Peugot 307 kan meerdere versies hebben, bijv. de sport versie of de stad versie) de klasse weer vullen? Als Peugot een nieuwe auto uitbrengt vul je die hele klasse weer?

Ik denk dus bijv. aan een config bestand:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
307:
  banden: pirelli 307
  motor: 34as-AD130PK
  carosserie: peugeot default
  interieur: leer


Wouter J op 08/04/2013 15:43:39:
En dan komen we bij een basis principe van OO: Isoleer wat verandert

Maar als het in een config bestand staat, staat het buiten de class.

Wouter J op 08/04/2013 15:43:39:
Quote:
Nu de vraag, waarom niet alleen 1 knop Start en de rest gaat vanzelf?

Goed nu gaan we heel erg afwijken van het programmeren. Je probeert nu code als real-life dingen te zien, dat is natuurlijk niet waar.
Het is misschien niet waar, maar daardoor niet minder waar :-) De vraag is... als iets een vaste routine heeft, waarom zou je dan die routine telkens handmatig aanroepen?

Stel we hebben een verwarmings class. Door die class aan te roepen kan ik de verwarming in een huis aanzetten.

We zouden dit kunnen doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
$verwarming
= new Verwarming();
$verwarming->controleerWaterToevoer();
$verwarming->controleerWaterNiveauInBoiler();
$verwarming->controleerOfGeiserAanstaat();
$verwarming->stelTemperatuurIn(21); // 21 graden
?>

Maar we zouden ook dit kunnen doen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
new Verwarming(21);
?>

Snap je wat ik bedoel?
Gewijzigd op 08/04/2013 15:55:53 door Ozzie PHP
 
Wouter J

Wouter J

08/04/2013 15:58:26
Quote Anchor link
Maar wat je nu doet met deze code:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
new Verwarming(21);
?>

Is iets anders dan de verwarming aanzetten. In dit geval is het namelijk de verwarming installeren.

Vervolgens gebruiken we bijv. een method Verwarming#setTemperature(21) om de verwarming in te stellen. En deze roept al deze 4 methods aan. Natuurlijk ga je die in dit geval niet allemaal zelf aanroepen, wat je natuurlijk ook niet gaat doen is telkens een nieuwe verwarming installeren als je de temperatuur hoger of lager wilt zetten.
 
Tim S

Tim S

08/04/2013 15:59:20
Quote Anchor link
In je stelTemperatuurIn methode kan je die controles dan beter doen.
 
Ozzie PHP

Ozzie PHP

08/04/2013 16:06:15
Quote Anchor link
Hmm, ja... zit wat in.

De situatie zoals ik die schets zal ook niet vaak voorkomen, maar als ie dus voorkomt wat moet ik er dan mee.

Even terugkomend op het voorbeeld van de autoloader... ik heb dus een register functie die altijd moet worden aangeroepen om de class te laten werken. Dus zodoende vroeg ik me af waarom ik 'm dan niet in de constructor zou aanroepen.

Stel bijv. dat je bij die verwarmingsclass altijd (voordat je de verwarming gaat installeren) zou willen controleren of er wel een leidingstelsel aanwezig is in het betreffende pand, waarom zou je die controle dan niet in de constructor uitvoeren in plaats van:

$verwarming = new Verwarming();
$verwarming->checkLeidingStelsel();
 
Ward van der Put
Moderator

Ward van der Put

09/04/2013 08:16:15
Quote Anchor link
Ozzie PHP op 08/04/2013 16:06:15:
Even terugkomend op het voorbeeld van de autoloader... ik heb dus een register functie die altijd moet worden aangeroepen om de class te laten werken. Dus zodoende vroeg ik me af waarom ik 'm dan niet in de constructor zou aanroepen.
Een autoloader is om verschillende redenen een uitzondering. Autoloaders worden aangeroepen in de volgorde waarin je ze op een stack plaatst. Dat betekent dat je het registreren van de ene autoloader niet los kunt zien van het registreren van een andere autoloader. Wil je daarover wel controle houden, dan zou je het registreren bijvoorbeeld kunnen verplaatsen naar één centrale Registry waar alle autoloaders zich moeten "aanmelden".

Ozzie PHP op 08/04/2013 16:06:15:
Stel bijv. dat je bij die verwarmingsclass altijd (voordat je de verwarming gaat installeren) zou willen controleren of er wel een leidingstelsel aanwezig is in het betreffende pand, waarom zou je die controle dan niet in de constructor uitvoeren in plaats van:

$verwarming = new Verwarming();
$verwarming->checkLeidingStelsel();

De verwarming "weet" niet dat ze is aangesloten op een leidingstelsel. En al helemaal niet dat dit leidingstelsel zich in een pand bevindt. Sterker nog, de verwarming weet niet eens wat een leiding of een pand is.

Een controle uitvoeren is iets anders dan totale controle willen hebben. De verwarming hoeft alleen een fout te constateren (ik voel te weinig waterdruk op mijn drukmeter) en die te melden (ik doe het derde ledje van links aan). Daarna is het aan de eigenaar van de verwarming om iets te doen met de rode ledjes.
Gewijzigd op 09/04/2013 08:17:30 door Ward van der Put
 
- Raoul -

- Raoul -

09/04/2013 11:35:22
Quote Anchor link
Ozzie.. wat probeer je nu eigenlijk te doen? Een auto inladen met de juiste properties? Dan maak je beter gebruik van een factory.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.