verantwoordelijkheid get
Stel we hebben deze class:
Code (php)
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:
Code (php)
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.
En hoezo zou je de naam van de get() methode zomaar veranderen? ik bedoel je hebt het toch wel uitgedacht voor dat je deze gaat bouwen... ik denk dat het systeem juist kwetsbaarder wordt als zomaar jan en alleman erbij kan.
Dit kan dus juist niet, want alleen methods in dezelfde class kunnen bij een private property, dus niet jan en alleman.
Mij lijkt het juist dat je systeem kwetsbaarder wordt als je (onnodige) verantwoordelijkheden tussen functies creëert, waardoor die functies altijd afhankelijk zijn van een andere functie.
Dank voor je reactie en ben benieuwd of meer mensen hier een mening over hebben.
"Je kan hiermee d.m.v. een regel code informatie uit een andere klasse halen maar deze niet bewerken/veranderen."
En wanneer je i.p.v. de getters en setters besluit om de property direct aan te roepen breek je deze principe.
een voorbeeldje van encapsulation ff snel van internet geplukt:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
class App {
private static $_user;
public function User( ) {
if( $this->_user == null ) {
$this->_user = new User();
}
return $this->_user;
}
}
class User {
private $_name;
public function __construct() {
$this->_name = "Visitor";
}
public function GetName() {
return $this->_name;
}
}
$app = new App();
echo $app->User()->GetName();
?>
class App {
private static $_user;
public function User( ) {
if( $this->_user == null ) {
$this->_user = new User();
}
return $this->_user;
}
}
class User {
private $_name;
public function __construct() {
$this->_name = "Visitor";
}
public function GetName() {
return $this->_name;
}
}
$app = new App();
echo $app->User()->GetName();
?>
Maar dat begrijp ik wel Reshad. Ik zeg ook niet dat je de get functie moet weggooien? Die heb je nodig om van buiten de class een property aan te spreken. Maar ik bedoel in de class zelf! Als een functie in de class zelf een property nodig heeft, dan zou ik die direct aanspreken, maar Wouter zou hiervoor de get() functie in diezelfde class gebruiken. Snap je?
Nu, dezelfde gedachtegang kan je doorvoeren naar de situatie binnen een class. 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.
Wat betreft jouw 2e alinea. Ik ben het er wederom mee eens dat alleen set() functies een private property mogen setten/wijzigen. Alleen vraag ik me af of het slim is dat overige functies die een private property willen uitlezen dit per se via de get() method moeten doen. Wat jij zegt, dat als je een property wijzigt je alleen de get functie hoeft te wijzigen klopt. Dat kan een voordeel zijn. De andere kant van het verhaal is dat alle overige functies afhankelijk worden van de get functie en er bovendien telkens een extra functie aanroep moet plaatsvinden. Weegt dit wel op tegen het voordeel vraag ik me af? Dat is dus een beetje waar ik over zit te twijfelen...
Ik heb voor mezelf bepaald dat een class autonoom moet zijn. Elke class is verantwoordelijk voor zijn eigen handel en wandel en moet ervoor zorgen dat input correct is en output correct is. Binnen de class echter mogen er wat mij betreft afhankelijkheden zijn en mag er wat makkelijk worden omgegaan met properties en data.
Het is dus een keuze, performance kan je daarin mee laten wegen.
Ik zou dus gewoon doen wat jijzelf het prettigste vind werken, maar wel rekening houden dat je met de get() tijd kunt besparen als je iets moet wijzigen in de properties.
Ben toch even benieuwd dan... zomaar een voorbeeldje. Wat zou jouw voorkeur hebben? De 1e of de 2e versie. En waarom?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
of
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Foo {
private $data = array();
public function getData() {
return $this->data;
}
public function has($key) {
return array_key_exists($key, $this->getData());
}
public function getKeys() {
return array_keys($this->getData());
}
public function count() {
return count($this->getData());
}
}
?>
class Foo {
private $data = array();
public function getData() {
return $this->data;
}
public function has($key) {
return array_key_exists($key, $this->getData());
}
public function getKeys() {
return array_keys($this->getData());
}
public function count() {
return count($this->getData());
}
}
?>
Toevoeging op 12/02/2013 09:36:14:
@Rick: thanks voor je reactie!
Ik zou de eerste doen. Omdat volgens mijn keuze de afhankelijkheid binnen de class geen probleem is. Daarbij neem ik dus voor lief dat het aanpassen van het property (mocht ik dat ooit willen doen) mij extra werk op zal leveren zoals Rick ook zegt. Dat weet ik, maar dat accepteer ik.
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.
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 ;)
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:
Code (php)
Nu gebruikt Henk ons User systeem voor een restaurant, om simpel te checken of iemand alcohol mag drinken of niet:
Code (php)
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:
Code (php)
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.
Gewijzigd op 12/02/2013 17:26:23 door Wouter J
Pffff, die keuzes ook altijd ;)