Mã giao diện trống có mùi không? [đóng cửa]


76

Tôi có một hàm trả về cùng một loại đối tượng (kết quả truy vấn) nhưng không có thuộc tính hoặc phương thức nào chung. Để có một kiểu chung, tôi đã sử dụng giao diện trống làm kiểu trả về và "triển khai" trên cả hai.

Tất nhiên, điều đó nghe có vẻ không đúng. Tôi chỉ có thể tự an ủi mình bằng cách bám vào hy vọng rằng một ngày nào đó các lớp đó sẽ có điểm chung và tôi sẽ chuyển logic chung đó sang giao diện trống của mình. Tuy nhiên, tôi không hài lòng và đang suy nghĩ về việc liệu tôi có nên có hai phương thức khác nhau và gọi tiếp theo có điều kiện hay không. Đó sẽ là một cách tiếp cận tốt hơn?

Tôi cũng đã được thông báo rằng .NET Framework sử dụng các giao diện trống cho mục đích gắn thẻ.

Câu hỏi của tôi là: một giao diện trống là một dấu hiệu mạnh mẽ của một vấn đề thiết kế hay nó được sử dụng rộng rãi?

CHỈNH SỬA : Đối với những người quan tâm, sau này tôi phát hiện ra rằng các công đoàn phân biệt đối xử trong các ngôn ngữ chức năng là giải pháp hoàn hảo cho những gì tôi đang cố gắng đạt được. C # có vẻ chưa thân thiện với khái niệm đó.

CHỈNH SỬA : Tôi đã viết một đoạn dài hơn về vấn đề này, giải thích vấn đề và giải pháp chi tiết.


15
Chúng được gọi là giao diện đánh dấu và dường như chúng được sử dụng rộng rãi.
BoltClock

3
Đọc msdn.microsoft.com/en-us/library/ms182128%28v=vs.80%29.aspx (cần ý kiến của tôi là phương pháp khác nhau)
V4Vendetta

1
Một cái gì đó trên dòng tương tự stackoverflow.com/questions/835140/...
V4Vendetta

9
Mùi mã có thể là một mùi dễ chịu, trong trường hợp nào thì tốt? Cà phê, bánh quế và thịt xông khói ví dụ
Chris S

Khi bạn gọi hàm của mình, bạn có biết từ các tham số bạn cung cấp loại đối tượng nào đang quay trở lại không? Nếu vậy, có nhiều hàm trả về kiểu thích hợp sẽ đúng hơn.
Angel O'Sphere

Câu trả lời:


48

Mặc dù có vẻ như tồn tại một mẫu thiết kế (hiện nay rất nhiều người đã đề cập đến "giao diện điểm đánh dấu") cho trường hợp sử dụng đó, tôi tin rằng việc sử dụng một cách thực hành như vậy là một dấu hiệu của một mùi mã (ít nhất là hầu hết thời gian).

Như @ V4Vendetta đã đăng, có một quy tắc phân tích tĩnh nhắm mục tiêu điều này: http://msdn.microsoft.com/en-us/library/ms182128(v=VS.100).aspx

Nếu thiết kế của bạn bao gồm các giao diện trống mà các kiểu dự kiến ​​sẽ triển khai, có thể bạn đang sử dụng một giao diện làm điểm đánh dấu hoặc một cách để xác định một nhóm các kiểu. Nếu việc nhận dạng này xảy ra tại thời điểm chạy, thì cách chính xác để thực hiện điều này là sử dụng thuộc tính tùy chỉnh. Sử dụng sự hiện diện hay vắng mặt của thuộc tính hoặc các đặc tính của thuộc tính để xác định các loại mục tiêu. Nếu việc nhận dạng phải xảy ra tại thời điểm biên dịch, thì có thể chấp nhận sử dụng giao diện trống.

Đây là khuyến nghị MSDN được trích dẫn:

Xóa giao diện hoặc thêm thành viên vào đó. Nếu giao diện trống đang được sử dụng để gắn nhãn một nhóm loại, hãy thay thế giao diện bằng một thuộc tính tùy chỉnh.

Điều này cũng phản ánh phần Phê bình của liên kết wikipedia đã được đăng.

Một vấn đề lớn với các giao diện đánh dấu là một giao diện xác định một hợp đồng để triển khai các lớp và hợp đồng đó được kế thừa bởi tất cả các lớp con. Điều này có nghĩa là bạn không thể "hoàn thành" một điểm đánh dấu. Trong ví dụ được đưa ra, nếu bạn tạo một lớp con mà bạn không muốn tuần tự hóa (có lẽ vì nó phụ thuộc vào trạng thái nhất thời), bạn phải sử dụng NotSerializableException một cách rõ ràng (mỗi tài liệu ObjectOutputStream).


1
Tôi nghĩ rằng trong trường hợp sử dụng của tôi (chỉ có hai lớp và sẽ không thể được dẫn xuất), nó có vẻ ổn. Xem chỉnh sửa làm rõ của tôi.
Sedat Kapanoglu

Tôi chấp nhận đây là câu trả lời. Mặc dù các câu trả lời khác cũng cung cấp thông tin có giá trị, câu trả lời này cũng giải thích cặn kẽ nhất về các vấn đề tiềm ẩn với cách tiếp cận.
Sedat Kapanoglu

