2011-01-10 17 views
11

Sau nhiều lần đọc và suy nghĩ khi tôi bắt đầu quấn đầu vào DDD, tôi hơi bối rối về các phương pháp hay nhất để xử lý các hệ thống phân cấp phức tạp. nguồn gốc. Tôi nghĩ đây là một câu hỏi thường gặp nhưng sau khi đọc vô số ví dụ và thảo luận, không có ai nói về vấn đề tôi đang gặp.Vui lòng làm rõ cách tạo/cập nhật xảy ra đối với các thực thể con của một tập hợp tổng hợp

Nếu tôi phù hợp với tư duy DDD, các thực thể bên dưới gốc tổng hợp sẽ không thay đổi. Đây là mấu chốt của rắc rối của tôi, vì vậy nếu điều đó không đúng, đó là lý do tại sao tôi bị mất.

Đây là ví dụ được chế tạo ... hy vọng nó chứa đủ nước để thảo luận.

Hãy xem xét chính sách bảo hiểm ô tô (Tôi không có bảo hiểm, nhưng điều này khớp với ngôn ngữ tôi nghe khi trên điện thoại với công ty bảo hiểm của tôi).

Chính sách rõ ràng là một thực thể. Trong chính sách, giả sử chúng ta có Tự động. Tự động, vì lợi ích của ví dụ này, chỉ tồn tại trong một chính sách (có thể bạn có thể chuyển tự động sang chính sách khác, vì vậy đây cũng là tiềm năng cho tổng hợp, thay đổi Chính sách ... nhưng giả sử nó đơn giản hơn bây giờ) . Vì một Auto không thể tồn tại mà không có một Policy, tôi nghĩ nó nên là một thực thể chứ không phải là một gốc. Vì vậy, chính sách trong trường hợp này là một gốc tổng hợp.

Bây giờ, để tạo Chính sách, giả sử nó phải có ít nhất một ô tô. Đây là nơi tôi cảm thấy thất vọng. Giả sử Auto khá phức tạp, bao gồm nhiều trường và có thể là một đứa trẻ cho nơi nó được thu thập (một Vị trí). Nếu tôi hiểu chính xác, một nhà xây dựng "tạo Chính sách"/nhà máy sẽ phải lấy đầu vào là Tự động hoặc bị hạn chế thông qua trình tạo không được tạo mà không có Tự động này. Và sự sáng tạo của Auto, vì nó là một thực thể, không thể được thực hiện trước (bởi vì nó là bất biến? Có lẽ đây chỉ là một cách giải thích không chính xác). Vì vậy, bạn không thể nói Auto mới và sau đó setX, setY, add (Z).

Nếu tự động là hơi tầm thường, bạn sẽ phải xây dựng một hệ thống phân cấp lớn của các nhà xây dựng và như vậy để cố gắng quản lý việc tạo Tự động trong ngữ cảnh của Chính sách.

Một bước nữa cho điều này là sau, sau khi Chính sách được tạo và muốn thêm một Tự động khác ... hoặc cập nhật một Tự động hiện có. Rõ ràng, các chính sách kiểm soát này ... tốt ... nhưng Policy.addAuto() sẽ không hoàn toàn bay vì người ta không thể chỉ vượt qua trong một Auto mới (phải không !?). Ví dụ nói những thứ như Policy.addAuto (VIN, make, model, v.v.) nhưng tất cả đều đơn giản đến mức trông hợp lý. Nhưng nếu phương pháp tiếp cận phương pháp nhà máy này tách rời với quá nhiều tham số (toàn bộ giao diện Tự động, có thể hiểu được) tôi cần một giải pháp.

Từ thời điểm đó trong suy nghĩ của tôi, tôi nhận ra rằng có một tham chiếu tạm thời cho một thực thể là OK. Vì vậy, có thể nó là tốt để có một thực thể được tạo ra bên ngoài của cha mẹ của nó trong tổng hợp trong một môi trường thoáng qua, vì vậy có thể nó là OK để nói điều gì đó như:

auto = AutoFactory.createAuto(); auto.setX auto.setY

