[oop] class locken
Een vraagje... ik heb een class waarin ik data kan opslaan en deze class kan ik locken zodat er geen data meer aan kan worden toegevoegd.
Nu had ik dus in die class een is_locked() method gemaakt, zodat ik kan zien of een object gelockt is.
Echter, nu zit ik daar nog even over na te denken en nu vraag ik me af of die is_locked() method wel nodig is? Want, zo besef ik me ineens, het zou raar zijn om eerst te kijken of het object gelockt is, en zo nee om dan pas gegevens toe te voegen. Blijkbaar wil je gegevens toevoegen en mag het object op dat moment simpelweg niet op slot zitten. Dus hoef je dit ook niet te testen!
Zijn jullie het eens met mijn gedachte dat het dus onzin is om een is_locked() method te hebben?
Ja
eerdere uitleg van Wouter over verantwoordelijkheden op vier niveaus eigenlijk wel aardig. Die is_locked() hoort er namelijk hooguit in als je de verantwoordelijkheid bij de klasse zelf legt.
Ik vond de >> Ja
Oké.
@Ward:
Ik snap niet helemaal wat je bedoelt. Of ik begrijp jou niet, of jij mij niet.
De vraag is, is die is_locked() method überhaupt nodig. In 1e instantie dacht ik van wel. In 2e instantie van niet, want waar heb ik die eigenlijk voor nodig?
Stel ik wil iets toevoegen aan een class, dan is het raar om eerst te checken of ik wel iets kan toevoegen. Blijkbaar wil ik iets toevoegen, en als op dat moment heb object op slot zit, dan zit er blijkbaar iets fout in m'n logica. Of zie jij dat anders?
Gewijzigd op 14/05/2014 20:32:34 door Ozzie PHP
Vervolgens is de vraag of je dat dan wel moet afhandelen met een is_locked(). Dat zou je kunnen doen als je het op het niveau van de klasse zelf wilt oplossen, maar je kunt het ook oplossen op de drie andere niveaus die Wouter noemde: de setters, een hiërarchie van klassen of de applicatie.
Kun je een voorbeeld geven?
De class die ik nu heb kun je alleen locken en niet unlocken. Stel je krijgt bijv. externe data binnen, dan kun je het object locken zodat je geen data kunt toevoegen of wijzigen.
Nu had ik dus keurig een public is_locked method gemaakt, zodat een andere class kan testen of het object gelocket is. Het idee was zeg maar dit:
Maar achteraf zat ik dus te bedenken... oké.. ik wil iets toevoegen, maar stel dat het object wél gelocked is. Wat dan? Dan kan ik dus de data niet toevoegen. En dat slaat volgens mij nergens op. Dus, ik wil iets toevoegen, maar ojee... het object zit op slot dus dan voeg ik maar niks toe. Volgens mij, en zeg het me aub als ik het verkeerd zie of als ik iets over het hoofd zie, slaat dat nergens op. Volgens mij moet je op het moment dat je iets gaat toevoegen simpelweg zelf 100% zeker weten dat dit ook kan. En vanuit dat oogpunt heeft volgens mij die is_locked() method dus geen enkele toegevoegde waarde. Mee eens?
Een ander voorbeeld is een active record pattern voor objecten die maar door één gebruiker of proces tegelijk kunnen worden gewijzigd.
Voor al die situaties geldt, zoals gezegd, dat het ook anders kan, zonder is_locked(). Je zou bijvoorbeeld de setters tijdelijk dienst kunnen laten weigeren. Of je legt de verantwoordelijkheid bij de applicatie en laat die de toestand van het systeem als geheel controleren.
Bij mij gaat het gewoon om objecten die onderdeel zijn van het framework. Ik zou bijv. in zo'n object de POST data kunnen opslaan. Door het object te locken, voorkom ik dat iemand de POST data kan wijzigen, want dat wil je natuurlijk niet. Maar die is_locked method voegt dus niets toe, dus die sloop ik eruit.
Je request object kan je toch nooit vanuit de applicatie wijzigen?
Wat bedoel je Ger? Hangt er vanaf hoe je het programmeert toch? Ik lock de objecten, dus dan kun je het inderdaad niet wijzigen.
Dat object valt toch niet te wijzigen, dus om daar adder/setter methods aan toe te voegen is pure onzin.
Ah oké.. ik gebruik een universele class waar dat al in zit en daar is het zeker geen onzin. Maar voor de verdere discussie is dat een irrelevant detail.
Ik denk dat het binnen OOP zeer significant is.
Het is een class om data vast te houden. Het kan bijv. POST data zijn, of COOKIE data, maar ook configuratie data, of data afkomstig van een externe partij. Sommige frameworks noemen het ook wel een parameter bag. Het voordeel is dat je niet voor alles een niewe class hoeft te maken, maar gewoon één universele class gebruikt.
Vervolgens maak je dus ook een LockedParameterBag of een ImmutableParameterBag of hoe je het ook noemt, die alleen maar getters bevat.
Hoe moet ik dan zonder setters de informatie setten? :-s
public __construct(array $parameters = array()) {...}
Dat zou kunnen, maar daar zie ik zelf wel nadelen aan. Ik zou dan rechtstreeks vanuit de constructor setten, en niet met aparte setters werken. En, het kan ook zo zijn dat ik op meerdere plekken iets wil toevoegen en de class daarna pas wil locken. Dat gaat in deze opzet niet.
Je zou het bijvoorbeeld ook met de setters zelf kunnen regelen, een van de andere alternatieven. Laat de setters alleen parameters accepteren die nog niet in de locked paramater bag voorkomen. Komt een parameter wel voor, dan wordt die geweigerd of genegeerd. De verantwoordelijkheid over de juistheid van de parameters plaats je bij validators buiten de parameter bag, zodat je parameter bag uitsluitend bruikbare data bevat.
Maar ik snap niet echt wat je bedoelt Ward. Ik heb gewoon een object met setters en getters. op het moment dat je het object locket, dan kun je geen gegevens meer wijzigen/toevoegen/verwijderen. Doe je dat wel, dan volgt een exception. Dat is toch een prima oplossing? Of zie ik iets over het hoofd?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class ImmutableParameterBag
{
private $Parameters = array();
public function set($key, $value)
{
if (!array_key_exists($key, $this->Parameters)) {
$this->Parameters[$key] = $value;
}
}
public function get($key)
{
if (array_key_exists($key, $this->Parameters)) {
return $this->Parameters[$key];
} else {
return null;
}
}
}
?>
class ImmutableParameterBag
{
private $Parameters = array();
public function set($key, $value)
{
if (!array_key_exists($key, $this->Parameters)) {
$this->Parameters[$key] = $value;
}
}
public function get($key)
{
if (array_key_exists($key, $this->Parameters)) {
return $this->Parameters[$key];
} else {
return null;
}
}
}
?>
Het hangt er echter nogal van af:
- wil je in één keer een locked object hebben (gebruik bijvoorbeeld de constructor);
- wil je meer gecontroleerd in stappen read-only data hebben (gebruik bijvoorbeeld de setters);
- wil je een open object hebben dat alleen op afroep locked wordt (gebruik bijvoorbeeld een methode).
Wáárom wil je data of objecten locked maken? Die vraag hoort er eigenlijk aan vooraf te gaan.