Podczas czytania artykułów o ISP wydaje się, że istnieją dwie sprzeczne definicje ISP:
Zgodnie z pierwszą definicją (patrz 1 , 2 , 3 ), ISP stwierdza, że klasy implementujące interfejs nie powinny być zmuszane do implementacji funkcji, których nie potrzebują. Tak więc interfejs tłuszczuIFat
interface IFat
{
void A();
void B();
void C();
void D();
}
class MyClass: IFat
{ ... }
powinny być podzielone na mniejsze interfejsy ISmall_1iISmall_2
interface ISmall_1
{
void A();
void B();
}
interface ISmall_2
{
void C();
void D();
}
class MyClass:ISmall_2
{ ... }
ponieważ w ten sposób mój MyClassjest w stanie zaimplementować tylko te metody, których potrzebuje ( D()i C()), nie będąc zmuszonym do zapewnienia również implementacji fikcyjnych A(), B()oraz C():
Ale zgodnie z drugą definicją (patrz 1 , 2 , odpowiedź Nazara Merzy ), ISP stwierdza, że MyClientwywołanie metod MyServicenie powinno być świadome metod MyService, których nie potrzebuje. Innymi słowy, jeśli MyClientpotrzebuje tylko funkcji C()i D(), a następnie zamiast
class MyService
{
public void A();
public void B();
public void C();
public void D();
}
/*client code*/
MyService service = ...;
service.C();
service.D();
powinniśmy segregować MyService'smetody na interfejsy specyficzne dla klienta :
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();
Tak więc, zgodnie z pierwszą definicją, celem ISP jest „ ułatwienie życia klasom implementującym interfejs IFat ”, podczas gdy w drugim przypadku celem ISP jest „ ułatwienie życia klientom wywołującym metody MyService ”.
Która z dwóch różnych definicji dostawcy usług internetowych jest rzeczywiście poprawna?
@MARJAN VENEMA
1.
Kiedy więc zamierzasz podzielić IFat na mniejszy interfejs, jakie metody ostatecznie decydują o wyborze ISmallinterface na podstawie spójności elementów.
Chociaż sensowne jest umieszczenie spójnych metod w tym samym interfejsie, pomyślałem, że przy wzorcu ISP potrzeby klienta mają pierwszeństwo przed „spójnością” interfejsu. Innymi słowy, pomyślałem, że z ISP powinniśmy skupić w tym samym interfejsie metody potrzebne konkretnym klientom, nawet jeśli oznacza to pominięcie tego interfejsu tych metod, które ze względu na spójność powinny być również umieszczone w tym samym interfejsie?
Tak więc, jeśli było wielu klientów, którzy będą musieli tylko zadzwonić CutGreens, ale nie również GrillMeat, to aby zastosować się do wzorca ISP, powinniśmy tylko umieścić w CutGreensśrodku ICook, ale nie również GrillMeat, mimo że te dwie metody są bardzo spójne ?!
2)
Myślę, że twoje zamieszanie wynika z ukrytego założenia z pierwszej definicji: że klasy wdrażające przestrzegają już zasady pojedynczej odpowiedzialności.
Przez „wdrażanie klas nie przestrzegających SRP” masz na myśli te klasy, które implementują IFatlub klasy, które implementują ISmall_1/ ISmall_2? Zakładam, że masz na myśli klasy, które implementują IFat? Jeśli tak, to dlaczego zakładasz, że jeszcze nie przestrzegają SRP?
dzięki