hoặc nếu gắn bó với tính bất biến, AutoBuilder.new(). SetX(). SetY(). Xây dựng()

và sau đó có nó được sắp xếp ra khi bạn nói chính sách .addAuto (tự động)

Ví dụ bảo hiểm này trở nên thú vị hơn nếu bạn thêm Sự kiện, chẳng hạn như Tai nạn với PolicyReport hoặc RepairEstimates ... một số đối tượng giá trị nhưng hầu hết các thực thể đều vô nghĩa bên ngoài chính sách ... tại ít nhất cho ví dụ đơn giản của tôi.

Vòng đời của Chính sách với hệ thống phân cấp đang phát triển theo thời gian có vẻ là hình ảnh cơ bản tôi phải vẽ trước khi bắt đầu đào sâu ... và đó là khái niệm nhà máy hoặc cách các thực thể con được xây dựng/gắn với một thư mục tổng hợp rằng tôi đã không nhìn thấy một ví dụ vững chắc của.

Tôi nghĩ tôi thân thiết. Hy vọng điều này là rõ ràng và không chỉ là một câu hỏi thường gặp lặp lại có câu trả lời tất cả các nơi.

+1

christian, tôi nghĩ câu hỏi chính về tổng hợp được giới hạn nhất quán hoặc tính nhất quán giao dịch tôi cũng sẽ nói. Đặt câu hỏi này. Thông tin tối thiểu REAL bạn cần để tạo chính sách là gì? Chỉ là sự sáng tạo. Tất cả những gì bạn cần là rất ít để làm cho nó "hợp lệ". Sau đó, bạn ASSIGN, một tự động cho nó, (chính sách không xây dựng AUTOS). Hiểu rồi? Tôi làm việc cho một công ty bảo hiểm. Tôi sẽ không lo lắng nhiều về chính sách. Nó đầu tiên bắt đầu với một câu trích dẫn, và trước đó là một dẫn đầu. Vì vậy, tất cả những gì bạn phải làm là "liên kết" tất cả thông tin đó với chính sách bằng cách suy ra nhận dạng từ dữ liệu được thu thập của bạn. –

Trả lời

1

đối tượng bên dưới gốc tổng hợp sẽ không thay đổi.

No. Các đối tượng giá trị được cho là không thay đổi. Các đối tượng có thể thay đổi trạng thái của họ là.

Chỉ cần chắc chắn rằng bạn làm đóng gói thích hợp:

  • thực thể sẽ thay đổi bản thân
  • thực thể được sửa đổi thông qua tổng hợp gốc chỉ

nhưng Policy.addAuto() sẽ không khá bay vì người ta không thể vượt qua trong một chiếc xe mới (phải không?)

Thông thường nó được cho là như vậy. Vấn đề là nhiệm vụ tạo tự động có thể trở nên quá lớn. Nếu bạn may mắn và biết rằng thực thể có thể được sửa đổi, có thể chia nhỏ nó thành các tác vụ nhỏ hơn như SpecifyEngine, sự cố được giải quyết.


Tuy nhiên, "thế giới thực" không hoạt động theo cách đó và tôi cảm thấy đau của bạn.

Tôi gặp trường hợp người dùng tải lên 18 trang tải dài dữ liệu (với quy tắc ưa thích bổ sung - nó phải được "nhập" bất kể dữ liệu không hợp lệ (như tôi nói - điều đó giống như nói đúng == sai)). Quá trình tải lên này được coi là một hoạt động nguyên tử.

Những gì tôi làm trong trường hợp này ...

Trước hết - Tôi có mô hình excel đối tượng tài liệu, ánh xạ (ví dụ Customer.Name == tấm 1st, "C24") và độc giả mà điền vào DOM. Những thứ đó sống trong cơ sở hạ tầng ở rất xa.

