@Wouter,
Ik begrijp niet waarom een object geen public properties zou mogen bevatten, als je jouw werkwijze met get en set volgt. Want dan zijn ze net zo public.
Ger, je hebt dan grip op het setten en getten. Nu is het misschien allemaal straightforward, allewel er al een check in zit of de setting al bestaat, maar misschien dat ik dat straks wel anders wil doen. Dan moet naar mijn mening de interface hetzelfde blijven, maar de code erachter anders. Met public properties beperk je jezelf enorm, je bent gebonden aan die oncontroleerbare public property en alleen met een BC break kun je dat veranderen.
Het is ook niet zo dat ik het geheel met je oneens ben, maar met een get(property) in je object worden al je private vars gewoon public (of zie ik iets verkeerd?)
En dan vind je redenering dat je nooit public properties mag hebben niet logisch.
Ja, het is nu public. Maar OO gaat voor namelijk ook over 'in de toekomst'. Mocht ik in de toekomst checks willen doen en meer controle willen hebben op mijn settings array dan kan ik zo even chapchap de get method aanpassen en klaar is kees.
Echter als je public properties gebruikt moet je eerst die get method aanmaken en vervolgens al je code aanpassen om de get method te gebruiken en dat gaat naar mijn mening tegen de OO principes in.
Dat is ook precies de rede dat ik de regel heb dat alleen getters en setters toegang hebben tot de properties. De rest moet allemaal de getters en setters gebruiken, zelfs al is het dezelfde klasse.
En dan vind je redenering dat je nooit public properties mag hebben niet logisch.
Ik zal het je nog sterker vertellen: nooit public properties ennooit protected properties.
Bekijk het eens anders. Een class is verantwoordelijk voor alles wat er binnen die class gebeurt. Als een ander deel van de applicatie vraagt om een waarde, dan moet die class ervoor zorgen dat die iets nuttigs teruggeeft. Dat wordt erg lastig op het moment dat andere delen van de applicatie in de interne data van die class kan gaan zitten vroeten. Dan zal die class dus elke keer moeten checken of de data nog wel is wat het was. Maar nog erger, als een ander deel van de applicatie rechtstreeks een property kan uitlezen dan weet de class daar niet eens iets van en kan dus zelfs de check niet uitgevoerd worden.
Vergelijk het nu eens met een database beheerder die verantwoordelijk is voor de hele database omgeving van een bedrijf. Als er iets mis is met de databases dan is die man de klos. Denk je dat die man iedereen nu rechtstreeks lees en schrijf rechten op de database gaat geven? Ik denk het niet....
Die config gegevens moeten door de applicatie ingegeven worden. Dat kan uit een database komen, kan uit een applicatie config object komen, kan ook in hardcoded applicatie constante zitten.
Mijn Oauth config class is een algemene class die dus niet applicatie specifieke gegevens in zich heeft zitten.
euhm een config object die zijn gegevens uit de applicatie config object haalt??
en uit de database ja, maar niet alles. om de database te benaderen heb je ook een configuratie nodig. (user, pass, host, db)
Okee jij maakt een verschil tussen applicatie configuration en de configuratie voor één of andere class.
Natuurlijk moet je dat verschil maken, maar dat is het punt niet.
Als je via een config een bepaalde variabele kunt instellen is ie net zo public als je gewoon een public property aanduidt.
Dus, ik begrijp nog steeds die opmerkingen van Erwin en Wouter niet helemaal.
Ik zie in ieder geval het nut niet het niet van:
$this->setName('Ger')
of
$this->name='Ger'
public function setName($name)
{
$this->name = ucfirst($name);
}
}
?>
Controle:
<?php
class Bag
{
private $values;
public function set($id, $value)
{
if (isset($this->values[$id])) {
throw new InvalidArgumentException(sprintf('Item "%s" is already defined', $id));
}
// ...
}
}
?>
Deprecate handling:
Een user klasse had eerst een age property, maar dat is vervangen door een birthday property. Met getters kun je voor een tijdelijke oplossing zorgen, zodat de applicatie goed werkt, en tegelijkertijd meld je de user dat hij zijn script moet aanpassen.
<?php
class User
{
private $birthday;
public function getAge()
{
trigger_error('Use::getAge is deprecated, use getBirthday instead', E_USER_DEPRECATION);
euhm een config object die zijn gegevens uit de applicatie config object haalt??
en uit de database ja, maar niet alles. om de database te benaderen heb je ook een configuratie nodig. (user, pass, host, db)
Okee jij maakt een verschil tussen applicatie configuration en de configuratie voor één of andere class.
Krijgt niet haalt. Mijn Oauth config klasse krijgt de gegevens vanuit de applicatie, maar heeft zelf geen weet waar die vandaan komen. Mijn Oauth config klasse heeft dus ook geen database connectie nodig, want die werkt daar verder niet mee. Juist daarom heb ik dat gesplitst. De Oauth config klasse is applicatie onafhankelijk. In de constructor krijgt het de gegevens geinjecteerd. Binnen de applicatie mag het dan best ergens hardcoded staan, want die klassen zijn applicatie specifiek en hoef ik dus niet te kunnen hergebruiken.
Ger van Steenderen op 12/06/2013 23:09:37
Ik zie in ieder geval het nut niet het niet van:
$this->setName('Ger')
of
$this->name='Ger'
Dit is nu binnen de klasse, terwijl het voornamelijk om toegang van buiten een klasse gaat.
<?php
$obj->name = 'Ger';
//of
$obj->setName( 'Ger' );
?>
Het verschil is de controle. In het eerste geval heeft de klasse geen controle over wat er geplaatst wordt en uitgelezen wordt. Er kunnen dus geen checks plaatsvinden en er kunnen geen andere acties afgehandeld worden.
In het tweede geval heeft de klasse volledige controle. Het kan waardes veranderen, weigeren of exceptions gooien als er iets niet klopt. Daarmee kan de klasse zelf volledig zelfstandig zorg dragen voor de consistentie van de data.
Zelfs als het nu helemaal niet nodig 'lijkt' is het verstandig. In de eerste plaats vanwege toekomst. Het je setters en getters kan je checks later eenvoudig toevoegen. heb je publieke properties dan zal je al je code door moeten om te vinden waar die aangesproken worden en dat veranderen. Maar in de tweede plaats kan je nu al in de problemen komen:
<?php
class Test{};
$obj->name = new Test();
echo $obj->name;
?>
Hier krijg je nu al een foutmelding. In een setter had je dat al kunnen afvangen door ofwel te checken, ofwel te typecasten. Dus nu ga je eigenlijk al checks invoeren.