1
Như đã được chỉ ra ở những nơi khác, mặc dù attributescách làm này là 'đúng đắn', chúng khó thực hiện và sử dụng hơn, điều này trong thực tế sẽ có tác dụng ngược lại với việc sử dụng chúng.
nicodemus 13

9

Bạn nói rằng hàm của bạn "trả về các đối tượng hoàn toàn khác nhau dựa trên một số trường hợp nhất định" - nhưng chúng khác nhau như thế nào? Một người có thể là một người viết luồng, một lớp giao diện người dùng khác, một đối tượng dữ liệu khác? Không ... tôi nghi ngờ điều đó!

Các đối tượng của bạn có thể không có bất kỳ phương thức hoặc thuộc tính chung nào, tuy nhiên, chúng có thể giống nhau về vai trò hoặc cách sử dụng. Trong trường hợp đó, một giao diện đánh dấu có vẻ hoàn toàn phù hợp.


Chúng là các loại kết quả truy vấn khác nhau nhưng cả hai kết quả truy vấn đều có.
Sedat Kapanoglu

1
OK - như tôi nghĩ, chúng có vai trò chung, mặc dù chúng không chứa các thuộc tính chung. Nghe có vẻ như một giao diện đánh dấu là vừa phải!
ColinE

8

Nếu không được sử dụng làm giao diện đánh dấu , tôi sẽ nói rằng có, đây là mùi mã.

Giao diện xác định hợp đồng mà người triển khai tuân thủ - nếu bạn có giao diện trống mà bạn không sử dụng phản chiếu (như cách làm với giao diện điểm đánh dấu), thì bạn cũng có thể sử dụng Objectkiểu cơ sở (đã tồn tại).


2
objectsẽ quá chung chung và sẽ không cung cấp gợi ý về "loại" trả lại. giao diện giúp tôi thu hẹp các tùy chọn của mình về việc diễn giải giá trị trả về của hàm. nhưng tôi hiểu nhận xét của bạn liên quan đến sự thiếu rõ ràng về sự giống nhau của các đối tượng tôi đang trả lại.
Sedat Kapanoglu

@ssg - khá. Phải có một cái gì đó tương tự với các đối tượng này nếu bạn chuyển chúng cho một phương thức để hoạt động trên chúng, nếu không bạn nên có các phương thức riêng biệt.
Oded

6

Bạn đã trả lời câu hỏi của chính mình ... "Tôi có một hàm trả về các đối tượng hoàn toàn khác nhau dựa trên một số trường hợp nhất định." ... Tại sao bạn lại muốn có cùng một hàm trả về các đối tượng hoàn toàn khác nhau? Tôi không thể thấy một lý do nào để điều này hữu ích, có thể bạn có một cái hay, trường hợp đó, hãy chia sẻ.

CHỈNH SỬA: Xem xét sự làm rõ của bạn, bạn thực sự nên sử dụng giao diện đánh dấu. "hoàn toàn khác nhau" là hoàn toàn khác so với "là cùng một loại". Nếu họ hoàn toàn khác nhau (không chỉ là họ không có thành viên chia sẻ), đó sẽ là một mùi mã.


Đây có vẻ như là một ứng cử viên tốt hơn cho một nhận xét. Tôi đã thêm một phần làm rõ cho câu hỏi của mình. Hỏi đi nếu bạn cần bất cứ điều gì khác.
Sedat Kapanoglu

4

Như nhiều người có lẽ đã nói, một giao diện trống không có giá trị sử dụng như một "giao diện đánh dấu".

Có lẽ cách sử dụng tốt nhất mà tôi có thể nghĩ đến là biểu thị một đối tượng thuộc một tập hợp con cụ thể của miền, được xử lý bởi một Kho lưu trữ tương ứng. Giả sử bạn có các cơ sở dữ liệu khác nhau mà từ đó bạn truy xuất dữ liệu và bạn có triển khai Kho lưu trữ cho mỗi cơ sở dữ liệu. Một Kho lưu trữ cụ thể chỉ có thể xử lý một tập hợp con và không được cung cấp một thể hiện của một đối tượng từ bất kỳ tập hợp con nào khác. Mô hình miền của bạn có thể trông giống như sau:

//Every object in the domain has an identity-sourced Id field
public interface IDomainObject
{
   long Id{get;}
}

//No additional useful information other than this is an object from the user security DB
public interface ISecurityDomainObject:IDomainObject {}

//No additional useful information other than this is an object from the Northwind DB
public interface INorthwindDomainObject:IDomainObject {}


//No additional useful information other than this is an object from the Southwind DB
public interface ISouthwindDomainObject:IDomainObject {}

Các kho lưu trữ của bạn sau đó có thể được tạo chung cho ISecurityDomainObject, INorthwindDomainObject và ISouthwindDomainObject, và sau đó bạn có một kiểm tra thời gian biên dịch để đảm bảo rằng mã của bạn không cố chuyển đối tượng Bảo mật đến Northwind DB (hoặc bất kỳ hoán vị nào khác). Trong những tình huống như thế này, giao diện cung cấp thông tin có giá trị về bản chất của lớp ngay cả khi nó không cung cấp bất kỳ hợp đồng thực hiện nào.

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.