Khi đọc các bài viết về ISP, dường như có hai định nghĩa trái ngược nhau về ISP:
Theo định nghĩa đầu tiên (xem 1 , 2 , 3 ), ISP tuyên bố rằng các lớp thực hiện giao diện không nên bị buộc phải thực hiện các chức năng mà họ không cần. Do đó, giao diện chất béoIFat
interface IFat
{
void A();
void B();
void C();
void D();
}
class MyClass: IFat
{ ... }
nên được chia thành các giao diện nhỏ hơn ISmall_1
vàISmall_2
interface ISmall_1
{
void A();
void B();
}
interface ISmall_2
{
void C();
void D();
}
class MyClass:ISmall_2
{ ... }
vì theo cách này, tôi MyClass
chỉ có thể thực hiện các phương thức mà nó cần ( D()
và C()
), mà không bị buộc phải cung cấp các triển khai giả cho A()
, B()
và C()
:
Nhưng theo định nghĩa thứ hai (xem 1 , 2 , câu trả lời của Nazar Merza ), ISP tuyên bố rằng MyClient
các phương thức gọi trên MyService
không nên biết về các phương thức MyService
mà nó không cần. Nói cách khác, nếu MyClient
chỉ cần chức năng của C()
và D()
, thì thay vì
class MyService
{
public void A();
public void B();
public void C();
public void D();
}
/*client code*/
MyService service = ...;
service.C();
service.D();
chúng ta nên tách biệt MyService's
các phương thức thành các giao diện dành riêng cho khách hàng :
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();
Do đó, với định nghĩa trước đây, mục tiêu của ISP là " làm cho cuộc sống của các lớp thực hiện giao diện IFat trở nên dễ dàng hơn ", trong khi với mục tiêu sau của ISP là " làm cho cuộc sống của các phương thức gọi của MyService dễ dàng hơn ".
Điều nào trong hai định nghĩa khác nhau của ISP là thực sự chính xác?
@MARJAN VENema
1.
Vì vậy, khi bạn định chia IFat thành giao diện nhỏ hơn, phương thức nào kết thúc trong đó ISmallinterface sẽ được quyết định dựa trên mức độ gắn kết của các thành viên.
Mặc dù có ý nghĩa khi đặt các phương thức gắn kết trong cùng một giao diện, tôi nghĩ với mẫu ISP, nhu cầu của khách hàng được ưu tiên hơn "tính cố kết" của giao diện. Nói cách khác, tôi nghĩ với ISP, chúng ta nên gộp trong cùng một giao diện mà các phương thức cần thiết cho các khách hàng cụ thể, ngay cả khi điều đó có nghĩa là thoát khỏi giao diện đó, những phương thức nào, vì lợi ích của sự gắn kết, cũng được đưa vào cùng giao diện đó?
Do đó, nếu có rất nhiều khách hàng sẽ chỉ cần gọi CutGreens
, nhưng cũng không GrillMeat
, thì để tuân thủ mẫu ISP, chúng ta chỉ nên đặt CutGreens
bên trong ICook
, nhưng cũng không GrillMeat
, mặc dù hai phương thức này rất gắn kết?!
2.
Tôi nghĩ rằng sự nhầm lẫn của bạn bắt nguồn từ một giả định ẩn trong định nghĩa đầu tiên: rằng các lớp thực hiện đã tuân theo nguyên tắc trách nhiệm duy nhất.
Bằng cách "thực hiện các lớp không tuân theo SRP", bạn đang đề cập đến các lớp thực hiện IFat
hoặc các lớp thực hiện ISmall_1
/ ISmall_2
? Tôi giả sử bạn đang đề cập đến các lớp thực hiện IFat
? Nếu vậy, tại sao bạn cho rằng họ đã không theo dõi SRP?
cảm ơn