Uno dei miliardi di concetti che Code Complete 2 mi sta lasciando in testa riguarda i metodi che implementiamo nel nostro codice. Sembra una sciocchezza, però una dichiarazione di metodo fatta in questo modo...
public DomainModelObject GetAvaiableStream()
{
bool isValid;
DomainModelObject ret;
// Codice che fa chissà cosa
if(isValid)
return(ret);
else
return(null);
}
Questo metodo, puramente casuale e senza alcuna utilità, ci ritorna un'istanza della classe DomainModelObject creata in chissà quale modo. Questo metodo, un po' come succede per l'interfaccia esposta dalle classi, crea un contratto. Garantisce che la sua chiamata ritorna un oggetto di questo tipo. La firma di un metodo ci dice una cosa del tipo: io ti assicuro che se mi chiami e mi passi gli oggetti che necessito per fare la mia elaborazione, io ti garantisco la restituzione di un oggetto di un certo tipo. In questo caso, di oggetti passati in input non ce ne sono, mentre l'oggetto ritornato è appunto un DomainModelObject.
Nel codice qui sopra c'è volutamente un errore. Non di compilazione, sia chiaro, ma un errore logico, che rompe il contratto e rende un po' più inconsistente il codice. Vediamo perchè.
Il codice dovrebbe creare un'istanza di DomainModelObject.
Se ci riesce, isValid è true, e l'oggetto viene effettivamente ritornato al chiamante.
Se non ci riesce, isValid è false, e viene ritornato null.
Quest'ultimo caso manda in fumo il design del metodo e della classe. Ritornare null significa che il chiamante deve prendersi cura di controllare questa cosa, per non scatenare un bel NullReferenceException. E' molto meglio rispettare questo contratto, evitando di riempire il nostro codice di if o di Exception. Se il test lo facciamo nel metodo - ed in effetti c'è già - possiamo isolare il problema e ritornare una sorta di InvalidDomainModelObject - istanza reale di una classe concreta derivata di DomainModelObject - che è ovviamente != null.
La classe InvalidDomainModelObject è a tutti gli effetti un DomainModelObject, quindi, ma permette di mantenere valido il contratto del metodo. In questa classe dovremmo fare l'overloading dei metodi, per renderli inoffensivi.
Per maggiori informazioni, chiedete a Martin Fowler e al suo pattern Special Case!