[oop] classes hergebruiken
Worden classes eigenlijk hergebruikt?
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
require '/pad/naar/classFoo.php';
$a = new Foo();
$b = new Foo();
$c = new Foo();
?>
require '/pad/naar/classFoo.php';
$a = new Foo();
$b = new Foo();
$c = new Foo();
?>
Ik vraag me af of als je een class inlaadt, dan alle functies bij PHP "bekend" zijn, of worden alle methods in een class telkens opnieuw ingeladen als je een nieuwe class aanmaakt??
Stel we hebben een class Foo en een class Bar. Class Bar is bijna hetzelfde als class Foo, maar heeft 2 functies minder omdat die in bepaalde situaties niet nodig zijn. Stel nu dat beide classes 15 dezelfde methods hebben en class Foo heeft er dan nog 2 extra. Stel dat PHP class Foo onthoudt, dan lijkt het me dat je beter één class (Foo) kunt gebruiken, in plaats van een class Foo en een (bijna dezelfde) class Bar. Als ik dan namelijk class Foo gebruik moeten er 17 methods worden ingeladen, maar als ik zowel class Foo als class Bar gebruik, dan moeten er 17 en 15 methods worden ingeladen.
Wie kan hier iets meer over vertellen?
2) Classes maak je omdat dat moet door een OO ontwerp, classes maak je niet omdat het goed is voor performance
3) Kritische vragen stellen is goed, maar het is beter om eerst na te denken of die vraag wel goed is. Of je niet tever doorgaat en eigenlijk alle principes overboord gooit.
Ander voorbeeld. We hebben een class User die een User aanmaakt.
Wordt nu telkens als ik een new User aanmaak die class met al zijn methods opnieuw ingeladen? Of worden de methods alleen de 1e keer als ik een User aanmaak ingeladen?
Weet jij het antwoord op mijn vraag?
verder zou het een beetje overkill zijn als elke klass in het geheugen opgeslagen zou worden toch? stel je hebt maar een paar duizend klassen... dan zou je dus elke klasse ook moeten afsluiten wanneer je het niet meer nodig hebt.
dus volgens mij niet.
Voordat we een class kunnen gebruiken moeten we deze eerst requiren. Dan zou ik dus denken dat de class wél in het geheugen wordt gezet. De 2e keer dat je diezelfde class gebruikt, hoef je 'm namelijk niet meer in te laden (requiren). Vandaar dat ik dus heel benieuwd ben hoe het nu eigenlijk zit.
Stel we hebben een class die auto's maakt, dan lijkt het me eigenlijk logischer dat PHP op de een of andere manier onthoudt welke methods er allemaal inzitten, dan dat ie telkes als er een auto wordt gemaakt opnieuw weer alle methods gaat inlezen.
Reshad, sorry, maar ik vind je denkwijze niet logisch. Allereerst is de server iets dat zeer goed is in het onthouden. Het enige wat hij niet kan is het bedenken wanneer iets onthouden moet worden. Gelukkig begrijpt de php engine dit wel en geeft hij de server heel vaak de opdracht iets te onthouden.
En daarnaast wordt er al heel veel onthouden, denk alleen al aan alle variabelen. Kleine moeite om een klasse te onthouden wanneer er eenmaal eentje is aangemaakt.
Merk ook op dat php voordat een klasse is aangemaakt ook al weet welke methods en properties een klasse heeft (denk aan de reflection klassen)
Stel we hebben een globale class Foo die key-value paren opslaat (bijv. een ParameterBag). Dit is een heel uitgebreide class die data kan toevoegen, editen, verwijderen, keys tellen enz. enz.
Nu wil ik op een gegeven moment key-value paren opslaan, maar ik weet 100% zeker dat ik deze paren niet ga editen of verwijderen, en keys tellen en overige functies heb ik ook niet nodig. Nu kan ik hiervoor perfect class Foo gebruiken, alleen eigenlijk is deze wel iets te uitgebreid omdat er functies inzitten die ik in dit specifieke geval niet nodig heb. Er is dus sprake van een stukje overhead binnen de class.
Zou het nu slim zijn om een extra class Bar te maken waarin alleen die methods zitten die ik in dit geval écht nodig heb? Een soort gestripte versie van class Foo dus??
Stel nu dat we 100 classes nodig hebben waarin we key-value paren opslaan en we weten dat we deze niet gaan editen, verwijderen enz. Dan kunnen we dus kiezen voor class Foo (met overhead) of voor class Bar (kleinere class, exact op maat).
Stel nu dat PHP de classes NIET onthoudt en we zouden kiezen voor class Foo, dan betekent dit dat er 100x een class wordt ingeladen met een hele hoop methods die niet worden gebruikt. Stel dat er 10 methods in staan die niet worden gebruikt, dan betektent dit dat er 10 x 100 = 1.000 onnodige methods worden ingeladen. Dan lijkt het me beter om voor de gestripte versie van clas Foo, namelijk class Bar, te gaan.
Echter, als PHP wel classes onthoudt dan maakt het niks uit. Dan kan ik net zo goed class Foo gebruiken, want de methods worden toch maar 1x ingelezen.
Het is een fictieve situatie, maar toch wel interessant om te weten vind ik. Maar of iemand hier ook het antwoord op weet? Tja...
Gewijzigd op 28/04/2013 23:52:43 door Ozzie PHP
Wat er wel gebeurt is als je een class opnieuw aanmaakt dat de variabelen (!) en misschien de class zelf (?) opnieuw opgeslagen worden (getest met een kleine bench) in tegenstelling als je de class opnieuw zou gebruiken. Dit scheelde wel een hoop, maar het moet natuurlijk mogelijk zijn om dat te doen.
Maar de class wordt dus niet opnieuw geladen als je deze aanroept. Misschien wordt deze wel opgeslagen, maar ik denk dat PHP wel zo slim is om alleen de verschillen op te slaan (dus de variabelen).
Aaron - op 29/04/2013 00:23:59:
Als ik het goed begrijp is je vraag of één class mermaals wordt ingeladen als je deze aanmaakt. Het antwoord is nee. Je moet eens spl autoload gebruiken en de autoloader class echo $class typen. Deze zal maar één keer voorkomen als je de class mermaals aanroept.
Ja, dit klopt. Een class bestand wordt maar 1x gerequired.
Aaron - op 29/04/2013 00:23:59:
Wat er wel gebeurt is als je een class opnieuw aanmaakt dat de variabelen (!) en misschien de class zelf (?) opnieuw opgeslagen worden (getest met een kleine bench) in tegenstelling als je de class opnieuw zou gebruiken. Dit scheelde wel een hoop, maar het moet natuurlijk mogelijk zijn om dat de doen.
Je moet inderdaad een class opnieuw kunnen aanmaken, maar wordt er dan telkens voor iedere nieuwe class geheugen gereserveerd om de methods in op te slaan? Of worden de methods maar 1x opgeslagen en verwijst iedere nieuwe class naar de opgeslagen methods?
Aaron - op 29/04/2013 00:23:59:
Maar de class wordt dus niet opnieuw geladen als je deze aanroept. Misschien wordt deze wel opgeslagen, maar ik denk dat PHP wel zo slim is om alleen de verschillen op te slaan (dus de variabelen).
Hier zou je helemaal gelijk in kunnen hebben, maar ik ben benieuwd of er iemand is die dit 100% kan bevestigen (of ontkennen).
De ene class had maar 4 functies [setId($id), setKey($key), getId() en getKey()] en de andere class 8 functies [setId($id), setKey($key), getId(), getKey(), setAlgo($algo), setRaw($raw), getAlgo() en getRaw()]. Bij beide classes riep ik dus setId($id) en setKey($key) aan om tot een verschil van 0.03 seconden op één miljoen iteraties te komen.
Dus ik denk dat zoals mijn vermoeden al daarnet zei PHP de functies gewoon eenmaal opslaat en dan voor elke class die geopend worden de variabelen nogmaals apart opgeslagen met een soort ID.
Resultaten
[Class met 4 functies]
1.7087509632111
1.7423548698425
1.6903710365295
1.7268841266632
1.7182660102844
[Class met 8 functies]
1.7572648525238
1.759959936142
1.7442409992218
1.7827949523926
1.7658550739288
Het laden van die gestripte class duurt dus waarschijnlijk langer dan het verschil die ik hier nu heb. Ook heb je normaal gezien géén 1 miljoen objecten op één pagina...
Typo's aangepast, bench resultaten en conclusie toegevoegd
In mijn voorbeeldje zou je dan dus beter voor class Foo (de uitgebreide variant) kunnen gaan. Interessant!
Er is dus wel een verschil als je een lange of korte naam gebruikt! Raar.
Een clas "Foo" en een class "FooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFooFoo"
Bij een miljoen iteraties zijn de tijden vrijwel gelijk. Je zou dus denken dat het niet aan de lange naam ligt.
Maar nogmaals, 0.03 seconden op 1 miljoen iteraties is 0.00000003 per class iteratie. Onvoorstelbaar en aangezien je een class normaal geen één miljoen keer gebruikt duurt het laden van Bar veel langer dan Foo opnieuw gebruiken.
PHP heeft dus een perfect cache mechanisme!
Typo's en toelichting aangepast
Als de ParameterBag key-value paren vasthoudt met alle CRUD methods en een FooBag alleen key-value paren vasthoudt met create en read methods zul je dus een upperklasse (AbstractBag) moeten maken die alle over eenkomstige methods bevat, in dit geval dus alle methods van de klasse die het minste kan, de FooBag.
Vervolgens extend de FooBag en de ParameterBag deze upperklasse en voegt de ParameterBag er nog een paar extra methods bij.
Dat is kijken naar hoe het in een OO design zou moeten.
Thanks allebei voor de nuttige reacties!