2011-02-02 37 views
32

Giả sử chúng ta có kiến ​​trúc lấy cảm hứng từ CQRS, với các thành phần như Lệnh, Mô hình miền, Sự kiện miền, Đọc mô hình DTO.
Tất nhiên, chúng ta có thể sử dụng các đối tượng giá trị trong Mô hình miền của chúng tôi. Câu hỏi của tôi là, họ cũng nên được sử dụng trong:Đối tượng giá trị trong CQRS - nơi sử dụng

  1. Commands
  2. Sự kiện
  3. DTOs

Tôi chưa thấy bất kỳ ví dụ nơi Value Objects (VO) được sử dụng trong các thành phần đã đề cập ở trên. Thay vào đó, các kiểu nguyên thủy được sử dụng. Có lẽ nó chỉ là những ví dụ đơn giản. Sau khi tất cả, sự hiểu biết của tôi về VOs sử dụng trong DDD là chúng hoạt động như một chất keo dán cho toàn bộ ứng dụng.

Động lực của tôi:

Lệnh.
Giả sử người dùng gửi biểu mẫu chứa trường địa chỉ. Chúng ta có Object Value Object để biểu diễn khái niệm này. Khi xây dựng lệnh trong máy khách, chúng ta nên xác nhận hợp lệ đầu vào của người dùng, và khi nó được tạo đúng, chúng ta có thể tạo đối tượng Address ngay tại đó và khởi tạo Command với nó. Tôi thấy không cần ủy quyền tạo đối tượng Address cho trình xử lý lệnh.

Sự kiện miền.
Mô hình miền đã hoạt động về các đối tượng giá trị, do đó, bằng cách xuất bản sự kiện với VO thay vì chuyển đổi chúng thành các kiểu nguyên thủy, chúng ta có thể tránh một số mã ánh xạ. Tôi khá chắc chắn rằng nó không sao để sử dụng VO trong trường hợp này.

DTO.
Nếu DTO phía truy vấn của chúng tôi có thể chứa đối tượng giá trị, điều này cho phép tính linh hoạt hơn. Ví dụ: nếu chúng tôi có đối tượng Money, chúng tôi có thể chọn hiển thị nó bằng EUR hoặc USD, không cần phải thay đổi Đọc mô hình.

+3

Sau khi cân nhắc điều này một thời gian, kết luận của tôi: có các đối tượng hành vi phong phú trong Sự kiện đơn giản là không thể được, vì chúng phải thể hiện dữ liệu lịch sử và chúng tôi không có cách nào để tuần tự hóa hành vi ngày hôm nay. Đối với các lệnh DTO, các lệnh này có thể hoạt động, và nó vẫn chưa rõ ràng cho tôi nếu khớp nối mà nó giới thiệu là chấp nhận được hay không (dù sao, đây là nhiều hơn về 'cả hai lớp Domain và Presentation nên tham khảo cùng một sự thực thi của Money VO' thay vì 'nên TransferMoneyCommand chứa tiền VO hoặc MoneyDTO'). – driushkin

Trả lời

22

Ok tôi đã thay đổi ý định. Tôi đã cố gắng để đối phó với VOs một bó gần đây và sau khi xem này http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson nó làm rõ một vài điều cho tôi.

Lệnh và sự kiện là thông điệp (và không phải đối tượng, đối tượng là dữ liệu + hành vi), trong một số khía cạnh giống DTO, chúng truyền dữ liệu về sự kiện và bản thân chúng đóng gói không có hành vi.

Đối tượng giá trị không giống DTO. Họ là một đại diện tên miền và họ nói chung, phong phú về hành vi giống như tất cả các đại diện miền khác.

Lệnh và sự kiện giao tiếp thông tin vào và ra khỏi miền tương ứng, nhưng bản thân chúng không đóng gói bất kỳ hành vi nào. Từ quan điểm đó có vẻ như sai và có thể là một ranh giới bối cảnh có thể vi phạm để vượt qua VO bên trong chúng.

Để diễn giải Oren (mặc dù anh ấy đang đề cập đến nHibernate và WCF) "Không gửi miền của bạn qua dây". http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx

