Door
Lord Gaga
op 19-06-2014 09:58
gewijzigd op 19-06-2014 10:00
1.156 views
Hallo,
Op dit moment ben ik bezig met een aantal classes en ik snap even niet tot in hoeverre ik moet valideren.
Stel je hebt een class die een ID en een naam verwachten als parameters.
Controleer je in de class dan ook of:
- Het ID een number is
- Deze number een integer is
- De naam een string is
- De string alleen uit letters bestaat
Of gaat dit te ver?
Ik hoop dat iemand me hier antwoord op kan geven.
Alvast bedankt!
Edit:
De parameters zijn geen user input maar worden door de programmeur (in dit geval ik) zelf ingevoerd.
Dan moet je expliciet een validator aanroepen en dat vereist altijd een actieve ingreep (die je kunt vergeten). Het kan beter impliciet en passief:
<?php
class ProductMapper
{
public static function fetchById(ProductIdentifier $id)
{
// <...>
return new Product($id);
}
}
class Product
{
private $Id;
public function __construct(ProductIdentifier $id)
{
$this->Id = $id;
}
}
?>
Hiermee gebeurt het automatisch en kan niemand het dus nog vergeten of het verbouwen tot iets dat het systeem ondermijnt. We hebben één class ProductIdentifier die bepaalt wat een geldige product-ID is én alle klassen houden zich daar aan.
>> Maar met een ID is het lastig vind ik. ALs een ID niet klopt wordt ie simpelweg niet gevonden.
Dan kan ook. En gebeurt ook: het bestaat gewoon niet als een query 0 retourneert. Dat zegt dan echter meer iets over het bestaan van de ID, niet over de geldigheid van die ID.
[offtopic]
In het Groot Handboek Micro-optimalisatie zou je een hoofdstuk kunnen opnemen over redenen waarom je géén databaseverbinding moet openen als je op voorhand al weet dat iets toch niet gevonden zal worden in de database.
[/offtopic]
Je maakt nu gebruik van een ProductIdentifier, maar die moet je toch ook actief aanroepen?
$product_identifier = new ProductIdentifier($id);
Waar zit dan het verschil?
En nu ga je dus vanuit de mapper een object dat enkel een ID met zich meedraagt meegeven aan het product? En dat object ga je dan weer als property instellen?
Is dat niet vreemd? Het Product moet gewoon een geldig ID krijgen. Jij maakt er nu een object om te zorgen dat het ID is gevalideerd, waarmee je de bevoegdheid van het valideren toch enigszins bij de Product class legt. Mijns insziens moet de ID van de Product class ook daadwerkelijk een ID zijn, en niet een "controle object".
Je kunt een vergelijking trekken met een interne klasse van PHP zelf: DateTime. Iedereen die deze klasse gebruikt, en dus elk systeem dat deze klasse gebruikt, moet erop kunnen vertrouwen dat deze klasse een geldige (valide) datum en tijd aanhoudt. Daarom ga je niet zelf lopen aanrommelen met timestamps als integers of allerlei ISO-strings of arrays met uren/minuten/seconden: iets van de TimeStamp-class betekent voor iedereen hetzelfde.
Om vergelijkbare redenen kun je een class ProductIdentifier opvoeren, zodat iedereen en alle klassen het over hetzelfde heeft zodra een Product-ID nodig is.
Je hebt gelijk: ergens moet die $id worden aangemaakt. Maar zo heel veel werk is dat niet, terwijl je er veel voor terugkrijgt. Dit kan van alles betekenen:
$id = 12;
En dit kan echter maar één ding betekenen, voor de klasse zelf én voor alle klassen die de klasse gebruiken:
Ik moet zeggen dat ik deze oplossing nog nooit ben tegengekomen. Tot nog toe zie ik altijd gewoon $id staan.
Maar dat neemt niet weg dat het een handige oplossing zou kunnen zijn. Maar maak je dan voor ieder object wat een ID vereist een apart Identifier object? En als je dan die lijn even doortrekt...
<?php
$admin = new Admin();
$admin->setName('Ward');
?>
Zou volgens jouw beredenering dus dit worden?
<?php
$admin = new Admin();
$name = new Name('Ward');
$admin->setName($name);
?>
Correct? En idem voor e-mailadres, leeftijd enz. ?
Het is toch gewoon dependency injection met een cast naar het gewenste type?
In plaats van:
public function Foo(array $product_data)
krijg je:
public function Foo(ProductIdentifier $id)
Zo heel spannend is dat niet. In plaats van "het moet een array zijn" formaliseer je gewoon "het moet een Product-ID van de klasse ProductIdentifier zijn".
Ik snap nog steeds niet waar en wanneer ik nou precies moet gaan valideren.
Op dit moment heb ik het volgende:
Client.prototype.setCanvas = function setCanvas(canvas)
{
try
{
if (Common.isNodeSpecific(canvas, 'canvas'))
{
this._canvas = canvas;
return true;
}
else
{
if (DEBUG_MODE)
{
console.error('Failed to set canvas: ' + canvas + ' is not a valid canvas element');
}
return false;
}
}
catch(error)
{
if (DEBUG_MODE)
{
console.error('Failed to set canvas');
console.error(error.stack);
}
return false;
}
};
Is doet een goede manier, of moet die hele validatie ergens anders?
Ergens vind ik namelijk nogal een overkill aan validatie, maar dat kan aan mij liggen.
Zou iemand me voor kunnen doen hoe ik dit het best aanpak?
Edit:
De Common.isNodeSpecific is de volgende functie: