Lợi ích của việc có các mô hình POCO thuần túy là gì?


14

Lợi ích chính của việc có các mô hình POCO thuần túy là gì? Tôi nhận được rằng các Mô hình nên sạch sẽ và đơn giản, nhưng tôi có xu hướng thích duy trì các đối tượng con trong các lớp mô hình. Ví dụ nếu tôi có mộtClassAClassBđược định nghĩa như sau:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

Có một cái gì đó vốn đã sai với việc có các phương thức thêm và loại bỏ? Thay vào đó, tôi có nên chỉ hiển thị danh sách và cho phép mã máy khách thêm bất cứ điều gì vượt qua trách nhiệm xác thực dữ liệu đơn giản như không null và không trùng lặp với lớp khác không?

Bất kỳ trợ giúp được đánh giá cao. Cảm ơn.


Tôi sẽ xóa các phương thức Thêm / Xóa trừ khi chúng thêm một số giá trị, như dịch một đối số ClassB null thành phiên bản mẫu NullObject của đối tượng:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham

Nếu bạn đã từng đối phó với sự đau đầu của các lớp ActiveRecord với hàng trăm phương thức có thể hoặc không phải là điều bạn muốn tại bất kỳ thời điểm nào, tôi nghĩ sẽ dễ hiểu hơn về kháng cáo.
Casey

Lý do chính để tránh thiết kế đặc biệt này là vì nó đi ngược lại các nguyên tắc thiết kế .net. Nó hoàn toàn tùy ý, nhưng mọi người mong đợi bộ sưu tập có các phương thức đột biến trong đó.
Frank Hileman

@Casey Tôi không sử dụng mẫu Bản ghi hoạt động, phương thức thêm chỉ đơn giản là thực hiện một số xác thực dữ liệu nhỏ. Phương thức remove nằm ở đó vì bộ sưu tập không bị lộ, họ chỉ cần thêm và xóa khỏi danh sách nội bộ. Mặc dù vậy, tôi đã thay đổi nó để sử dụng một loại bộ sưu tập khác cho phép tôi thực hiện xác nhận trong khi vẫn sử dụng các phương thức Thêm / Xóa tích hợp.
Jesse

Câu trả lời:


42

Hai câu hỏi của bạn không liên quan.

Lợi ích của việc có các mô hình POCO thuần túy là gì?

Một POCO thuần túy không phụ thuộc vào một số khuôn khổ, quy ước, [] điều hay kết nối mật thiết với một số đối tượng phụ thuộc tương tự. Nói cách khác, thế giới hoàn toàn có thể thay đổi xung quanh một POCO và nó chỉ tiếp tục làm những gì nó làm mà không cần quan tâm. Bạn không thể phá vỡ nó bằng cách cập nhật một khung, bằng cách chuyển nó sang một hệ thống mới hoặc nhìn nó thật buồn cười. Nó chỉ tiếp tục làm việc. Các phụ thuộc duy nhất là những điều nó yêu cầu rõ ràng.

POCO không có gì hơn ý tưởng POJO. Chữ J được đổi thành chữ C vì mọi người nhìn bạn buồn cười khi bạn giải thích một khái niệm có tên Java nếu những người đó đang sử dụng C #. Ý tưởng không phụ thuộc vào ngôn ngữ. Họ có thể chỉ đơn giản gọi nó là Plain Old Object. Nhưng ai muốn khoe khoang về việc sử dụng POO?

Tôi sẽ để Fowler giải thích nguồn gốc:

Thuật ngữ này được đặt ra trong khi Rebecca Parsons, Josh MacKenzie và tôi đang chuẩn bị cho một cuộc nói chuyện tại một hội nghị vào tháng 9 năm 2000. Trong cuộc nói chuyện, chúng tôi đã chỉ ra nhiều lợi ích của việc mã hóa logic kinh doanh vào các đối tượng java thông thường thay vì sử dụng Entity Beans. Chúng tôi tự hỏi tại sao mọi người lại chống lại việc sử dụng các đối tượng thông thường trong hệ thống của họ và kết luận rằng đó là vì các đối tượng đơn giản thiếu một cái tên lạ mắt. Vì vậy, chúng tôi đã cho họ một cái, và nó được bắt rất độc đáo.

martinfowler.com: POJO

Đối với câu hỏi khác của bạn:

Có một cái gì đó vốn đã sai với việc có các phương thức thêm và loại bỏ?

Tôi không thích Atrực tiếp biết về B. Nhưng đó là một điều DIP không phải là một điều POJO .


Tôi đã phụ thuộc trực tiếp vào mục Bđích đơn giản, lý tưởng là cả hai sẽ thực hiện các giao diện. Nhưng Avẫn có một danh sách IInterfaceB. Có điều gì đó sai với AddChildphương pháp nếu trẻ em được ghép lỏng lẻo thông qua các tham chiếu giao diện?
Jesse

6
Tôi có thể làm một loạt những điều ngớ ngẩn vì đơn giản. Điều tôi không thích là A biết về B. A không sử dụng B nên không cần xác định giao diện A sở hữu phù hợp để nói chuyện với B thông qua. Theo như tôi có thể nói A là một bộ sưu tập. Vì vậy, A nên đối phó với B thông qua <T> để không phải biết điều gì về nó.
candied_orange

2
Tôi cũng đã thấy đối tượng sử dụng dữ liệu cũ của PODO đối với các ứng dụng dữ liệu cũ đơn giản để tránh bất kỳ loại công cụ xác định ngôn ngữ nào trong từ viết tắt. PODO nghe có vẻ hơi ngớ ngẩn (nghe có vẻ giống như một biểu tượng mà bạn nghe thấy trên Tatooine, đối với tôi), nhiều hơn so với POJO hoặc POCO tôi cho rằng, nhưng ít ngớ ngẩn hơn POO.
KRyan

2
Tôi tự hỏi bài thuyết trình của Fowler sẽ tốt đến mức nào nếu anh ta gọi họ là POO?
Oliver

3

Với Thêm và Xóa, bạn đang thực hiện Collection<T>các tính năng. Hãy tự hỏi tại sao bạn sử dụng IEnumerable<T>thay vì List<T>hoặc một số lớp đột biến khác? Rõ ràng đó không phải là vì bộ sưu tập của bạn nên được đọc.

Lý do duy nhất tôi có thể nghĩ đến là bạn muốn kiểm soát phương thức truy cập nào bạn muốn xuất bản. Trong trường hợp đó, sẽ tốt hơn khi tạo lớp bộ sưu tập của riêng bạn, đóng gói một danh sách, thực hiện các phương thức chọn của bạn Thêm và loại bỏ và thực hiện IEnumerable<T>. Sau đó sử dụng nó thay vìIEnumerable<T> cho các loại bộ sưu tập trẻ em của bạn.

Nhưng có vẻ như tôi List<ClassB>sẽ chỉ phục vụ bạn tốt.


0

Những gì AddChildthêm vào, vàRemoveChild loại bỏ từ? Nếu đó là từ cơ sở dữ liệu (hoặc lưu trữ liên tục dưới bất kỳ hình thức nào), bạn đã có Bản ghi hoạt động. Không nhất thiết luôn luôn là một điều xấu, nhưng nó chắc chắn khiến bạn phải lo lắng về các khuôn khổ, quy ước, sự phụ thuộc, v.v., như @CandiedOrange đề cập.

Đồng thời, đâu sẽ là điểm tránh sự phụ thuộc từ ClassA sang ClassB (hoặc ít nhất là InterfaceB) nếu tất cả chúng đều nằm trong cùng một ứng dụng? Trong miền thế giới thực mà ứng dụng của bạn đang lập mô hình, mọi thứ phụ thuộc vào nhau. Các đối tượng trong thế giới thực có các bộ sưu tập các đối tượng khác "thuộc về" chúng. Hoàn toàn phù hợp để thể hiện các mối quan hệ đó trong mã của bạn.

Lý do duy nhất khiến nó trở nên phức tạp hơn một chút là vì dường như bạn có nhu cầu quản lý chính xác cách thức ClassB được liên kết và tách khỏi ClassA. Vì vậy, bạn có một chút hành vi để thực hiện. Bạn có thể triển khai nó trong lớp (hoàn toàn "hợp pháp"; xem /programming//a/725365/44586 ) hoặc bạn có thể có một loại lớp riêng biệt có chứa hành vi đó. Làm những gì có ý nghĩa nhất cho hoàn cảnh cá nhân của bạn.

Trong mọi trường hợp, POJO / POCO thực sự chỉ là OOP vì nó có nghĩa là, không được trang bị và không bị cản trở. Thực hiện theo các nguyên tắc OOP và bạn sẽ an toàn.


Thực sự AddChild chỉ kiểm tra sự trùng lặp và null và không cho phép. RemoveChild có mặt vì để ngăn chặn backdoor thêm bộ sưu tập được hiển thị dưới dạng IEnumerable. Nó sẽ chỉ thực hiện loại bỏ tiêu chuẩn khỏi bộ sưu tập mặc dù.
Jesse

1
Cảm ơn vì đã giải thích. Vâng, nghe có vẻ chính xác là loại hành vi nên có trong POCO, và chắc chắn tốt hơn là chỉ hiển thị IEnumerable cơ bản của bạn để người gọi sửa đổi hoặc thay thế theo ý muốn.
John M Gant

Tôi nghĩ Active Record chỉ là một mô hình xấu.
Casey

1
@Casey, bạn sẽ không nhận được bất kỳ tranh luận từ tôi về điều đó. Nhưng tôi sẽ không tranh luận nếu ai đó muốn sử dụng nó. Điểm chính là nếu Jesse có ý định sử dụng một mẫu như Active Record tích hợp tính bền bỉ với định nghĩa mô hình, anh ta sẽ có tất cả các vấn đề nổi bật của CandiedOrange và sẽ không thực sự đủ điều kiện là POCO, vì những gì đáng giá. Nhưng dù sao đó không phải là những gì anh ấy đang làm.
John M Gant
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.