Ola mensen,

Stel we hebben deze class:

<?php
class Foo {

private $data = array();

public function getData {
return $this->data;
}

public function has($key) {
return array_key_exists($key, $this->data);
}

}
?>

Nu gaat het om de functie has();

In het bovenstaande voorbeeld spreekt deze functie rechtstreeks de private property $data aan.

Nu weet ik dat sommigen (waaronder Wouter) het zo op zouden lossen:

<?php
class Foo {

private $data;

public function getData {
return $this->data;
}

public function has($key) {
return array_key_exists($key, $this->getData());
}

}
?>

Wouter werkt met een heel strict "GET" beleid zoals hij zelf zegt. Alleen de "get()" methods mogen private properties aanspreken. Nu vraag ik me af of daar een reden voor is?

En hoe doen de anderen, buiten Wouter, dit? Gebruiken jullie ook overal een "get()" functie voor, of mag iedere method in een class de private properties aanspreken?

Wat zijn voordelen, wat zijn nadelen?

Wat ik zelf kan bedenken:
- alles via een get() method
voordeel: je weet zeker dat alleen de get() method de private property kan uitlezen
nadelen: 1) je roept telkens onnodig een extra method aan 2) meerdere functies worden afhankelijk van de get() method. Als de get() method wordt gewijzigd (bijv. qua naam) dan werken de method die van de get() method afhankelijk zijn niet meer. Ik zou denken dat daardoor je systeem "kwetsbaarder" wordt.
- rechtstreeks een private property aanspreken
nadeel: ook niet-get() methods kunnen private properties aanspreken (maar is dat erg?)
voordelen: er hoeven geen extra get() methods te worden aangeroepen (beter voor performance) en iedere functie die een private property moet uitlezen werkt op zichzelf en is dus niet afhankelijk van een get() method.

Ik ben benieuwd naar hoe jullie het doen en naar jullie argumenten.
Ah oké, maar dit lijkt een beetje in tegenstelling te zijn met wat je eerder zei toch?

Erwin H op 12/02/2013 09:09:19

Als al je methodes binnen de class ook alleen maar via getters en setters werken, dan hoef je je dus ook nooit zorgen te maken over wat er binnen de class gebeurt. Verander je de properties, dan hoef je alleen de getter en setter aan te passen en je weet weer zeker dat alles zonder problemen zal werken.


Nee, het ene is een feit, het andere is een keuze. Ik heb in mijn eerdere post ook dit gezegd:
Erwin H op 12/02/2013 09:09:19
Ik moet zeggen dat ik binnen een class niet zo strict ben als Wouter


Zoals de grote php guru Cruyff ooit al eens zei: "Elk voordeel heb z'n nadeel".


Haha, oké... thanks voor het meedenken. Heb weer even wat om over na te denken ;)
Dan moet ik ook nog maar even reageren, al verwoord Erwin mijn verhaal al voor het grootste deel (hoe kan het ook anders, hij is de gene die me hier over heeft laten nadenken).

Ozzie PHP
2) meerdere functies worden afhankelijk van de get() method. Als de get() method wordt gewijzigd (bijv. qua naam) dan werken de method die van de get() method afhankelijk zijn niet meer. Ik zou denken dat daardoor je systeem "kwetsbaarder" wordt.

Ik vind dit (het feit dat je systeem "kwetsbaarder") een beetje een non-argument. Je kan zeggen dat ze afhankelijk worden van de get method, maar je kan ook zeggen dat ze afhankelijk worden van de property en dat als je die een andere naam geeft, dan werken alle functies die afhankelijk zijn van die property ook niet meer. Het systeem is dus even kwetsbaar.

Ik zou zelfs, heel stiekem, durven te beweren dat mijn methode juist een stapje minder kwetsbaar is. Stel we hebben een User klasse:
<?php
class User
{
private $age;

// ...

public function setAge($age)
{
$this->age = (int) $age;
}

public function getAge()
{
return $this->age;
}
}
?>
Nu gebruikt Henk ons User systeem voor een restaurant, om simpel te checken of iemand alcohol mag drinken of niet:
<?php
class User extends BaseUser
{
public function isAllowedToDrinkAlcohol($minAge = 18)
{
return $minAge <= $this->getAge();
}
}
?>

Nu zijn we wat maandjes verder en dan kom je erachter dat het helemaal niet slim is om de leeftijd van iemand op te slaan, maar dat het slimmer is om de geboortedatum op te slaan. Dus we passen de User klasse aan.

Nu zit Henk met een probleem, zijn code werkt niet meer. In het geval van het direct aanroepen van de properties zal je nu met een probleem zitten. Met getters niet: Wat jij doet is een backwards comptability break voorkomen door de getter te behouden:
<?php
class User
{
private $birthday;

// ...

public function getAge()
{
return DateTime::createFromFormat('d/m/Y', $this->getBirthday())
->diff(new DateTime('now'))
->y;
}
}
?>

Nu zou het script van Henk niet gestoord worden, terwijl de $age property wel is verdwenen van de User klasse. Nog beter zou het zijn om dan in deze getter een deprecation te loggen, zodat Henk door krijgt dat hij een verouderde functie gebruikt. Hij zal dan zijn script gaan aanpassen en in een versie na de gene waarin je de $age hebt veranderd in $birthday zal je de hele getAge functie kunnen verwijderen.

Dit wordt heel veel gedaan in grote open-source projecten. Je kan nooit alles in 1 keer goed scripten, maar het is wel de bedoeling dat je dat zo goed mogelijk doet. Anders kun je andere mensen met problemen van jou complete rewrite van je project. Mocht je alsnog wat dingen veranderen, dan kun je met getters en setters even een tijdelijke oplossing maken zodat je later alles veilig kunt veranderen.
Thanks Wouter daar zit ook weer wat in. En wat je zegt over de afhankelijkheid van properties vs methods... tja, da's ook wel weer waar. Misschien ga ik dan toch ook maar over op het gebruik van get() functies binnen de class :-/

Pffff, die keuzes ook altijd ;)

Reageren