Quando si leggono articoli su ISP, sembrano esserci due definizioni contraddittorie di ISP:
Secondo la prima definizione (vedi 1 , 2 , 3 ), l'ISP afferma che le classi che implementano l'interfaccia non dovrebbero essere costrette a implementare funzionalità di cui non hanno bisogno. Quindi, interfaccia fatIFat
interface IFat
{
void A();
void B();
void C();
void D();
}
class MyClass: IFat
{ ... }
dovrebbe essere suddiviso in interfacce più piccole ISmall_1eISmall_2
interface ISmall_1
{
void A();
void B();
}
interface ISmall_2
{
void C();
void D();
}
class MyClass:ISmall_2
{ ... }
poiché in questo modo my MyClassè in grado di implementare solo i metodi di cui ha bisogno ( D()e C()), senza essere costretto a fornire anche implementazioni fittizie per A(), B()e C():
Ma secondo la seconda definizione (vedi 1 , 2 , risposta di Nazar Merza ), l'ISP afferma che MyClientchiamare i metodi su MyServicenon dovrebbe essere consapevole dei metodi su MyServicecui non ha bisogno. In altre parole, se MyClientsolo ha bisogno della funzionalità di C()e D(), quindi invece di
class MyService
{
public void A();
public void B();
public void C();
public void D();
}
/*client code*/
MyService service = ...;
service.C();
service.D();
dovremmo separare i MyService'smetodi in interfacce specifiche del cliente :
public interface ISmall_1
{
void A();
void B();
}
public interface ISmall_2
{
void C();
void D();
}
class MyService:ISmall_1, ISmall_2
{ ... }
/*client code*/
ISmall_2 service = ...;
service.C();
service.D();
Pertanto, con la prima definizione, l'obiettivo dell'ISP è " semplificare la vita delle classi che implementano l'interfaccia IFat ", mentre con quest'ultima l'obiettivo dell'ISP è " semplificare la vita dei clienti che chiamano i metodi di MyService ".
Quale delle due diverse definizioni di ISP è effettivamente corretta?
@MARJAN VENEMA
1.
Quindi, quando hai intenzione di dividere IFat in un'interfaccia più piccola, quali metodi finiscono in cui ISmallinterface dovrebbe essere deciso in base alla coesione dei membri.
Mentre ha senso mettere metodi coerenti all'interno della stessa interfaccia, ho pensato che con il modello ISP le esigenze del cliente abbiano la precedenza sulla "coesione" di un'interfaccia. In altre parole, ho pensato che con l'ISP dovremmo raggruppare all'interno della stessa interfaccia quei metodi richiesti da determinati clienti, anche se ciò significa lasciare fuori da quella interfaccia quei metodi che dovrebbero, per motivi di coesione, essere inseriti all'interno di quella stessa interfaccia?
Così, se c'erano un sacco di clienti che saranno sempre e solo bisogno di chiamare CutGreens, ma non anche GrillMeat, poi per aderire al modello ISP dobbiamo solo mettere CutGreensdentro ICook, ma non anche GrillMeat, anche se i due metodi sono altamente coesivo ?!
2.
Penso che la tua confusione derivi da un presupposto nascosto nella prima definizione: che le classi attuatrici stanno già seguendo il principio della responsabilità unica.
"Implementando classi che non seguono SRP" ti riferisci a quelle classi che implementano IFato alle classi che implementano ISmall_1/ ISmall_2? Presumo che ti riferisci alle classi che implementano IFat? In tal caso, perché pensi che non seguano già SRP?
Grazie