web log di marco mangia

staccato dalla tastiera, dal codice mi aspetto solo che esso non mi perseguiti più
posts - 6, comments - 4893, trackbacks - 10

mercoledì 9 settembre 2009

IoC: maccheroni per programmatori procedurali

In questo primo articolo darò un'introduzione "infantile" al concetto di Inversion of Control(IoC) ed ad una sua implementazione tramite il pattern di Dependency Injection(DI). Sebbene IoC e DI siano considerati sinonimi, mi è sembrato di capire che DI sia una implementazione particolare di IoC, a mano o tramite framework. Comuque, qui non farò riferimento a framework particolari, ma solo al principio di base che dovrebbe condurci a scrivere codice a basso accoppiamento (low coupling).

Per una mia innata prigrizia, mi piace di più usare le immagini per fissare i concetti. Non sto qui ad elencare i motivi biologici.

Dependendency Inversion Principle
Già, chi collegherebbe una lampada saldandola ai cavi elettrici nella parete ? A patto che abbia voglia di vincere il premio Darwin di quest'anno. Il problema è che non sono sicuro del risultato finale ...

DIP in pratica ci spinge a utilizzare e dipendere da interfacce (o astrazioni). Quasi non c'è più niente da dire, vista la banalità della cosa. Pigro sì, ma pragmatico:
  • Nessuna classe dovrebbe derivare da un tipo concreto
  • Nessuna variabile dovrebbe avere un riferimento ad un tipo concreto
  • Nessun metodo dovrebbe fare l'override di un metodo implementato in qualcuna delle sue classi base

Altre due imaginette ci aiutano a capire ancora meglio:


Nella prima una classe consumer ha delle dipendenze con le classi concrete, ovvero ha il comp ci creare uno dei tre tipi facendo ricorso all'operatore new


E' il caso appunto in ciui componenti  ad alto livello dipendono da componenti a basso livello


Il verso della dipendenza imita molto quello della tipica programmazione procederale



public class Dependent
{
public IDependent _dependent;
public void DoSomething(string dependent)
{
if (dependent.EndsWith("1"))
_dependent = new DependentClass1();
if (dependent.EndsWith("2"))
_dependent = new DependentClass2();
if (dependent.EndsWith("3"))
_dependent = new DependentClass3();
_dependent.DoSomethingInDependent();
}
}

La seconda invece ci mostra gli effetti della cura dopo aver implementato DIP:


L'iniettore della dipendenza stesso dipende da una astrazione (classe abstract o tipo interface). Ovvero possiede un riferimento all'interfaccia tramite un campo privato





Così i tipi concreti che derivano dall'interfaccia, implementandola


Il verso della dipendenza si è invertita, da questo il nome di Inversione di Controllo (mesi fà mi dicevo: inversione de che ??)

    public class Injector
{
private IDependent _dependent;
public IDependent Dependent
{
get { return _dependent; }
set { _dependent = value; }
}
public void DoSomething()
{
Dependent.DoSomethingInDependent();
}
}

Persino il class diagram, uhh:
Martin Fowler in suo famosissimo articolo ci insegna 3 tipi di DI:
  • Iniezione tramite metodi d'interfaccia di Tipo 1
  • Iniezione tramite proprietà di Tipo 2
  • Iniezione tramite costruttore di Tipo 3
La prima è quella che obbliga a definire un'interfaccia (da non confondersi con l'astrazione necessaria al DIP) , dalla quale poi l'iniettore dovrà derivare, constringendolo ad implementare i metodi
La seconda invece è la proprietà che si preoccupa di valorizzare il campo privato che rappresenta la dipendenza verso l'interfaccia
La terza invece è quella in cui, il riferimento viene risolto nel momento in cui l'iniettore viene creato, dovendolo passare come parametro.

Forse Martin si era sparato tutti i cofanetti di Spielberg prima di scrivere l'articolo, diciamo che non farei una distinzione così ferrea tra tipi, basta capire quando ci servono.
Delle tre, la prima non l'ho mai usata nè vista usare. Dopo tutto devo scrivere del codice in più. Preferisco la seconda e la terza modalità o un misto delle due, poichè mi risulta comodo per lo "state based unit-testing", cioè posso governare e controllare come viene risolta la dipendenza. Userei solo la seconda o al massimo la prima solo quando ho bisogno di posticipare l'iniezione.
 
Dimenticavo, appena posso mi comprerò questa simpatica magliettina che fa parte della campagna anti-if promossa da xplabs.

E' proprio IoC, uno dei mezzi che ci aiutano in questa battaglia. Non per if stesso ma per un suo abuso, chiaro.




NB: ho fatto anche un versione video, o screencast, di questo articolo. Devo un attimo sistemare il "montaggio". Ho Sergio Leone in chat che mi sta dando dei validi consigli. Lo pubblico più tardi o al max domani mattina.

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (1208) | Filed Under [ Design Patterns ]

Powered by:
Powered By Subtext Powered By ASP.NET