Validatie, tot hoe ver ga je?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ventilatiesysteem Productontwikkelaar HBO WO Verwa

Samengevat: Zij bieden flexibele ventilatiematerialen, geluidsdempers, rookgasafvoer producten en industrieslangen. Ben jij een technisch productontwikkelaar? Heb jij ervaring met het ontwikkelen van nieuwe producten? Vaste baan: Technisch Productontwikkelaar HBO WO €3.000 - €4.000 Zij bieden een variëteit aan flexibele ventilatiematerialen, geluiddempers, rookgasafvoer producten, industrieslangen en ventilatieslangen voor de scheepsbouw. Met slimme en innovatieve materialen zorgen wij voor een gezonde en frisse leefomgeving. Deze werkgever is een organisatie die volop in ontwikkeling is met hardwerkende collega's. Dit geeft goede ontwikkelingsmogelijkheden. De branche van dit bedrijf is Techniek en Engineering. Functie: Voor de vacature als Technisch Productontwikkelaar Ede Gld HBO WO ga

Bekijk vacature »

Lord Gaga

Lord Gaga

19/06/2014 09:58:57
Quote Anchor link
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.
Gewijzigd op 19/06/2014 10:00:28 door Lord Gaga
 
PHP hulp

PHP hulp

30/11/2024 11:54:20
 
Koen Hollander

Koen Hollander

19/06/2014 09:59:57
Quote Anchor link
Als ik dingen valideer, dan valideer ik alle eisen.

Ik kijk ook vaak de strlen na.

Het liefst 2 keer. Ook al is dat overbodig.
Gewijzigd op 19/06/2014 10:01:12 door Koen Hollander
 
Lord Gaga

Lord Gaga

19/06/2014 10:03:19
Quote Anchor link
Oke, dus stel dat ik als parameter een canvas element verwacht, dan moet ik dus checken of:
- De parameter NIET null is (Want null is ook een object en null.nodeType geeft een error)
- De parameter een object is (Want node is een object)
- Het object een nodeType heeft (Als het object een nodeType heeft, is dit een node)
- Het object de nodeName 'CANVAS' heeft (Het is dus een canvas element)
 
- Ariën  -
Beheerder

- Ariën -

19/06/2014 12:52:36
Quote Anchor link
Koen Hollander op 19/06/2014 09:59:57:
Het liefst 2 keer. Ook al is dat overbodig.

Hoe, en op welke manier?
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 13:02:11
Quote Anchor link
Bij multi-byte karaktersets kan de stringlengte wel eens anders uitvallen dan je verwacht. Vandaar dat sommigen strlen() bijvoorbeeld door een mb_strlen() of strlen_utf8() vervangen.
 
Ozzie PHP

Ozzie PHP

19/06/2014 13:06:43
Quote Anchor link
Koen Hollander op 19/06/2014 09:59:57:
Het liefst 2 keer. Ook al is dat overbodig.

Dat lijkt me niet zinvol. Je zegt zelf al dat het overbodig is, dus dan heeft het geen enkele toegevoegde waarde.

Mijns insziens moet je vooral controleren wat "van buitenaf" komt en wat je als programmeur dus niet zelf in de hand hebt.

Op het moment dat een ID een class binnenkomt, dan moet die ID al kloppen. Het moet niet zo zijn dat de class die ID nog eens moet gaan controleren.

Jij als programmeur weet wat voor ID er verwacht wordt, dus op het moment dat je die zelf intypt, weet je dat het klopt: $foo = new Foo(12);

Echter, op het moment dat een bezoeker een ID opvraagt, zou je deze wel kunnen controleren. Als jij weet dat het ID een getal moet zijn, kun je controleren of het inderdaad een getal is.

Als je alles zou controleren, dan zou je alles wat je zelf doet ook moeten gaan controleren, en dat wordt een beetje belachelijk.

Stel dat ik in mijn code zet:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
$admin
= new Admin();
$admin->setName('Ozzie PHP');

en dan vervolgens...

$validator = new AdminValidator();
$validator=>validate($admin); // dus nu ga ik controleren wat ik zelf heb ingetypt
?>

Dit lijkt me nogal overkill. Nee, vooral dus de dingen controleren die van buitenaf komen.
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 13:22:42
Quote Anchor link
Ozzie PHP op 19/06/2014 13:06:43:
Op het moment dat een ID een class binnenkomt, dan moet die ID al kloppen. Het moet niet zo zijn dat de class die ID nog eens moet gaan controleren.

Jij als programmeur weet wat voor ID er verwacht wordt, dus op het moment dat je die zelf intypt, weet je dat het klopt: $foo = new Foo(12);

Dan moet je toch nog ergens formaliseren wat een geldige ID is. De class Product weet zelf niet dat de ID bijvoorbeeld slechts een UNSIGNED SMALLINT is in de database en dus niet groter dan 65535 mag zien. Dat weet een class ProductMapper misschien wel, maar je wilt voor validaties niet afhankelijk zijn van exceptions van een mapper.

