2012-03-16 29 views
5

Tôi bắt đầu viết một giao diện thông thạo và nhìn vào một mảnh cũ Martin Fowler đã viết trên giao diện thông thạo (mà tôi đã không nhận ra anh và Eric Evans đặt ra thuật ngữ). Trong phần này, Martin đề cập rằng những người định cư thường trả về một thể hiện của đối tượng đang được cấu hình hoặc làm việc, điều mà anh ta nói là vi phạm CQS.Giao diện thông thạo có vi phạm Nguyên tắc Tách Truy vấn Lệnh không?

Các quy ước chung trong thế giới cú đúp xoăn là modifier phương pháp này có hiệu lực, mà tôi thích vì nó tuân theo nguyên tắc của CommandQuerySeparation. Quy ước này không cản trở giao diện thông thoáng của , vì vậy tôi có khuynh hướng tạm ngưng quy ước cho trường hợp này.

Vì vậy, nếu giao diện thông thạo của tôi không giống như:

myObject 
    .useRepository("Stuff") 
    .withTransactionSupport() 
    .retries(3) 
    .logWarnings() 
    .logErrors(); 

Đây có phải là thực sự là một vi phạm CQS?

CẬP NHẬT Tôi đã phá vỡ mẫu của mình để hiển thị cảnh báo ghi nhật ký và lỗi dưới dạng hành vi riêng biệt.

+0

'logWarningsAndErrors' có trả lại gì không? Nếu không, thì nó thực sự là một giao diện thông thạo? –

+0

@ M.Babcock đã cập nhật mẫu của tôi. Chắc chắn, 'logWarningsAndErrors' trả về một giao diện mà tôi có thể thêm các hành vi bổ sung vào. –

Trả lời

0

No. Mẫu ở đây là "Cấu hình". Các lệnh cấu hình như vậy trả về đối tượng cấu hình chính nó như trái ngược với một cái gì đó không liên quan đến lệnh. Vi phạm phân tách Lệnh/Truy vấn sẽ xảy ra nếu các lệnh phục vụ mục đích cấu hình trả về một số dữ liệu không liên quan, ví dụ:

if (myObject.UseRepository("Stuff") > 1 && myObject.UseRepository("Bla") < 5) { 
    // oh, good, some invisible stuff internal to myObject is in right interval... 
} 
+2

sry, tôi không hiểu câu trả lời của bạn, nhưng tôi muốn. bạn có thể mở rộng nó không? "nếu bạn có ..." đã ở đâu? ngoài ra, không có thay đổi trạng thái nội bộ trong đoạn mã của bạn. tôi thấy sự vi phạm nguyên tắc "nói, đừng hỏi", nhưng đó là nó –

+0

Đã cố gắng cải tổ, hãy cho tôi biết nếu vẫn khó hiểu ... –

9

Vâng, đúng vậy. Tất cả những phương pháp đó rõ ràng là trả lại một cái gì đó, và rõ ràng là họ có tác dụng phụ (đánh giá từ thực tế là bạn không làm bất cứ điều gì với giá trị trả về, nhưng bạn không bận tâm để gọi cho họ). Vì định nghĩa của CQS nói rằng các mutator không nên trả về một giá trị, chúng ta có một sự vi phạm rõ ràng trong tay.

Nhưng điều quan trọng với bạn là CQS có bị vi phạm không? Nếu giao diện thông thạo làm cho bạn hiệu quả hơn mọi thứ được xem xét và nếu bạn coi đó là một mẫu nổi tiếng với lợi ích và nhược điểm như nhau, thì tại sao nên nó quan trọng vi phạm nguyên tắc X trên giấy?

+0

Làm thế nào là nó rõ ràng rằng 'logWarningsAndErrors' trả về một cái gì đó? –

+0

@ M.Babcock: Về mặt kỹ thuật, không phải, chỉ từ đoạn mã đó. Bạn đã cho tôi ở đó. – Jon

+0

Đồng ý. Tại sao nó quan trọng nếu nó vi phạm nguyên tắc X, nếu nó giúp bạn sử dụng nó. –

2

Nó vi phạm nguyên tắc này khi nó thay đổi đối tượng nhưng không phải khi nó chỉ trả về một đối tượng mới.

var newObject = myObject 
    .useRepository("Stuff") 
    .withTransactionSupport() 
    .retries(3) 
    .logWarningsAndErrors(); 

Nếu myObject không thay đổi sau tuyên bố này, mọi thứ đều ổn. Nói chung, một giao diện thông thạo vi phạm nguyên tắc CQS, nếu, và chỉ khi nó có tác dụng phụ.

Tuy nhiên, câu hỏi là, nếu ví dụ của bạn đại diện cho một truy vấn nào cả. "Thông thạo" có nhất thiết có nghĩa là "truy vấn" không? Nó có lẽ chỉ có thể được coi là một giao diện hành động lưu loát trong đó cùng một đối tượng được truyền từ một hành động sang hành động tiếp theo.

+0

hm, nhưng toàn bộ điểm cấu hình là thay đổi đối tượng (tùy thuộc vào cấu hình) vậy tại sao lại bận tâm? –

+0

Điều gì sẽ khác biệt nếu đối tượng bị sửa đổi là một phiên bản mới hoặc cũ? Bất kỳ một trong số 4 cuộc gọi hoặc sửa đổi giá trị trả lại của biểu thức (bất kể đó là gì) hoặc không làm gì cả và do đó nên bỏ qua. – Jon

+0

Câu hỏi đặt ra là, nếu nó sửa đổi một đối tượng hiện có và trả về một kết quả cùng một lúc, làm cho nó một lệnh và một truy vấn cùng một lúc. Nó phải là lệnh ** hoặc ** truy vấn. –

Các vấn đề liên quan