Điều tiếp theo - đối tượng thực thể và giá trị trong miền của tôi trông giống như DOM dto`s, nhưng chỉ chiếu mà tôi quan tâm, với các loại dữ liệu thích hợp và theo xác thực. + Tôi có 1: 1 liên kết trong mô hình tên miền của tôi mà cô lập ra lộn xộn bẩn (may mắn đủ, nó loại phù hợp với ngôn ngữ phổ biến).

Được trang bị điều đó - vẫn còn một phần phức tạp - ánh xạ giữa các DOM dtos excel với đối tượng miền. Đây là nơi tôi hy sinh đóng gói - tôi xây dựng thực thể với các đối tượng giá trị của nó từ bên ngoài. Quá trình suy nghĩ của tôi là loại đơn giản - thực thể bị phơi sáng quá mức này không thể được tiếp tục và sự hợp lệ vẫn có thể bị ép buộc (thông qua các nhà xây dựng). Nó sống bên dưới gốc tổng hợp.

Về cơ bản - đây là phần mà Bạn không thể chạy trốn khỏi Tàn tật.
Đôi khi, ứng dụng chỉ chỉnh sửa nhóm dữ liệu.

P.s. Tôi không chắc rằng tôi đang làm đúng. Có thể tôi đã bỏ lỡ điều gì đó quan trọng về vấn đề này. Hy vọng rằng sẽ có một số cái nhìn sâu sắc từ người trả lời khác.

+0

Cảm ơn câu trả lời. – christian

+0

Về tính không thay đổi của các thực thể, ý tôi là từ OUTSIDE, vì vậy chúng tôi đang ở cùng một trang ở đó. Tôi thấy rằng nguyên tử có thể bị phá vỡ và có thể có một nơi nào đó, nhưng nếu điều đó không thể xảy ra (như ví dụ của bạn, nhưng ngay cả trong ví dụ chính sách của tôi), có vẻ như gợi ý là các nhà máy phức tạp ... tất cả trạng thái có thể sửa đổi của miền của bạn hoặc phải ánh xạ từ những thứ loại DTO. Có thể những người khác sẽ làm sáng thêm một chút. – christian

0

Một phần của câu trả lời của tôi dường như được chụp trong các bài viết:

Domain Driven Design - Parent child relation pattern - Specification pattern

Best practice for Handling NHibernate parent-child collections

how should i add an object into a collection maintained by aggregate root

Để tóm tắt:

It is OK để tạo ra một thực thể bên ngoài tổng hợp của nó nếu nó có thể quản lý tính nhất quán của riêng nó (bạn vẫn có thể sử dụng nhà máy cho nó). Vì vậy, có một tham chiếu thoáng qua để tự động là OK và sau đó một chính sách mới (Auto) là làm thế nào để có được nó vào tổng hợp. Điều này có nghĩa là xây dựng các biểu đồ "tạm thời" để có được các chi tiết trải ra một chút (không phải tất cả được xếp thành một phương thức hoặc nhà xây dựng nhà máy).

tôi nhìn thấy lựa chọn thay thế của tôi như là một trong hai:

(a) Xây dựng một DTO hoặc đồ thị thiếu máu khác đầu tiên và sau đó vượt qua nó để một nhà máy để có được tổng hợp xây dựng.

Cái gì như:

autoDto = new AutoDto(); 
autoDto.setVin(..); 
autoDto.setEtc... 
autoDto.setGaragedLocation(new Location(..)); 
autoDto.addDriver(...); 
Policy policy = PolicyFactory.getInstance().createPolicy(x, y, autoDto); 
auto1Dto... 
policy.addAuto(auto1Dto); 

(b) Sử dụng các nhà xây dựng (có khả năng hợp chất):

builder = PolicyBuilder.newInstance(); 
builder = builder.setX(..).setY(..); 
builder = builder.addAuto(vin, new Driver()).setGaragedLocation(new Location()); 
Policy = builder.build(); 
// and how would update work if have to protect the creation of Auto instances? 
auto1 = AutoBuilder.newInstance(policy, vin, new Driver()).build(); 
policy.addAuto(auto1); 

Như điều này xoắn xung quanh và xung quanh một vài điều dường như rõ ràng.

Theo tinh thần của ngôn ngữ phổ biến, nó có ý nghĩa để có thể nói:

policy.addAuto

policy.updateAuto

Những lập luận để những điều này và như thế nào tổng hợp và ngữ nghĩa sáng tạo của thực thể được quản lý không hoàn toàn rõ ràng, nhưng phải xem xét một nhà máy để hiểu được miền có vẻ hơi bị ép buộc.

Ngay cả khi Chính sách là tổng hợp và quản lý cách mọi thứ được đặt cùng nhau bên dưới, các quy tắc về giao diện Tự động dường như thuộc về Tự động hoặc nhà máy của nó (với một số ngoại lệ cho việc Liên quan đến chính sách).

Vì Chính sách không hợp lệ nếu không có trẻ em được xây dựng tối thiểu, những trẻ này cần được tạo trước hoặc trong quá trình tạo.

Và tuyên bố cuối cùng là mấu chốt. Có vẻ như đối với hầu hết các phần, các bài viết này xử lý việc tạo ra trẻ em như các vấn đề riêng biệt và sau đó dán chúng. Cách tiếp cận DDD thuần túy dường như cho rằng Chính sách phải tạo ra các Autos nhưng các chi tiết của spin đó nằm ngoài tầm kiểm soát trong các trường hợp không tầm thường.

+0

Tôi muốn nói rằng các trường hợp không tầm thường là do bạn không làm cho Tự động tổng hợp gốc. Một thực thể phải khá tầm thường để nó không phải là một Tổng hợp chính nó. Nếu tự động cần phải được tạo ra bởi chính nó, hơn nó sống trên riêng của nó, và không phải là một phần của chính sách. Nếu Tự động chỉ là một số thông tin mà chỉ Chính sách được quan tâm và Chính sách chịu trách nhiệm, thì sẽ có ý nghĩa khi Chính sách tạo và cập nhật và xóa Chính sách. –

13

Tổng hợp Rễ tồn tại với mục đích nhất quán giao dịch.

Về mặt kỹ thuật, tất cả những gì bạn có là Đối tượng giá trị và đối tượng.

Sự khác biệt giữa hai yếu tố này là bất biến và nhận dạng.

Đối tượng giá trị sẽ không thay đổi và danh tính của nó là tổng của dữ liệu.

Money // A value object 
{ 
    string Currency; 
    long Value; 
} 

Hai đối tượng tiền bằng nhau nếu chúng có giá trị bằng nhau và bằng nhau. Do đó, bạn có thể trao đổi cái này cho cái kia và về mặt khái niệm, nó sẽ như thể bạn có cùng một Tiền.

Thực thể là một đối tượng có khả năng thay đổi theo thời gian, nhưng danh tính của chúng không thay đổi được trong suốt thời gian tồn tại của nó.

Person // An entity 
{ 
    PersonId Id; // An immutable Value Object storing the Person's unique identity 
    string Name; 
    string Email; 
    int Age; 
} 

Vậy khi nào và tại sao bạn có tổng hợp gốc?

Rễ tổng hợp là các thực thể chuyên môn có công việc là nhóm một tập hợp các khái niệm miền theo một phạm vi giao dịch chỉ nhằm mục đích thay đổi dữ liệu. Đó là, nói rằng một người có chân. Bạn sẽ cần phải tự hỏi mình, các thay đổi về Chân và các thay đổi về Người có được nhóm lại với nhau theo một giao dịch không? Hoặc tôi có thể thay đổi một cách riêng biệt với người khác không?

Person // An entity 
{ 
    PersonId Id; 
    string Name; 
    string Ethnicity; 
    int Age; 
    Pair<Leg> Legs; 
} 

Leg // An entity 
{ 
    LegId Id; 
    string Color; 
    HairAmount HairAmount; // none, low, medium, high, chewbacca 
    int Length; 
    int Strength; 
} 

Nếu chân có thể tự thay đổi và có thể tự thay đổi, cả hai đều là Tổng hợp gốc. Nếu Leg không thể thay đổi một mình, và Person phải luôn luôn được tham gia vào giao dịch, hơn Leg nên được viết bên trong thực thể Person. Tại thời điểm đó, bạn sẽ phải đi qua Người để thay đổi Chân.

Quyết định này sẽ phụ thuộc vào tên miền bạn là người mẫu:

Có lẽ Người là cơ quan duy nhất trên đôi chân của mình, họ mọc dài hơn và mạnh mẽ hơn dựa trên tuổi của mình, những thay đổi màu sắc theo dân tộc của mình, vv Đây là những bất biến và Người sẽ chịu trách nhiệm đảm bảo chúng được duy trì. Nếu ai đó muốn thay đổi chân của Người này, hãy nói rằng bạn muốn cạo chân, bạn phải yêu cầu anh ta tự cạo râu, hoặc đưa cho bạn tạm thời để bạn cạo râu.

Hoặc bạn có thể thuộc miền khảo cổ học. Ở đây bạn tìm thấy Chân, và bạn có thể thao tác các Chân một cách độc lập. Tại một thời điểm nào đó, bạn có thể tìm thấy một cơ thể hoàn chỉnh và đoán xem người này là ai trong lịch sử, bây giờ bạn có một Người, nhưng Người không nói gì trong những gì bạn sẽ làm với các Chân bạn tìm thấy, ngay cả khi nó được hiển thị Chân. Màu của chân thay đổi dựa trên mức độ phục hồi mà bạn đã áp dụng cho nó hoặc những thứ khác. Những bất biến này sẽ được duy trì bởi một thực thể khác, lần này nó sẽ không phải là con người, mà có thể là nhà khảo cổ học.

Để trả lời câu hỏi của bạn:

tôi tiếp tục nghe bạn nói về tự động, vì vậy đó là rõ ràng là một khái niệm quan trọng của tên miền của bạn. Nó là một thực thể hoặc một đối tượng giá trị? Có quan trọng nếu Auto là một với #XYZ nối tiếp, hoặc bạn chỉ quan tâm đến thương hiệu, màu sắc, năm, mô hình, thực hiện, vv? Giả sử bạn quan tâm đến danh tính chính xác của Tự động và không chỉ là các tính năng của nó, mà còn cần phải là một thực thể của tên miền của bạn. Bây giờ, bạn nói về chính sách, một chính sách ra lệnh cho những gì được đề cập và không được đề cập trong Auto, điều này phụ thuộc vào bản thân Auto, và có lẽ cả khách hàng nữa, vì dựa trên lịch sử lái xe của anh ta, loại và năm và những gì không tự động có, Chính sách của anh ấy có thể khác.

Vì vậy, tôi đã có thể thụ thai có:

Auto : Entity, IAggregateRoot 
{ 
    AutoId Id; 
    string Serial; 
    int Year 
    colour Colour; 
    string Model 
    bool IsAtGarage 
    Garage Garage; 
} 

Customer : Entity, IAggregateRoot 
{ 
    CustomerId Id; 
    string Name; 
    DateTime DateOfBirth; 
} 

Policy : Entity, IAggregateRoot 
{ 
    string Id; 
    CustomerId customer; 
    AutoId[] autos; 
} 

Garage : IValueObject 
{ 
    string Name; 
    string Address; 
    string PhoneNumber; 
} 

Bây giờ theo cách bạn làm cho nó âm thanh, bạn có thể thay đổi một chính sách mà không cần phải thay đổi một Auto và một khách hàng với nhau. Bạn nói những điều như thế nào, nếu Auto ở nhà để xe, hoặc chúng tôi chuyển Auto từ một chính sách này sang chính sách khác. Điều này làm cho tôi cảm thấy như tự động là chính của nó Tổng hợp gốc, và như vậy là chính sách và như vậy là khách hàng. Tại sao vậy? Bởi vì có vẻ như đó là việc sử dụng tên miền của bạn nên bạn sẽ thay đổi nhà để xe của Tự động mà không quan tâm đến Chính sách được thay đổi với nó. Nghĩa là, nếu ai đó thay đổi trạng thái Garage và IsAtGarage của Auto, bạn không quan tâm đến việc không thay đổi Chính sách. Tôi không chắc liệu tôi có rõ ràng hay không, bạn sẽ không muốn thay đổi Tên và DateOfBirth của Khách hàng theo cách không giao dịch, bởi vì có thể bạn thay đổi tên của mình, nhưng nó không thay đổi Ngày và bây giờ bạn có tham nhũng khách hàng có ngày sinh không khớp với tên của anh ta. Mặt khác, bạn có thể thay đổi Tự động mà không thay đổi Chính sách. Do đó, Tự động không nên nằm trong tổng hợp của Chính sách. Hiệu quả, Tự động không phải là một phần của Chính sách, nhưng chỉ có một cái gì đó mà Chính sách theo dõi và có thể sử dụng.

Bây giờ chúng ta thấy rằng nó hoàn toàn có ý nghĩa rằng bạn có thể tạo một Tự động trên chính nó, vì nó là một gốc tổng hợp. Tương tự, bạn có thể tự tạo Khách hàng. Và khi bạn tạo một Chính sách, bạn chỉ cần liên kết nó với một Khách hàng tương ứng và Ô tô của mình.

aCustomer = Customer.Make(...); 
anAuto = Auto.Make(...); 
anotherAuto = Auto.Make(...); 
aPolicy = Policy.Make(aCustomer, { anAuto, anotherAuto }, ...); 

Bây giờ, trong ví dụ của tôi, Nhà để xe không phải là một Tổng hợp tổng hợp. Điều này là bởi vì, nó không có vẻ là một cái gì đó tên miền trực tiếp làm việc với. Nó luôn được sử dụng thông qua Auto. Điều này có ý nghĩa, các công ty bảo hiểm không sở hữu nhà để xe, họ không làm việc trong kinh doanh nhà để xe. Bạn sẽ không bao giờ cần phải tạo ra một nhà để xe đã tồn tại trên riêng của nó. Thật dễ dàng để có phương thức anAuto.SentToGarage(name, address, phoneNumber) trên Tự động tạo Garage và gán nó cho Tự động. Bạn sẽ không tự xóa Nhà để xe. Thay vào đó, bạn sẽ làm anAuto.LeftGarage().

+0

Rất tiếc, chỉ cần đọc ngay bây giờ và bạn nên chỉnh sửa câu trả lời này. Bạn cho tiền như là một ví dụ tuyệt vời của một đối tượng giá trị, nhưng sau đó sử dụng nó như một phần của AR. Điều đó là không thể, AR sẽ tổng hợp các đối tượng miền khác. – JoeG

+0

@JoeG Điểm của AR là đảm bảo tính nhất quán của tổng hợp. Tổng hợp là khái niệm. Tiền là tổng hợp, nó bao gồm tiền tệ và giá trị với nhau. Nó cần cả hai để được coi là tiền. AR không phải là vật chứa. Vì vậy, nó là bình thường đối với tiền để trở thành AR trong ví dụ tầm thường của tôi. Tiền có trách nhiệm duy trì trạng thái tiền tệ và giá trị phù hợp với nhau và có thể nói là: đồng bộ hóa.Rõ ràng, nó không thay đổi kể từ khi nó là một VO, nhưng thực tế bạn nói Tiền là một AR, khi bạn sẽ bền bỉ Tiền bạn sẽ biết rằng tiền tệ và giá trị phải được giao dịch. –

+0

Có lẽ tôi đang đọc quá gần hoặc nó chỉ là một cái gì đó về từ ngữ của bạn. Bạn nói một VO là bất biến, Tiền là một VO, nhưng sau đó "nếu tiền có thể được thay đổi" nó có thể là một AR. Nó không thể thay đổi, nó là bất biến như một VO! VO có thể là một phần của Tổng hợp, nhưng không phải là AR. Trong Chpt 6 của DDD, Evans nói: "Chọn một ENTITY làm gốc của mỗi AGGREGATE ..." Nhấn mạnh NOT được thêm vào. Hơn nữa, vì mục đích của một tổng hợp là để điều trị thay đổi dữ liệu cho Tổng hợp như một đơn vị, và một VO không thể thay đổi, có một AR là vô nghĩa, ít nhất là IMO. – JoeG

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