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_1
iISmall_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 MyClass
jest 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 MyClient
wywołanie metod MyService
nie powinno być świadome metod MyService
, których nie potrzebuje. Innymi słowy, jeśli MyClient
potrzebuje 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's
metody 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ą IFat
lub 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