Tìm kiếm một số lời khuyên thiết kế OO


12

Tôi đang phát triển một ứng dụng sẽ được sử dụng để mở và đóng van trong môi trường công nghiệp và đã nghĩ đến một thứ đơn giản như thế này: -

public static void ValveController
{
    public static void OpenValve(string valveName)
    {
        // Implementation to open the valve
    }

    public static void CloseValve(string valveName)
    {
        // Implementation to close the valve
    }
}

(Việc triển khai sẽ ghi một vài byte dữ liệu vào cổng nối tiếp để điều khiển van - một "địa chỉ" có nguồn gốc từ tên van và "1" hoặc "0" để mở hoặc đóng van).

Một nhà phát triển khác hỏi liệu chúng ta có nên tạo một lớp riêng cho mỗi van vật lý hay không, trong đó có hàng tá. Tôi đồng ý sẽ tốt hơn nếu viết mã như vậy PlasmaValve.Open()hơn ValveController.OpenValve("plasma"), nhưng điều này có quá mức không?

Ngoài ra, tôi đã tự hỏi làm thế nào tốt nhất để giải quyết thiết kế với một vài yêu cầu giả định trong tương lai: -

  1. Chúng tôi được yêu cầu hỗ trợ một loại van mới yêu cầu các giá trị khác nhau để mở và đóng nó (không phải 0 và 1).
  2. Chúng tôi được yêu cầu hỗ trợ một van có thể được đặt ở bất kỳ vị trí nào từ 0-100, thay vì chỉ đơn giản là "mở" hoặc "đóng".

Thông thường tôi sẽ sử dụng tính kế thừa cho loại điều này, nhưng gần đây tôi đã bắt đầu hiểu về "thành phần trên sự kế thừa" và tự hỏi liệu có một giải pháp khéo léo nào được sử dụng thành phần không?


2
Tôi sẽ tạo một lớp van chung có định danh cho van cụ thể (không phải là chuỗi, có lẽ là enum) và bất kỳ thông tin nào cần thiết cho luồng điều khiển bên trong các phương thức OpenValve / CloseValve. Ngoài ra, bạn có thể làm cho lớp valv trừu tượng và thực hiện các triển khai riêng cho từng loại, trong đó van đóng / mở chỉ gọi logic bên trong lớp van đã cho cho các trường hợp các van khác nhau có cơ chế đóng / mở khác nhau. Cơ chế chung sẽ được định nghĩa trong lớp cơ sở.
Jimmy Hoffa

2
Đừng lo lắng về các yêu cầu giả định trong tương lai. YAGNI.
pdr

3
@pdr YAGNI là một con dao hai lưỡi, tôi đồng ý rằng nó đáng để theo dõi chung, nhưng nói đến mức cực đoan có thể nói làm bất cứ điều gì để giúp duy trì hoặc khả năng đọc trong tương lai là vi phạm YAGNI, vì điều này tôi thấy phạm vi của YAGNI quá mơ hồ nhiều Điều đó nói rằng, nhiều người nhận ra nơi sử dụng YAGNI và nơi để ném nó bởi vì kế toán cho tương lai sẽ giúp bạn giảm đau nghiêm trọng. Tôi chỉ nghĩ rằng mọi người nên cẩn thận đề nghị mọi người theo dõi YAGNI khi bạn không biết họ sẽ đến đâu trên quang phổ đó.
Jimmy Hoffa

2
Người đàn ông, "thành phần trên vô nhân đạo" được đánh giá cao. Tôi sẽ tạo một lớp / giao diện trừu tượng của Valve và sau đó phân lớp chúng thành PlasmaValve. Và sau đó tôi chắc chắn rằng ValveContoder của tôi sẽ hoạt động với (các) Valve, không quan tâm đến việc chúng chính xác là lớp con nào.
MrFox

2
@suslik: Hoàn toàn đúng. Tôi cũng đã thấy mã tuyệt vời được gọi là spaghetti bởi những người không hiểu các nguyên tắc RẮN. Chúng ta có thể đi mãi mãi với điều này. Quan điểm của tôi là tôi đã thấy nhiều vấn đề hơn gây ra bởi việc loại bỏ các nguyên tắc đã được thiết lập (sinh ra từ nhiều năm kinh nghiệm) ngoài tầm với so với những gì tôi đã thấy do tuân thủ quá mức. Nhưng tôi đồng ý rằng cả hai thái cực đều nguy hiểm.
pdr

Câu trả lời:


12

Nếu mỗi phiên bản của đối tượng van sẽ chạy cùng mã với ValveContoder này, thì có vẻ như nhiều phiên bản của một lớp sẽ là cách phù hợp. Trong trường hợp này, chỉ cần cấu hình van mà nó điều khiển (và cách) trong hàm tạo của đối tượng van.

Tuy nhiên, nếu mỗi điều khiển van cần mã khác nhau để chạy và ValveContoder hiện tại đang chạy một câu lệnh chuyển đổi khổng lồ làm những việc khác nhau tùy thuộc vào loại van, thì bạn đã thực hiện kém đa hình. Trong trường hợp đó, hãy viết lại nó cho nhiều lớp với một cơ sở chung (nếu điều đó có ý nghĩa) và để nguyên tắc trách nhiệm duy nhất là hướng dẫn thiết kế của bạn.


1
+1 để đề cập đến các câu lệnh chuyển đổi dựa trên loại như mùi mã. Tôi thường thấy các loại báo cáo chuyển đổi trong đó nhà phát triển tuyên bố rằng anh ta chỉ theo dõi KISS. Ví dụ hoàn hảo về cách các nguyên tắc thiết kế có thể bị biến thái heh
Jimmy Hoffa

2
Nhiều trường hợp cũng có thể giúp việc liên kết các van theo trình tự dễ dàng hơn, cho phép bạn mô hình hóa đường ống thực tế dưới dạng biểu đồ được định hướng trong mã của mình. Sau đó, bạn cũng có thể thêm logic nghiệp vụ vào các lớp, trong trường hợp bạn cần thực hiện một thao tác nào đó như mở một van khi một van khác đóng lại để tránh tích tụ áp suất hoặc đóng tất cả các van hạ lưu để bạn không bị hiệu ứng "búa nước" khi van được mở lại.
TMN

1

Gripe chính của tôi là sử dụng các chuỗi cho tham số xác định van.

Ít nhất là tạo một Valvelớp cógetAddress dạng nhu cầu triển khai cơ bản và chuyển chúng cho ValveControllervà đảm bảo rằng bạn không thể tạo các van không tồn tại. Bằng cách này, bạn sẽ không phải xử lý các chuỗi sai trong mỗi phương thức mở và đóng.

Cho dù bạn tạo các phương thức tiện lợi gọi mở và đóng ValveController vào bạn, nhưng thành thật mà nói, tôi sẽ giữ tất cả thông tin liên lạc đến cổng nối tiếp (bao gồm cả mã hóa) trong một lớp duy nhất mà các lớp khác sẽ gọi khi cần. Điều này có nghĩa là khi bạn cần di chuyển sang bộ điều khiển mới, bạn chỉ cần sửa đổi một lớp.

Nếu bạn thích thử nghiệm, bạn cũng nên tạo ValveControllermột singleton để bạn có thể giả định nó (hoặc tạo một máy đào tạo cho các nhà khai thác).


Tôi chưa bao giờ thấy ai giới thiệu một singleton vì mục đích thử nghiệm trước đây - thường thì nó đi theo một cách khác.
Kazark

Thành thật mà nói, singleton là nhiều hơn để tránh các thống kê và vì vậy giao tiếp có thể được đồng bộ hóa
ratchet freak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.