Beim Lesen von Artikeln über ISP scheint es zwei widersprüchliche Definitionen von ISP zu geben:
Nach der ersten Definition (siehe 1 , 2 , 3 ) sollten ISP-Klassen, die die Schnittstelle implementieren, nicht gezwungen werden, Funktionen zu implementieren, die sie nicht benötigen. Also fette SchnittstelleIFat
interface IFat
{
void A();
void B();
void C();
void D();
}
class MyClass: IFat
{ ... }
sollte in kleinere Schnittstellen ISmall_1
und aufgeteilt werdenISmall_2
interface ISmall_1
{
void A();
void B();
}
interface ISmall_2
{
void C();
void D();
}
class MyClass:ISmall_2
{ ... }
da auf diese Weise meiner MyClass
Lage ist, nur die Methoden zu implementieren , es braucht ( D()
und C()
), ohne auch Dummy - Implementierungen für bietet gezwungen werden A()
, B()
und C()
:
Gemäß der zweiten Definition (siehe 1 , 2 , Antwort von Nazar Merza ) gibt der ISP an, dass beim MyClient
Aufrufen MyService
von Methoden MyService
nicht berücksichtigt werden sollte, welche Methoden er nicht benötigt. Mit anderen Worten, wenn MyClient
nur die Funktionalität von C()
und benötigt wird D()
, dann statt
class MyService
{
public void A();
public void B();
public void C();
public void D();
}
/*client code*/
MyService service = ...;
service.C();
service.D();
Wir sollten MyService's
Methoden in kundenspezifische Schnittstellen unterteilen:
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();
Daher besteht das Ziel von ISP in der ersteren Definition darin, " das Leben von Klassen, die die IFat-Schnittstelle implementieren, zu vereinfachen ", während das Ziel von ISP darin besteht, " das Leben von Clients, die Methoden von MyService aufrufen, zu vereinfachen ".
Welche der beiden unterschiedlichen Definitionen von ISP ist tatsächlich korrekt?
@MARJAN VENEMA
1.
Wenn Sie also IFat in eine kleinere Schnittstelle aufteilen, sollten Sie anhand der Kohäsion der Mitglieder entscheiden, welche Methoden in welcher ISmall-Schnittstelle landen.
Während es sinnvoll ist, zusammenhängende Methoden innerhalb derselben Schnittstelle zu platzieren, dachte ich, dass bei einem ISP-Muster die Bedürfnisse des Kunden Vorrang vor der "Kohäsivität" einer Schnittstelle haben. Mit anderen Worten, ich dachte, mit dem ISP sollten wir die Methoden, die von bestimmten Clients benötigt werden, innerhalb derselben Schnittstelle zusammenfassen, auch wenn dies bedeutet, dass diese Methoden aus Gründen der Kohäsivität auch innerhalb derselben Schnittstelle weggelassen werden sollten.
Wenn es also viele Kunden waren , die sich immer nur auf Anruf benötigt wird CutGreens
, aber auch nicht GrillMeat
, dann ISP Muster haften sollten wir nur setzen CutGreens
innen ICook
, aber auch nicht GrillMeat
, auch wenn die beiden Methoden sind hochkohäsiv ?!
2.
Ich denke, Ihre Verwirrung rührt von der versteckten Annahme in der ersten Definition her: Die implementierenden Klassen folgen bereits dem Prinzip der einheitlichen Verantwortung.
Beziehen Sie sich mit "Implementieren von Klassen, die SRP nicht folgen" auf Klassen, die implementieren, IFat
oder auf Klassen, die ISmall_1
/ implementieren ISmall_2
? Ich nehme an, Sie beziehen sich auf Klassen, die implementieren IFat
? Wenn ja, warum nehmen Sie an, dass sie SRP nicht bereits folgen?
Vielen Dank