Interface Segregation Principle
Nhiều mẫu thiết kế mà chúng ta đã phám phá sử dụng khái quát hóa lớp cụ thể, các khái quát này được trình bày dưới dạng interface cho phép các lớp client sử dụng để gián tiếp gọi các hành vi của các lớp cụ thể. Các mẫu thiết kế làm điều này để các lớp client trở nên ít phụ thuộc hơn vào các lớp cụ thể, cho phép thay đổi được thực hiện dễ dàng hơn. Các giao diện đóng vai trò quan trọng trong lập trình hướng đối tượng, đến mức bạn nên cố gắng lập trình giao diện thay vì các lớp cụ thể. Tuy nhiên, có một vấn đề có thể phát sinh nếu một interface chứa quá nhiều. Bạn có thể nghĩ về bất cứ những vấn đề mà điều này có thể gây ra ?
Hãy xem xét ví dụ này. Hãy tưởng tượng việc tạo ra một hệ thống đại diện cho khu vực thanh toán tại một cửa hàng tạp hóa. Ở các nước Bắc Mỹ, có hai cách khách hàng có thể trả tiền cho mặt hàng của họ. Sử dụng nhân viên thu ngân hoặc máy bán hàng tự động, mục đích đó có thể khái quát hóa thành một giao diện. Cả hai đều quét các mặt hàng mà khách hàng muốn mua, chấp nhận một số hình thức thanh toán và thay đổi phân phối khi cần, nhưng có một số hành vi không được chia sẻ giữa hai cách này. Trong khi máy phục vụ tự động có thể thực hiện công việc vô thời hạn, một nhân viên thu ngân cần ăn, nghỉ giải lao và rời đi khi hết ca.
Bây giờ, bạn có thể chỉ cần đặt hành vi của con người vào một lớp thu ngân cụ thể, nhưng có một vấn đề với quyết định thiết kế này. Một lớp khách hàng sẽ không thể sử dụng sự gián tiếp để gọi những hành vi này của con người, vì chúng không có trong giao diện. Nhưng nếu lớp khách hàng của bạn gọi phương thức trực tiêp trên một nhân viên thu ngân, nó sẽ trở nên phụ thuộc vào lớp cụ thể đó. Vì vậy, sau khi bạn buộc phải thêm những hành vi của con người vào giao diện, hay bạn chỉ chấp nhận rằng bây giờ hệ thống của bạn phụ thuộc ở mức độ thấp và sẽ chỉ làm thêm khi bạn cần thay đổi nữa ? May mắn thay, bạn có thể sử dụng Interface Segregation Principle để giải quyết vấn đề này, bạn không phải gặp các vấn đề phụ thuộc buộc bạn phải khái quát hóa mọi thứ vào interface.
Nguyên tắc này nói rằng một lớp không nên bị phụ thuộc vào các phương thức mà nó không sử dụng, điều này có nghĩa là bất kỳ lớp nào implement giao diện không nên có các triển khai giả của bất kỳ phương thức nào được định nghĩa trong giao diện. Thay vào đó, bạn nên chia các giao diện lớn thành các khái quát nhỏ hơn, vậy làm thế nào để thực hiện điều này ?
Giao diện ICashier không hoạt động lớp thu ngân của con người vì tất cả các hành vi của nó được giao diện nắm bắt. Nhưng bạn có thể thấy, thiết kế này không lý tưởng, bởi vì máy tự phục vụ chứ không cần đồng hồ vào ra, nghỉ ngơi như con người. Bạn không muốn bị buộc phải cung cấp các phương thức triển khai ngu ngốc không làm gì cả, vì vậy, chúng ta nên chia ICashier thành hai phần nhỏ hơn, điều này sẽ cho phép mỗi Interface chính xác hơn với mô tả các hành vi dự kiến của nó và sẽ cho phép bạn chọn kết hợp chính xác các giao diện mà một số lớp cụ thể sẽ thực hiện.
Trong thiết kế này, giao diện ICashier cũ được chia thành ICashier mới và IHumanWorker. Giao diện ICashier mô tả hành vi chung của nhân viên, giao diện IHumanWorker mô tả hành vi chung của nhân viên, lớp HumanCashier có thể implement cả hai giao diện ICashier, IHumanWorker. Và lớp SelfServeMachine chỉ implement ICashier. Bằng cách này, cá hai lớp cụ thể của bạn sẽ chỉ cần cung cấp các triển khai cho các giao diện khái quát hóa chức năng cụ thể của chúng.
Các giao diện là một phần không thể thiếu của hệ thống hướng đối tượng, chúng giúp bạn giảm khớp nối bằng cách khái quát hóa các lớp cụ thể, nhưng cũng giống như với tất cả các nguyên tắc hướng đối tượng, bạn nên cố gắng sử dụng chúng đúng cách. Mặc dù các interface lớn không phải là một lựa chọn thiết kế kém, bạn cần kiểm tra chúng trong bối cảnh hệ thống của bạn để quyết định xem bạn có cần chia nó thành các khái quát nhỏ hơn bằng cách sử dụng nguyên tắc thiết kế này.
Interface Segregation Principle nói rằng một lớp không nên bị buộc phải phụ thuộc vào các phương thức mà nó không sử dụng và các giao diện nên được phân tách theo cách mà nó có thể mô tả chính xác chức năng riêng biệt của hệ thống của bạn.
Đôi khi không rõ cách phân tách giao diện của bạn một cách chính xác hoặc dự đoán các thay đổi trong tương lai trong các yêu cầu sẽ cần phân tách giao diện. Có một hệ thống giao diện đã được xác định rõ sẽ giúp bạn thấy các điểm phân biệt này tốt hơn. Bạn luôn luôn cố gắng thiết kế chính xác nhất giao diện, hãy nhớ chúng là những mô tả về những phần nào trong hệ thống của bạn có thể làm và mô tả càng tốt thì việc tạo, cập nhật, và bảo trì phẩn mềm của bạn càng dễ dàng hơn.
Hãy xem xét ví dụ này. Hãy tưởng tượng việc tạo ra một hệ thống đại diện cho khu vực thanh toán tại một cửa hàng tạp hóa. Ở các nước Bắc Mỹ, có hai cách khách hàng có thể trả tiền cho mặt hàng của họ. Sử dụng nhân viên thu ngân hoặc máy bán hàng tự động, mục đích đó có thể khái quát hóa thành một giao diện. Cả hai đều quét các mặt hàng mà khách hàng muốn mua, chấp nhận một số hình thức thanh toán và thay đổi phân phối khi cần, nhưng có một số hành vi không được chia sẻ giữa hai cách này. Trong khi máy phục vụ tự động có thể thực hiện công việc vô thời hạn, một nhân viên thu ngân cần ăn, nghỉ giải lao và rời đi khi hết ca.
Bây giờ, bạn có thể chỉ cần đặt hành vi của con người vào một lớp thu ngân cụ thể, nhưng có một vấn đề với quyết định thiết kế này. Một lớp khách hàng sẽ không thể sử dụng sự gián tiếp để gọi những hành vi này của con người, vì chúng không có trong giao diện. Nhưng nếu lớp khách hàng của bạn gọi phương thức trực tiêp trên một nhân viên thu ngân, nó sẽ trở nên phụ thuộc vào lớp cụ thể đó. Vì vậy, sau khi bạn buộc phải thêm những hành vi của con người vào giao diện, hay bạn chỉ chấp nhận rằng bây giờ hệ thống của bạn phụ thuộc ở mức độ thấp và sẽ chỉ làm thêm khi bạn cần thay đổi nữa ? May mắn thay, bạn có thể sử dụng Interface Segregation Principle để giải quyết vấn đề này, bạn không phải gặp các vấn đề phụ thuộc buộc bạn phải khái quát hóa mọi thứ vào interface.
Nguyên tắc này nói rằng một lớp không nên bị phụ thuộc vào các phương thức mà nó không sử dụng, điều này có nghĩa là bất kỳ lớp nào implement giao diện không nên có các triển khai giả của bất kỳ phương thức nào được định nghĩa trong giao diện. Thay vào đó, bạn nên chia các giao diện lớn thành các khái quát nhỏ hơn, vậy làm thế nào để thực hiện điều này ?
Giao diện ICashier không hoạt động lớp thu ngân của con người vì tất cả các hành vi của nó được giao diện nắm bắt. Nhưng bạn có thể thấy, thiết kế này không lý tưởng, bởi vì máy tự phục vụ chứ không cần đồng hồ vào ra, nghỉ ngơi như con người. Bạn không muốn bị buộc phải cung cấp các phương thức triển khai ngu ngốc không làm gì cả, vì vậy, chúng ta nên chia ICashier thành hai phần nhỏ hơn, điều này sẽ cho phép mỗi Interface chính xác hơn với mô tả các hành vi dự kiến của nó và sẽ cho phép bạn chọn kết hợp chính xác các giao diện mà một số lớp cụ thể sẽ thực hiện.
Trong thiết kế này, giao diện ICashier cũ được chia thành ICashier mới và IHumanWorker. Giao diện ICashier mô tả hành vi chung của nhân viên, giao diện IHumanWorker mô tả hành vi chung của nhân viên, lớp HumanCashier có thể implement cả hai giao diện ICashier, IHumanWorker. Và lớp SelfServeMachine chỉ implement ICashier. Bằng cách này, cá hai lớp cụ thể của bạn sẽ chỉ cần cung cấp các triển khai cho các giao diện khái quát hóa chức năng cụ thể của chúng.
Các giao diện là một phần không thể thiếu của hệ thống hướng đối tượng, chúng giúp bạn giảm khớp nối bằng cách khái quát hóa các lớp cụ thể, nhưng cũng giống như với tất cả các nguyên tắc hướng đối tượng, bạn nên cố gắng sử dụng chúng đúng cách. Mặc dù các interface lớn không phải là một lựa chọn thiết kế kém, bạn cần kiểm tra chúng trong bối cảnh hệ thống của bạn để quyết định xem bạn có cần chia nó thành các khái quát nhỏ hơn bằng cách sử dụng nguyên tắc thiết kế này.
Interface Segregation Principle nói rằng một lớp không nên bị buộc phải phụ thuộc vào các phương thức mà nó không sử dụng và các giao diện nên được phân tách theo cách mà nó có thể mô tả chính xác chức năng riêng biệt của hệ thống của bạn.
Đôi khi không rõ cách phân tách giao diện của bạn một cách chính xác hoặc dự đoán các thay đổi trong tương lai trong các yêu cầu sẽ cần phân tách giao diện. Có một hệ thống giao diện đã được xác định rõ sẽ giúp bạn thấy các điểm phân biệt này tốt hơn. Bạn luôn luôn cố gắng thiết kế chính xác nhất giao diện, hãy nhớ chúng là những mô tả về những phần nào trong hệ thống của bạn có thể làm và mô tả càng tốt thì việc tạo, cập nhật, và bảo trì phẩn mềm của bạn càng dễ dàng hơn.
Nhận xét
Đăng nhận xét