Nếu bạn muốn truyền đạt một đối tượng giá trị, tôi khuyên bạn nên chuyển các thuộc tính cần thiết cần thiết để xây dựng lại VO trong đó thay thế.

Original Text (cho hậu thế):

Nếu bạn đang yêu cầu nếu giá trị gia tăng đối tượng có thể được thông qua bởi các mô hình miền với các sự kiện hoặc thông qua vào bằng lệnh, tôi không thực sự nhìn thấy một vấn đề lớn với các cựu, mặc dù sau này có thể vi phạm một số quy tắc của gốc tổng hợp là "chủ sở hữu" của các giá trị.

Điều đó nói rằng một đối tượng giá trị đại diện cho các khái niệm như ví dụ về màu sắc. Bạn không màu xanh lá cây, bạn màu xanh lá cây hay không. Có vẻ như không có gì sai về bản chất với một lệnh nói với bạn rằng bạn là màu xanh lá cây bằng cách vượt qua điều này.

Đọc chương từ DDD trên mẫu Tổng hợp gốc giải thích các đối tượng và đối tượng giá trị khá tốt và đáng đọc hơn một vài lần.

+0

Tôi nghĩ rằng đó là ok từ quan điểm DDD thuần túy để chia sẻ VO, nhưng từ quan điểm cqrs, điều này có thể giới thiệu một số vấn đề kỹ thuật, như versioning của sự kiện nếu Event Sourcing được áp dụng. Và rồi câu hỏi tự nhiên nảy sinh, đây thực sự chỉ là một vấn đề kỹ thuật, hay nó là cái gì đó không đúng về bản chất với toàn bộ ý tưởng. – driushkin

+0

Sự hiểu biết tôi lấy từ cuốn sách DDD là trong khi tổng hợp nguồn gốc là chủ sở hữu của các thực thể tương ứng của họ và các đối tượng giá trị họ có thể vượt qua trên một tham chiếu đến những đối tượng thoáng qua. Mục đích duy nhất của gốc tổng hợp là xác định ranh giới giao dịch của hệ thống. Một lần nữa, tôi có thể hiểu sai một số điều này và luôn luôn là YMMV. Mặc dù chắc chắn sẽ rất tệ khi sắp xếp một thực thể như là một phần của sự kiện mà tôi không thể thấy bất kỳ vấn đề gì với VO vì chúng phải là một giá trị bất biến thực sự. –

+5

"Các đối tượng giá trị không giống DTO. Chúng là đại diện miền và chúng [...] phong phú về hành vi giống như tất cả các đại diện miền khác." Tôi rất không đồng ý với phần sau. Mặc dù chúng là một phần của miền (ví dụ: xác định địa chỉ * *), chúng có nghĩa là dùng một lần và không có bất kỳ hành vi nào liên quan đến chúng. Đó là lý do tại sao họ thường không thay đổi, để ngăn cản bạn không muốn gây rối với VO của bạn. – Dav

4

Tôi nói đó là một ý tưởng tồi.

Có một lý do khiến chúng tôi không thực hiện tương tự với các thực thể - để tránh ghép các phần khác của hệ thống với miền (sai địa điểm). Điều này cũng đúng đối với Value Objects, sự khác biệt duy nhất giữa các đối tượng giá trị và thực thể là tuổi thọ và quyền sở hữu - những khác biệt này không ảnh hưởng đến cách chúng ta nên và không nên kết đôi với chúng.

Hãy tưởng tượng rằng bạn tạo sự kiện chứa VO. Thay đổi trong miền của bạn yêu cầu bạn thay đổi VO đó. Bây giờ bạn đã tự đóng vai mình thành một góc nơi sự kiện của bạn cũng là buộc để thay đổi, ditto cho bất kỳ Lệnh hoặc DTO nào là một phần của.

Điều này cần tránh.

Sử dụng DTO và/hoặc nguyên thủy. Ánh xạ chúng (AutoMapper làm cho nó một thỏa thuận 1 dòng).

+1

