AntonioGanci

Il blog di Antonio Ganci
posts - 201, comments - 420, trackbacks - 31

mercoledì 7 dicembre 2011

Ridurre la complessità del sistema implementando un interfaccia in modo esplicito

Un collega mi ha suggerito una tecnica interessante quando si è in presenza di codice legacy.

Nella nostra codebase abbiamo creato l'astrazione ICommitCommand per modificare i dati delle risorse esterne nei setup dei un test di accettazione in cui utilizziamo i sistemi reali e non dei fake. Nel caso specifico la scrittura su un indice di Lucene e la modifica di alcuni dati nel db.

interface ICommitCommand
{
  void Execute();
}

 

Inizialmente avevo creato l'oggetto:

class LuceneCommand : ICommitCommand
{
  LuceneClient _client;

  public LuceneCommand(LuceneClient client) 
  {
    _client = client;
  }

  public void Execute()
  {
    _client.Update();
  }
}

 

LuceneCommand è un adapter per l'interfaccia ICommitCommand. Il problema dell'oggetto è che soffre dello smell Lazy Class (cioè una classe che fa troppo poco). Un modo per risolverlo è quello di fare implementare l'interfaccia direttamente a LuceneClient.

Purtroppo il metodo Execute non ha molto significato per LuceneClient. La soluzione che abbiamo adottato è quella di farlo implementare in modo esplicito:

class LuceneClient : ICommitCommand
{
  ...
  void ICommitCommand.Execute()
  {
    _client.Update();
  }
  ...
}

 

In questo modo se utilizzo direttamente LuceneClient non posso chiamare il metodo Execute, mentre se ne ho un riferimento come ICommitCommand posso chiamare il metodo.

Questa tecnica viene sfruttata anche nel .net framework per l'oggetto Dictionary che implementa il metodo Add(KeyValuePair) privatamente:

var dictionary = new Dictionary<int, string>();
dictionary.Add(new KeyValuePair<int, string>()); // Error
var d = (IDictionary<int, string>) dictionary;
d.Add(new KeyValuePair<int, string>()); // ok

 

Il vantaggio di questa soluzione è che riduce la complessità del sistema, evitando il proliferare di adapter che non fanno altro che permettere ad una classe di implementare l'interfaccia desiderata.

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (2) | Filed Under [ Tips ]

Powered by:
Powered By Subtext Powered By ASP.NET