Affrontare la complessità di un sistema

_Logo Tutte le tecniche presentate nella sezione coding hanno lo scopo di affrontare la complessità di un sistema suddividendolo in elementi distinti e con un singolo scopo, seguendo il principio detto separation of concerns. Tale principio si applica ad ogni elemento del progetto o, per utilizzare la terminologia di Visual Studio, della soluzione.

Decomporre un'applicazione in parti con la minor dipendenza possibile (detta anche sovrapposizione) implica:

  • Minimizzare il coupling che indica appunto il grado di dipendenza tra oggetti. Oltre a rendere il sistema più comprensibile, si limita l’impatto delle modifiche al sistema: meno dipendenze ci sono e più si evitano effetti a catena. Anche in questo caso se vi sono troppe dipendenze è generalmente utile creare nuove classi.
  • Massimizzare la cohesion che misura quanto il contenuto di una classe è legato allo scopo della classe stessa. Anche in questo caso più coesione significa andare a modificare, in caso di manutenzione, il minor numero di oggetti.

L'obiettivo, come citato all’inizio, è quello di avere classi comprensibili, testabili, facili da estendere e mantenere. E tali qualità devono superare la prova del tempo: tutto è chiaro quando si scrive il codice ma tale chiarezza deve rimane anche in una successiva manutenzione (dopo un mese? Un anno? Anni?).

Nell'affrontare questo processo interattivo ci si può ritrovare a pensare troppo al futuro, nel senso di prevedere tutte le casistiche possibili, anche quelle non richieste. Per evitare di estremizzare troppo alcune pratiche è bene considerare l'acronimo: YAGNI (Ya Ain't Gonna Need it), che indica di concentrarsi su cosa è importante oggi e non troppo sulle dinamiche future, che hanno il brutto vizio di cambiare e quindi affrontarle oggi non ha senso (o per lo meno non ha senso implementare soluzioni a loro dedicate).

Applicando il già citato principio di separazione delle competenze ai progetti che costituiscono la nostra applicazione, ci ritroveremo ad avere progetti suddivisi per competenza, generalmente adottando una struttura suddivisa in layer. Interessante a questo proposito alcune vecchie guide disponibili in MSDN. Naturalmente l’applicabilità e l’effettiva implementazione dipendono dal proprio progetto, ma molti degli aspetti trattati sono comunque significativi.

Ad esempio, tutto ciò che riguarda l'interfaccia utente fa parte del Presentation Layer, l'accesso ai dati del Data Layer, i processi e le entità business del Business Layer e così via. Ogni layer può essere composto da più progetti e i più comuni sono:

  • User interface (UI).
  • Business Logic (BL).
  • Data Access (DA).
  • Common

Come detto potremmo avere più progetti UI, BL, DA e Common: l’importante è che ognuno sia specializzato in un determinato scopo. Potremmo ad esempio avere più progetti UI (Windows, WinPhone, Web..) , potremmo decidere di suddividere il modello delle entità dalla business logica e avere quindi due progetti separati.

Il progetto Common è dedicato a tutte quelle classi che possono essere utili in tutta la soluzione o in più soluzioni. Riutilizzo è un’altra parola chiave della programmazione ad oggetti. Riutilizzare codice non significa solo creare librerie di classi utilizzabili in diversi progetti, ma anche specializzare classi esistenti tramite la derivazione. Da non dimenticare inoltre l’utilizzo di quello che esiste già: il .NET e le migliaia di librerie gratuite e non disponibili offrono molto.

Considerazioni

Naturalmente è consigliabile definire i layer in base alle necessità: non vale nemmeno iniziare con una struttura predefinita. Durante il design o la prototipazione i diversi livelli saranno identificati facilmente.

Strutturare la propria applicazione dipende da tanti fattori, tra cui la sua dimensione o complessità che dir si voglia, dalla sua aspettativa di vita, dalle risorse che utilizza e quindi dalle dipendenze che ha… Sempre bisogna considerare che i benefici di un’applicazione strutturata si hanno soprattutto in fase di manutenzione, quindi per applicazioni da mantenere nel tempo e che devono garantire il loro funzionamento anche dopo eventuali aggiornamenti. Strutturare l’applicazione vuol dire poter intervenire sui moduli effettivamente coinvolti in una modifica, significa poter dedicare un team per un certo modulo, significa poter semplificare il test dei sinoli layer in modo indipendente dagli altri.

L’aspetto più importante da tenere in mente è comunque la separazione delle competenze e l’utilizzo di principi che facilitano la creazione di sistemi complessi, come i principi SOLID. Tali concetti portano necessariamente a strutturate l’applicazione in diversi moduli o strati e quelli che ho citato sono abbastanza classici.

Lo scopo è evitare ridondanza, limitare le dipendenze e facilitare la comprensione per garantire la testabilità, la estendibilità e la manutenibilità del software.

Tag: OOP, layer