Vâng, những VO đó sẽ không thuộc về Mô hình Miền. Họ sẽ là một kiến ​​thức được chia sẻ trên tất cả các thành phần hệ thống (như MyApp.Core lắp ráp có thể được tham chiếu bởi bất cứ ai). Miễn là các khái niệm có ổn định, hoặc thậm chí, không có thay đổi đột phá, tôi đoán điều này sẽ ổn. Ofc, nếu chúng ta sử dụng Sourcing Event, điều này sẽ làm lộn xộn mã của chúng ta với các khái niệm cũ không còn được sử dụng mà là một phần của các sự kiện cũ. Vì vậy, đây là một nhược điểm tôi có thể nghĩ đến. Tuy nhiên, ý tưởng của việc có một mô-đun của các khái niệm được chia sẻ (như tiền tệ, tiền, vận tốc) trên các âm thanh ứng dụng rất hấp dẫn đối với tôi. – driushkin

+0

Nếu chúng là khái niệm được chia sẻ giữa các ứng dụng, tôi sẽ nói rằng chúng không phải là một phần của miền (như miền, theo định nghĩa thực tế, cụ thể đối với ứng dụng) vì chúng là cơ sở hạ tầng hoặc mã chung. Tôi đã nghĩ về Tiền đặc biệt khi tôi trả lời. –

+0

Tôi cũng cảm thấy rằng VO trong CQRS là một ý tưởng tồi, nhưng sau đó, làm thế nào chúng ta có thể đóng gói logic miền khi tổng hợp trở nên phức tạp? –

3

Tương tự như các câu trả lời khác, trong SOA điều này sẽ phá vỡ đóng gói dịch vụ vì miền hiện đang bị rò rỉ.

0

Theo Clean Code DTO của bạn là cấu trúc dữ liệu (chỉ để thêm cụm từ khác), trong khi đối tượng giá trị là đối tượng. Sự khác biệt mà các đối tượng có thể có hành vi. Trộn các cấu trúc dữ liệu với các đối tượng thường là một ý tưởng rất tồi, bởi vì sẽ rất khó để duy trì lai bạn nhận được.

Tôi không cảm thấy đúng khi đặt đối tượng giá trị cho DTO từ góc độ kiến ​​trúc. Các đối tượng giá trị nằm bên trong mô hình miền trong khi các DTO bạn đã đề cập đang định nghĩa giao diện của mô hình. Chúng ta thường xây dựng một giao diện để tách rời thế giới bên ngoài từ bên trong một cái gì đó. Vì vậy, trong trường hợp hiện tại, chúng tôi đã thêm DTO để tách rời thế giới bên ngoài khỏi các đối tượng giá trị (và các công cụ liên quan đến mô hình khác). Sau đó thêm các đối tượng giá trị vào giao diện là điên rồ.

Vì vậy, bạn chưa đáp ứng được giải pháp này vì đó là một mẫu chống.

+0

Vì vậy, chúng ta không nên thêm bất kỳ loại Chuỗi hoặc Số nguyên nào vào DTO, vì nó cũng là đối tượng giá trị? – bojanv55

+0

@ bojanv55 Chuỗi và số nguyên là nguyên thủy, không phải là đối tượng giá trị. Một đối tượng Date hoặc DateTime sẽ là một ví dụ tốt hơn. Tôi có nghĩa là DTO không nên chuyển VO được định nghĩa trong miền. Ví dụ: chúng tôi có VO trong miền của chúng tôi liên quan đến sự ra đời của ai đó, ví dụ: 1985-12-20. Nếu chúng ta truy vấn ngày sinh, thì chúng ta nên trả về 12-20 trong DTO. Nếu chúng ta truy vấn ngày sinh, thì chúng ta nên quay trở lại 1985-12-20 trong DTO. Nếu chúng ta truy vấn tuổi tác, thì chúng ta nên trả về 31 năm trong DTO. Vì vậy, DTO sẽ không chứa toàn bộ VO với logic của nó, chỉ là đại diện chúng ta thực sự cần thiết. – inf3rno

+0

@ bojanv55 Ít nhất đó là cách tôi sử dụng DTO và VO. Cách tiếp cận này làm việc cho đến nay, nhưng ofc. Tôi không thể sai lầm. :-) – inf3rno

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