Come implementare isValid correttamente?

5

Sto provando a fornire un meccanismo per convalidare il mio oggetto in questo modo:

class SomeObject {
    private $_inputString;
    private $_errors=array();

    public function __construct($inputString) {
        $this->_inputString = $inputString;      
    }

    public function getErrors() {
        return $this->_errors;
    }

    public function isValid() {
        $isValid = preg_match("/Some regular expression here/", $this->_inputString);
        if($isValid==0){
            $this->_errors[]=  'Error was found in the input';
        }
        return $isValid==1;
    }

}

Quindi quando sto testando il mio codice lo faccio in questo modo:

    $obj = new SomeObject('an INVALID input string');

    $isValid = $obj->isValid();
    $errors=$obj->getErrors();

    $this->assertFalse($isValid);
    $this->assertNotEmpty($errors);

Ora il test passa correttamente, ma ho notato un problema di progettazione qui. Cosa succede se l'utente ha chiamato $obj->getErrors() prima di chiamare $obj->isValid() ?

Il test fallirà perché l'utente deve prima convalidare l'oggetto prima di verificare l'errore risultante dalla convalida. Penso che in questo modo l'utente dipenda da una sequenza di azioni per funzionare correttamente, il che penso sia una cosa negativa perché espone il comportamento interno della classe.

Come posso risolvere questo problema?
Devo dire esplicitamente all'utente di convalidare prima? Dove lo dico?
Devo cambiare il modo in cui convalidare? C'è una soluzione migliore per questo?

UPDATE:
Sto ancora sviluppando la classe, quindi i cambiamenti sono facili e le funzioni di ridenominazione e il refactoring sono possibili.

    
posta Songo 11.10.2012 - 21:59
fonte

4 risposte

2

Ci sono due modi per aggirare questo problema:

  1. Per impostare $_errors su un errore che indica che la convalida non è ancora avvenuta, o
  2. Per andare "completamente senza stato": make isValid restituisce l'array di errori e controlla la dimensione dell'array per determinare se la validazione è riuscita o meno

Il primo percorso è più semplice per un sistema esistente: rendere questo cambiamento è molto più economico, ma l'interazione con il tuo oggetto rimane statica, nel senso che si basa sull'ordine delle chiamate.

Il secondo percorso potrebbe essere più difficile da integrare, ma se applicato in modo coerente, rende la tua API più facile da imparare. Lingue diverse offrono diversi modi per rispondere alla necessità di restituire più elementi da una chiamata. Nelle lingue che consentono il passaggio per riferimento o per puntatore, la funzione di convalida spesso restituisce un valore booleano e un segnaposto per errori viene passato per riferimento sul lato.

    
risposta data 11.10.2012 - 22:14
fonte
5

Perché dovresti permettere a un consumatore della tua classe di creare un oggetto in uno stato non valido? Disegnerei la classe in modo tale che se viene mai richiesto di immettere uno stato non valido (sia con parametri di costruzione errati, sia chiedendo una mutazione non valida) genera un'eccezione e non modifica lo stato.

    
risposta data 11.10.2012 - 23:29
fonte
0

Rendi isValid uguale a qualcosa di default che viene modificato solo quando è selezionato ... Quando chiama getErrors controlla quel valore predefinito e restituisce un'eccezione se è lì ... In questo modo, getErrors non funzionerà a meno che non sia stato eseguito prima isValid .

    
risposta data 11.10.2012 - 22:13
fonte
0

Crea $isValid una variabile di istanza.

Esegui il controllo degli errori nel costruttore, incluso il popolamento dell'array.

Quindi la funzione isValid() restituisce solo $isValid .

Eseguendo il controllo degli errori nel costruttore, disaccoppia tempo getErrors() da isValid()

    
risposta data 12.10.2012 - 02:12
fonte

Leggi altre domande sui tag