Omgekeerd kan de product-ID misschien een UNSIGNED BIGINT zijn. Dan heeft een class ProductMapper daar geen enkele moeite mee, maar loop je misschien ergens vast omdat PHP 18446744073709551615 niet als integer kan behappen.

Kortom: een apart data-object voor de product-ID zou dan niet verkeerd zijn.
 
Ozzie PHP

Ozzie PHP

19/06/2014 13:30:59
Quote Anchor link
>> Dan moet je toch nog ergens formaliseren wat een geldige ID is. De class Product weet zelf niet dat de ID bijvoorbeeld slechts een UNSIGNED SMALLINT is in de database en dus niet groter dan 65535 mag zien.

Lijkt mij dat je dan enkel wanneer het gaat om user input vanuit een formulier of URL een validatie gaat toepassen. Het lijkt me niet de bedoeling dat je jezelf gaat controleren. Als ik als programmeur in mijn code ergens typ $id = 12, dan kun je er vanuitgaan dat dat klopt, en dat je niet hoeft te controleren of 12 inderdaad een getal is groter dan 0 en kleiner dan x. Dat is aan de programmeur.
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 13:36:42
Quote Anchor link
>> Jij als programmeur weet wat voor ID er verwacht wordt [...]

Dan zit het alleen in jouw hoofd en is het nergens in de software terug te vinden. Wat je niet formaliseert door het in te bouwen, wordt niet gebruikt.

>> Als ik als programmeur in mijn code ergens typ $id = 12 [...]

Dat lijkt me een hoogst zeldzame uitzondering, want wanneer ga je nu een applicatie bouwen waar je zó specifiek een "hard coded" integer instelt? Dat zou dan op zijn minst een constante moeten zijn.
 
Ozzie PHP

Ozzie PHP

19/06/2014 13:40:24
Quote Anchor link
Het is maar een voorbeeld Ward. Wat ik bedoel te zeggen is dat je dingen van buitenaf moet controleren, maar als ik zelf hardcoded typ:

$site_admin->setName('Ward van der Put')

Dan ga ik niet controleren of die naam wel klopt.
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 14:17:17
Quote Anchor link
Ja, die uitzondering is dan wel verdedigbaar, maar dat is intern. Het gaat hier om de ruimere vraag: wanneer en hoe valideer je, zowel intern als extern?

Als je een schaalbaar systeem bouwt met een groeiende en veranderende database, dan zul je toch ergens moeten vastleggen wat een valide product-ID is. En dat wil je maar op één plaats doen, niet alleen omdat je het maar één keer wilt vastleggen, maar vooral omdat alle samenwerkende klassen dan exact dezelfde "definitie" van een product-ID hanteren.

Dat zou ik niet beperken tot validaties van externe input. Het systeem heeft meer "check & balances" nodig — ook intern.
Gewijzigd op 19/06/2014 14:17:45 door Ward van der Put
 
Ozzie PHP

Ozzie PHP

19/06/2014 14:22:39
Quote Anchor link
Maar met een ID is het lastig vind ik. ALs een ID niet klopt wordt ie simpelweg niet gevonden.

Maar dan zou je een aparte class moeten maken die valideert of het id klopt:

ProductID::validate($id)

zoiets dan?
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 15:30:50
Quote Anchor link
Dan moet je expliciet een validator aanroepen en dat vereist altijd een actieve ingreep (die je kunt vergeten). Het kan beter impliciet en passief:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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.
Gewijzigd op 19/06/2014 15:32:13 door Ward van der Put
 
Ozzie PHP

Ozzie PHP

19/06/2014 15:43:35
Quote Anchor link
Ward, ik begrijp het nog niet helemaal.

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".
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 15:59:38
Quote Anchor link
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:

$id = new ProductIdentifier(12);
Gewijzigd op 19/06/2014 16:00:45 door Ward van der Put
 
Ozzie PHP

Ozzie PHP

19/06/2014 16:42:31
Quote Anchor link
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...

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$admin
= new Admin();
$admin->setName('Ward');
?>

Zou volgens jouw beredenering dus dit worden?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
$admin
= new Admin();
$name  = new Name('Ward');
$admin->setName($name);
?>

Correct? En idem voor e-mailadres, leeftijd enz. ?
 
Ward van der Put
Moderator

Ward van der Put

19/06/2014 16:58:53
Quote Anchor link
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".
 
Lord Gaga

Lord Gaga

19/06/2014 17:19:00
Quote Anchor link
Ik snap nog steeds niet waar en wanneer ik nou precies moet gaan valideren.
Op dit moment heb ik het volgende:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
Common.isNode = function isNode(input)
{
    return !Common.isNull(input) && Common.isObject(input) && !!input.nodeType;
};

Common.isNodeSpecific = function isNodeSpecific(input, nodeName)
{
    return Common.isNode(input) && input.nodeName.toLowerCase() === nodeName;
};
Gewijzigd op 19/06/2014 17:23:13 door Lord Gaga
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.