Validatie programmatische en handmatige invoer

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo,

Stel dat je een 'autosysteem' hebt met een HTML formulier waarmee auto's (merk, naam, kleur, etc) ingevoerd en gewijzigd kunnen worden. Je maakt een CarManager object met de functies

CarManager::addCar(Car $carObject)
CarManager::updateCar(Car $carObject)

Dit CarManager object moet dienen als interface voor het beheren van auto's. Zowel het zelf gemaakte HTML formulier als code van client programmeurs moeten de CarManager gebruiken voor autobeheer.

Maar beide (HTML form en client programmeur) hebben verschillende eisen wat betreft validatie-informatie (denk ik?). Het HTML formulier heeft in geval van foute invoer behoefte aan een set (array?) met een foutmelding per veld, zodat je het formulier kunt voorzien van nette, specifieke foutinfo per veld. Een client programmeur verwacht waarschijnlijk eerder een Exception...

Hoe zouden jullie dit aanpakken? Bij een fout een Exception gooien en in de Exception een getFieldsInformation() functie aanbieden met specifieke veldinformatie wellicht?

Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 18:00
Je kunt ook 2 exception handlers maken, waarbij de één een set terug geeft van de velden en bijbehorende foutmeldingen, en een ander die gebruikt wordt tijdens de ontwikkelfase, die dus de exception zelf terug geeft.

Op zich moet dat niet zo'n probleem vormen lijkt me, het kan al worden geregeld door bijvoorbeeld in een config file een variabele (of constante is miss. beter!) te definiëren die true is als het een ontwikkelomgeving betreft en false als het een gebruiksomgeving betreft.

Vrij makkelijk om dit dan te regelen lijkt me. Het is wat meer codeerwerk, maar werkt wel.


Een andere optie is voor de ontwikkel/ testfase een andere pagina (url) met dezelfde code, maar een andere exception handler te gebruiken. Op de echte omgeving zullen ze pas werken als de fouten uit hun code zijn. Een beetje zoals Ideal het doet. Daar moet je zelfs eerst alle stappen in de testomgeving door voordat je de live omgeving in kan.

Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 15:59
Omdat je cars meestal in een refentiele database wilt opslaan:

Zorg voor not-null kolommen, foreign keys, unique constraints en eventueel check constraints. Deze geven een database fout bij het committen van je transactie die je kan throwen als exception. Je CarManager kan ook eigen verdere inhoudelijke controles doen en eventueel een exception throwen.

In de user interface laag kan je bijvoorbeeld een web framework gebruiken voor validatie en type conversie die informatie per veld kan geven. Hiermee zorg je ervoor dat not-null kolommen altijd gevuld zijn, kolommen een geldige waarde hebben en foreign keys niet verkeerd kunnen worden gevuld.

Omdat de exceptions die Car Manager throwt dan niet per veld zijn en dus minder vaak voorkomen kan je deze in je user interface laag (controller in mvc) catchen en aan de gebruiker tonen.

Met een aantal Java frameworks (Stripes, Bean Validation) is het valideren van user input trouwens niet veel meer dan een annotatie toevoegen aan een bean property:

Java:
1
2
3
4
5
6
public class Car {
  @Validate(required=true, maxlength=255)
  private String naam;
  
  ...etc
}


Een framework kan deze annotaties gebruiken om automatisch foutmeldingen aan de gebruiker bij het juiste veld te tonen - of zelfs JavaScript code genereren voor client-side èn server-side validatie.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@jbdeiman: ik ben misschien niet helemaal duidelijk geweest. Het systeem heeft een HTML interface waarin een gebruiker dingen (auto's) kan wijzigen en invoeren EN daarnaast kunnen auto's programmatisch, dus door een andere programmeur ingevoerd en gewijzigd worden via code. Het gaat niet om een tijdelijke ontwikkelfase, maar om een permanente oplossing: het systeem kan via een webinterface benaderd worden en via code. De webinterface maakt in de achtergrond ook gebruik van de CarManager.

@matthijsin: de database constraints staan sowieso al goed. Waar het vooral om gaat is dat zowel een client programmeur die de CarManager gebruikt als iemand die het HTML form gebruikt bijvoorbeeld geen speciale )#*$*)@ tekens mogen gebruiken in een autonaam. Het gaat dus om constraints op de eigenlijke invoer.

Ik gebruik overigens PHP, dus Stripes heb ik niet helaas. Ik moet het zelf knutselen.

Ik denk nu zelf richting de volgende oplossing:

Ik maak een custom PHP Exception, bijvoorbeeld CarInputException en geef die een methode 'getFieldInfo()'. Zo kan ik de foutafhandeling delegeren naar de client programmeur die via code een auto met een ongeldig veld invoert en het formulier kan bij foute invoer de getFieldInfo() methode gebruiken om nette foutmeldingen per veld op te pakken.

Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 18:00
@jtkleine
Maar voor het wijzigen/ invoeren van een auto, bijvoorbeeld, gebruik je een andere functie. Je kán ervoor kiezen eerst "checkinput" aan te roepen, maar je kan er ook voor kiezen om "edit_car/ add_car/ search_car" aan te roepen vanuit elk van de andere functies.

Stel ik voeg een auto toe: add_car, vanuit add_car controleer je met "check_input" of de input wel valide is. De functie returned alleen true of false afhankelijk van de uitkomst van deze controle. In "add_car" throw je de exception wanneer de input controle false retourneert. Op deze manier ben je heel vrij in het werken en krijgt ieder zijn eigen foutmeldingen terug. Het toevoegen en zoeken van auto's zijn van elkaar losstaande zaken (al zal je voor het toevoegen nog wel misschien willen zoeken of die niet al bestaat)

Als het goed is gebruik je dus ook verschillende functies daarvoor zodat zo'n opzet niet al te lastig is en je geen dingen dubbel hoeft te doen.
Misschien dat je dit bedoelde?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
jbdeiman schreef op zaterdag 12 december 2009 @ 08:31:
Stel ik voeg een auto toe: add_car, vanuit add_car controleer je met "check_input" of de input wel valide is. De functie returned alleen true of false afhankelijk van de uitkomst van deze controle. In "add_car" throw je de exception wanneer de input controle false retourneert. Op deze manier ben je heel vrij in het werken en krijgt ieder zijn eigen foutmeldingen terug.
Dit is de oplossing die ik nu gebruik. Het probleem of beter gezegd de 'vraag' is (was, inmiddels) wat ik precies ga returnen/gooien uit de addCar functie als er een fout ontstaat. Voor het formulier waarmee auto's toegevoegd kunnen worden had ik per veld (merk, kleur, etc) specifieke foutmeldingen nodig ('merk onbekend, kleur bevat ongeldige tekens, systeemnaam bestaat al, etc).

Ik heb het nu zo gedaan:

Als er in 1 of meer van de Car velden een fout zit gooi ik een custom CarInputException met daarin een custom functie: getFieldInfo(). Deze custom functie geeft een array met voor elk veld van de Car een FieldState object. In FieldState zit een boolean veld isValid en een message veld met de specifieke foutmelding. Ik kan nu zo een Car toevoegen:
PHP:
1
2
3
4
5
6
7
8
9
  public $fieldStates;

  function someFunction(Car $car) {
    try {
      $carManager->addCar($myCar);
    } catch(CarInputException $cip) {
      $this->fieldStates = $cip->getFieldInfo();
    }
  }


De $fieldStates variabele is een array met daarin voor elke Car property een FieldState object met foutinfo (of geen info als er geen fout in het betreffende veld zit) die weergegeven kan worden in het formulier.
Pagina: 1