Questo principio nasce dalla necessità di evitare che una classe debba incorporare metodi non necessari al proprio funzionamento, come diretta conseguenza di un fenomeno che Robert C.Martin denomina "Inquinamento da Interfacce" (Interface Pollution).
Infatti l'enunciato dell'Interface Segregation Principle recita:
“ I Client non dovrebbero essere costretti a dipendere da interfacce che non usano. ”
Facciamo un esempio ipotizzando una classe Appunto
che viene ereditata da Post-It
, BlockNotes
, ToDo
e Schizzo
.
Ora supponiamo di voler fare in modo che gli oggetti della classe ToDo
possano essere associati ad una specifica data per la quale devono essere completati; la nostra applicazione contiene già una classe, CalendarItem
, dalla quale derivano tutti gli oggetti che al loro interno hanno logiche tipiche da calendario; sarebbe quindi logico pensare di far si che ToDo
erediti da tale classe.
Il problema, nel nostro caso, è che ToDo
già eredita da Appunto
. L'errore che spesso viene commesso per risolvere questo impasse è quello di modificare la classe Appunto
facendola derivare da CalendarItem
in modo che anche tutte le sottoclassi, tra cui ToDo
possano acquisire il comportamento voluto.
Dove risiede il problema? In primis se proviamo ad applicare la stessa soluzione per comportamenti
simili sulle altre classi figlie di Appunto ci accorgiamo che ben presto la catena di ereditarietà che
si forma tende ad assumere proporzioni disastrose. In seconda istanza classi figlie come Post-It
sono influenzate dalla presenza di un padre (CalendarItem
in questo caso) assolutamente inutile.
Ma... non si doveva parlare di interfacce?
Robert C. Martin tratta specificatamente di interfacce quando espone questo principio, in realtà il
concetto di interfaccia varia sensibilmente da linguaggio a linguaggio (e in alcuni linguaggi è
addirittura assente). Per questo l'articolo si riferisce più genericamente al concetto di ereditarietà,
senza specificare nemmeno se la classe padre sia astratta o concreta.
L'importante in questo caso è classificare il comportamento da evitare, al di là della definizione delle entità sulle quali si sviluppa.
Il termine interface pollution si applica infatti anche al caso precedente, anche se forse è più proprio
parlare di class inheritance pollution.
La soluzione
Esistono due diverse soluzioni che possiamo implementare in questo caso:
CalendarItem adapter
Una prima soluzione è creare un oggetto che funga da Adattatore nei confronti della classe CalendarItem
e fare in modo che Todo
deleghi a tale oggetto i comportamenti legati alle logiche da calendario.
Multiple inheritance
Una seconda possibilità consiste nell'utilizzo dell'ereditarietà multipla. In questo scenario la classe ToDo
ha una duplice classe padre: Appunto
e CalendarItem
. Questa strada è percorribile solo nei linguaggi che supportano questo tipo di feature per l'entità che stiamo analizzando: classi, come in questo esempio, o interfacce.