Tôi có nên tạo giao diện cho các đối tượng truyền dữ liệu?


19

Đó là một ý tưởng tốt hay một ý tưởng tồi để tạo ra một giao diện cho các đối tượng truyền dữ liệu? Giả định rằng đối tượng thường là đột biến.

Mặc dù ví dụ của tôi là trong Java, nó nên được áp dụng cho bất kỳ ngôn ngữ nào khác có khái niệm tương tự.

interface DataTransferObject  {
    String getName();
    void setName(String name);
}

class RealDataTransferObject  implements DataTransferObject {

    String name;
    String getName() {
        return name;
    } 
    void setName(String name) {
        this.name = name;
    }
}

Tất nhiên, đây là một ví dụ đơn giản, trong cuộc sống thực có thể có nhiều lĩnh vực hơn.

Câu trả lời:


24

Câu trả lời chung là không , bởi vì bạn không bao giờ nên thêm mã mà không có lý do cụ thể, cụ thể cho nó và không có lý do chung nào cho giao diện như vậy.

Điều đó đang được nói, đôi khi có thể có một lý do tốt. Nhưng trong tất cả các trường hợp tôi đã thấy, các giao diện này là một phần, chỉ bao gồm một hoặc một vài thuộc tính được chia sẻ bởi nhiều lớp mà tôi muốn sử dụng đa hình mà không cho chúng một siêu lớp chung. Các ứng cử viên điển hình là một Idtài sản để sử dụng trong một số loại đăng ký hoặc một Nametài sản để hiển thị cho người dùng. Nhưng nó có thể hữu ích trong mọi trường hợp bạn muốn một số mã xử lý mọi thứ có X - chỉ cần tạo một XSourcegiao diện có chứa các phương thức getX(và, chỉ khi được yêu cầu setX).

Nhưng một giao diện riêng cho mỗi lớp mô hình, chứa tất cả các thuộc tính? Tôi không thể tưởng tượng một lý do tốt để làm điều đó. Một lý do xấu sẽ là một khung được thiết kế tồi đòi hỏi nó; Các EJB thực thể đã làm điều đó, nếu tôi nhớ chính xác. Rất may, họ rất tệ, họ không bao giờ đạt được nhiều lực kéo và bị từ chối kể từ EJB 3.0

Sidenote: vui lòng tránh sử dụng thuật ngữ "đối tượng giá trị" để mô tả các hạt Java chỉ với các getters và setters tầm thường - nó mâu thuẫn với định nghĩa phổ biến hơn về đối tượng giá trị là một thứ không có bản sắc thường bất biến. Một thuật ngữ tốt hơn sẽ là DTO hoặc lớp mô hình - mặc dù trong trường hợp sau lưu ý rằng các mô hình miền thiếu máu được coi là một phản mẫu.


3
"Các mô hình miền thiếu máu được coi là một phản mẫu" - bởi Martin Fowler, người ở PEAA, thừa nhận rằng ông biết những người đã làm việc theo cách đó trong nhiều thập kỷ "rất thành công". Vì vậy, tôi đề nghị, bớt một mô hình chống và nhiều hơn một Fowler-thích-làm việc. Tuy nhiên, câu trả lời tốt, +1.
pdr

4
@pdr: Fowler có thể đã đặt ra thuật ngữ này, nhưng anh ta không phải là người duy nhất coi họ là một phản mẫu. Tôi không nghĩ bất cứ ai thực sự hiểu OO đều nghĩ rằng nên loại bỏ logic cụ thể của miền khỏi mô hình miền.
Michael Borgwardt

Cảm ơn đã sửa chữa thuật ngữ, DTO là từ tôi đã tìm kiếm tối qua nhưng không thể nhớ về cuộc sống của tôi. Bằng cách thay đổi tên xung quanh, mọi thứ trở nên thiết kế hợp lý hơn.
Archimedes Trajano

@pdr Tôi nghĩ cách tốt nhất để nói rằng đó là một phản đề trong bối cảnh lập trình OO. Có nhiều mô hình khác trong đó nó hoàn toàn tốt, và bạn thậm chí có thể làm việc thành công theo cách đó trong ngôn ngữ OO (nó sẽ không đặc biệt hướng đối tượng).
Daniel B

3
@MichaelBorgwardt: Tôi đồng ý, anh ấy không đơn độc trong việc đó. Nhưng cũng không phải là những người không đồng ý. Nếu bạn nói rằng "mô hình miền thiếu máu được một số người coi là chống mẫu", thì tôi đã không nói gì. Thành thật mà nói, tôi nghĩ rằng toàn bộ câu trả lời của bạn sẽ tốt hơn nếu không có đoạn cuối cùng. Nửa đầu sẽ có một nhận xét tốt hơn; nửa thứ hai không cung cấp gì cho câu hỏi này.
pdr

2

Tạo giao diện là ok, nhưng KHÔNG phải là cách ví dụ của bạn hoạt động. Bạn nên xóa setter khỏi giao diện, và nó sẽ ổn thôi:

interface ValueObject {
  String getName();
};

