contratti / asserzioni di codice: cosa con controlli duplicati?

10

Sono un grande fan della scrittura di asserzioni, contratti o qualsiasi tipo di controllo disponibile nella lingua che sto usando. Una cosa che mi disturba un po 'è che non sono sicuro di quale sia la pratica comune per gestire i controlli duplicati.

Esempio di situazione: prima scrivo la seguente funzione

void DoSomething( object obj )
{
  Contract.Requires<ArgumentNullException>( obj != null );
  //code using obj
}

poi qualche ora dopo scrivo un'altra funzione che chiama la prima. Poiché tutto è ancora fresco nella memoria, decido di non duplicare il contratto, poiché so che DoSomething wil controlla già un oggetto nullo:

void DoSomethingElse( object obj )
{
  //no Requires here: DoSomething will do that already
  DoSomething( obj );
  //code using obj
}

Il problema ovvio: DoSomethingElse ora dipende da DoSomething per verificare che obj non sia nullo. Quindi, se DoSomething decidesse mai di non controllare più, o se decido di usare un'altra funzione, obj potrebbe non essere più controllato. Il che mi porta a scrivere questa implementazione dopo tutto:

void DoSomethingElse( object obj )
{
  Contract.Requires<ArgumentNullException>( obj != null );
  DoSomething( obj );
  //code using obj
}

Sempre al sicuro, non preoccuparti, tranne che se la situazione aumenta, lo stesso oggetto potrebbe essere controllato un numero di volte ed è una forma di duplicazione e sappiamo tutti che non è così bello.

Qual è la pratica più comune per situazioni come queste?

    
posta stijn 07.11.2011 - 09:52
fonte

2 risposte

12

Personalmente verificherei il null in qualsiasi funzione che fallirà se ottiene un null e non in una funzione che non lo farà.

Quindi, nel tuo esempio precedente, se doSomethingElse () non ha bisogno di dereferenziare obj, allora non verificherei obj per null lì.

Se DoSomething () fa dereference obj allora dovrebbe controllare null.

Se entrambe le funzioni sono dereferenziali, allora dovrebbero entrambi controllare. Quindi, se DoSomethingElse dereferences obj dovrebbe controllare null, ma DoSomething dovrebbe anche controllare null perché potrebbe essere chiamato da un altro percorso.

In questo modo puoi lasciare il codice abbastanza pulito e comunque garantire che i controlli siano nella posizione corretta.

    
risposta data 07.11.2011 - 10:02
fonte
2

Grande! Vedo che hai trovato informazioni su Contratti di codice per .NET. I Contratti di codice vanno molto oltre le tue asserzioni medie, di cui il controllore statico è l'esempio migliore. Questo potrebbe non essere disponibile se non hai installato Visual Studio Premium o una versione superiore, ma è importante capire l'intenzione dietro di essa se stai per utilizzare i Contratti di codice.

Quando si applica un contratto a una funzione, è letteralmente un contratto . Questa funzione garantisce di comportarsi in base al contratto ed è garantita solo per essere utilizzata come definito dal contratto.

Nell'esempio fornito, la funzione DoSomethingElse() non è conforme al contratto come specificato da DoSomething() , in quanto è possibile passare il valore null e il controllo statico indica questo problema. Il modo per risolvere questo problema è aggiungere lo stesso contratto a DoSomethingElse() .

Ora, questo significa che ci sarà la duplicazione, ma questa duplicazione è necessaria quando scegli di esporre la funzionalità su due funzioni. Queste funzioni, anche se private, possono essere chiamate da diversi punti della classe, quindi l'unico modo per garantire che da qualsiasi chiamata l'argomento non sarà mai nullo è duplicare i contratti.

Questo dovrebbe farti riconsiderare perché hai diviso il comportamento in due funzioni in primo luogo. È sempre stata la mia opinione ( contrariamente alla credenza popolare ) che non deve dividere funzioni chiamate solo da un posto . Esponendo l'incapsulamento applicando i contratti questo diventa ancora più evidente. Sembra che abbia trovato un'argomentazione extra per la mia causa! Grazie! :)

    
risposta data 07.11.2011 - 16:31
fonte

Leggi altre domande sui tag