Clean Code, Classes

by nicola aramini

Posted on agosto 09, 2017 at 08:44 AM

Classes

Leggendo il capitolo di Clean Code che parla di classi ho imparato (o approfondito) 2 grandi principi che adesso guidano le mie scelte quando scrivo codice:

  • SRP
  • OCP.

Gli acronimi sono molto “cool” ma spesso non si capiscono quindi:

  • Single Responsibility Principle
  • Open Closed Principle.

Single Reponsibility Principle (SRP)
La tipica accezione di SRP è: “le classe (o i metodi) devono fare una e una sola cosa e farla bene”.
L’accezione che fa capire molto meglio il significato, secondo me, è la seguente: “una classe (o un metodo) deve avere un solo motivo per cambiare”.
Facciamo un esempio per capire meglio questo principio:
Ho una classe che esegue una query su DB, manipola il risultato modificando valori e committa questi cambiamenti su DB.
Il tutto non sembra così male ma proviamo ad applicare il SRP:
Cosa succede se cambia la mia base dati?
Cosa succede se cambia l’algoritmo che uso per modificare i valori presi tramite query?
Il risultato delle domande è che il SRP non è rispettato!
Queste classi vanno separate per poter rispettare il principio descritto sopra.

Perchè rispettare questo principio è così importante?

  1. è molto più semplice leggere 10 righe, che hanno uno scopo ben preciso definito dal nome della classe, rispetto al leggere 200 righe di una classe che si chiama helper (nominare classi che fanno tante cose è difficile);
  2. il codice è altamente e facilmente testabile;
  3. a fronte di una modifica nelle regole di business o di requisiti tecnici, è molto più semplice cambiare la classe per renderla conforme ai cambiamenti.

Open Closed Principle (OCP)
Questo principio recita: “le classi devono essere chiuse alle modifiche ed aperte alle estensioni”…. cosa vuol dire???
Non l’ho mai capito fino a che non ho letto “Refactoring” di Martin Fowler.
Il tipico esempio per capire questo principio è il seguente:
Per calcolare l’area di quadrato e triangono ho la seguente classe:

public class AreaCalculator
{
public double CalculateTotalArea(object[] shapeList)
{
  var totalArea = 0;
  foreach(var shape in shapeList){
    if (shape is Square)
    {
        totalArea += …calcolo dell’area del quadrato…
    }

    if (shape is Triangle)
    {
        totalArea += …calcolo dell’area del triangolo…
    }
    }

    return totalArea;
  }
}

Tutto funziona correttamente: istanzio new AreaCalculator().CalculateTotalArea(mieShapes) e questo metodo mi restituisce il valore che voglio.
Domani arriva il mio cliente e dice: “presto, dobbiamo gestire anche l’area del cerchio!”.
Io devo ricordarmi di andare in questa classe ad aggiungere l’if per gestire il cerchio, inoltre, se avessi “sparso” questa catena di if per il mio codice, dovrei ricordarmi di modificare tutti i punti dove faccio questa azione.
Il risultato è che ho dovuto modificare il codice per rispondere al nuovo requisito.

Per rispettare OCP avrei dovuto:
create una classe base “Shape” (magari abstract) che mi obbliga ad implementare il metodo “GetArea()” e far ereditare ogni mia classe da Shape.
A questo punto ogni classe deve avere la sua implementazione di GetArea().
In questo modo il metodo CalculateTotalArea() sarebbe diventato:

public double CalculateTotalArea(Shape[] shapeList)
{
  var totalArea = 0;

  foreach(var shape in shapeList){
    totalArea += shape.GetArea();
    }

    return totalArea;
  }

All’arrivo del cliente avrei dovuto preoccuparmi di AGGIUNGERE una classe derivante da Shape che deve implementare il metodo GetArea().
OCP sta tutto nella parola aggiungere: non ho dovuto modificare il codice esistente, quello funziona “by design”, avrei potuto anche non conoscere la presenza del metodo CalculateTotalArea!

Da domani provate ad applicare questi due principi (se già non lo fate) e ne vedrete i benefici a brevissimo termine!

Buon lavoro e good coding!


Notizie sull'autore

nicola aramini

Nicola Aramini Hi! I'm Nicola and I'm a .NET software developer at Elfo. I like my job and i like change to improve. In my free time, as often as I can, i go to the conferences and to the events in order to keep me posted on the new topic about software development.