Điều này cho phép nhiều triển khai khác nhau của nó, như tên có thể được tìm nạp từ cơ sở dữ liệu ... Setter nên ở giao diện khác.


2

Các giao diện xác định một hợp đồng giữa các lớp thực hiện các giao diện và các máy khách của chúng. Chúng được sử dụng như một cơ chế trừu tượng hóa để khách hàng có thể thao tác "những thứ có hành vi nhất định".

Vì vậy, câu trả lời chung cho câu hỏi "tôi có nên tạo và sử dụng giao diện này không?" là: Có, nếu bạn có thể liên kết một khái niệm (một) duy nhất có liên quan về mặt ngữ nghĩa cho khách hàng của bạn.

Ví dụ, so sánh là một giao diện tốt, bởi vì nó giải thích rằng mọi thứ có thể được so sánh nhờ một trong các phương thức của họ và với tư cách là một khách hàng tôi quan tâm đến việc xử lý các đối tượng so sánh (ví dụ: để sắp xếp chúng). Một điều tương tự, CoolStuff không phải là một giao diện tốt nếu bạn thừa nhận các đối tượng thú vị không có hành vi cụ thể (thực tế, bạn có thể tưởng tượng một phần mềm xử lý các đối tượng mát mẻ có ý nghĩa, bởi vì chúng có hành vi phổ biến như beCool phương pháp).

Trong trường hợp cụ thể của bạn, tôi tin rằng giao diện của bạn là vô dụng. Ai sẽ sử dụng nó, làm thế nào và khi nào? Bạn không thể tạo giao diện cho từng giá trị có thể thay đổi. Vì vậy, hãy tự hỏi những gì là tài sản có liên quan và thú vị đằng sau phương pháp của bạn.

Nếu những gì bạn muốn là xử lý các đối tượng có tất cả các giá trị có thể thay đổi của chúng có thể truy cập được thông qua một vài phương thức, hãy xem khái niệm về Java bean và cách bạn có thể buộc các lớp của mình áp dụng các quy ước của chúng.


2

Như Michael đã nói, đừng thêm giao diện trừ khi bạn có nhu cầu cụ thể về giao diện đó.

Kiểm tra là một ví dụ về một lý do tốt. Mặc dù tôi thích sử dụng các cộng tác viên thực sự nếu họ chỉ là "đối tượng giá trị" như bạn gọi cho họ, để cách ly thử nghiệm đơn vị thực sự, bạn có thể cần tạo một đối tượng giả để thử nghiệm, trong trường hợp đó một giao diện khá hữu ích.


1
Các giao diện không cần thiết cho việc sử dụng các khung mô phỏng theo độ tuổi.
Michael Borgwardt

Âm thanh như bạn đang ủng hộ khỉ. Tôi đã từng đi trên con đường đó với nốt ruồi trong C # và nó không đẹp lắm. Tốt hơn để vượt qua trong cộng tác viên của bạn nếu có thể.
jhewlett

1
Mặc dù hai khung mô phỏng tôi sử dụng Mockito và easyMock không thể chế nhạo các lớp cuối cùng khi biến chúng thành bất biến.
Archimedes Trajano

1

Nếu bạn muốn đối tượng này có một số loại xác thực trường trong tương lai, bạn nên đưa chúng vào giai đoạn đầu.


0

'Giao diện cho đối tượng giá trị' là cái mà tôi thường dùng để gọi một người truy cập.

Tôi đã trải nghiệm các chính sách khác nhau liên quan đến người truy cập cần. Một số người ủng hộ khi càng nhiều càng tốt, một số khác cấm sau đó để giảm số lượng mã để viết.

Một số lý do cho người truy cập (hoặc sử dụng giá trị trực tiếp) như sau:

  • Bộ truy cập cho phép thay đổi sau cách lưu trữ giá trị
  • Accessor cho phép thêm nhật ký truy cập khi bạn muốn gỡ lỗi phần mềm của mình (khi thêm một cuộc gọi nhật ký trong một phương thức, bạn nắm bắt mọi thay đổi giá trị)
  • Các bộ truy cập phù hợp hơn với lập trình đối tượng, mọi biến được gói gọn bằng các phương thức
  • Bộ truy cập làm giảm tính biểu cảm của mã (nhiều SLOC hơn cho cùng một kết quả)
  • Bộ truy cập cần một số CPU

Cá nhân tôi ủng hộ để giảm số lượng người truy cập và sử dụng chúng khi bạn mong đợi setter (setName) sẽ trở thành nhiều hơn một ảnh hưởng đơn giản sau này.


0

Loại đối tượng giá trị này là mức độ khá thấp. Tôi khuyên bạn nên đẩy nó theo một trong hai hướng: (1) làm cho đối tượng giá trị trở nên bất biến, nghĩa là, giống như một giá trị thực , hoặc, (2) nâng cao khả năng biến đổi thành chức năng kinh doanh theo định hướng cấp cao hơn, nghĩa là chúng ta nên phơi bày giao diện về các đơn vị chức năng liên quan đến miền.

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.