Làm thế nào để làm việc với rễ tổng hợp lớn?


11

Tôi đang học DDD và tôi có nhiều câu hỏi hơn câu trả lời.

Chúng ta hãy xem xét một mô hình của một thư mục chứa số lượng lớn các tập tin.
Đây là cách tôi nhìn thấy nó:

Thư mục là một gốc tổng hợp.
Thực thể này phải có logic xác thực kiểm tra tính duy nhất của tên tệp khi nó được thêm hoặc chỉ đổi tên. Và thực thể Tệp chứa logic 'SetName', thông báo Thư mục qua Sự kiện Miền về các thay đổi tên.
Nhưng thư mục nên hoạt động như thế nào?
Không phải lúc nào cũng có thể tải tất cả các tệp vào bộ nhớ. Trong trường hợp này, kho lưu trữ Tệp có logic adhoc để kiểm tra tính duy nhất của tên không? Tôi cho rằng đó là một quyết định khả thi.
Tuy nhiên, điều gì sẽ xảy ra nếu một số tệp đã được thêm hoặc đổi tên mà không có giao dịch hiện tại chưa được cam kết? (không có gì ngăn cấm điều đó. Ranh giới giao dịch được đặt bên ngoài liên quan đến logic kinh doanh). Có lẽ kho lưu trữ nên tính đến cả trạng thái trong bộ nhớ và trạng thái bền vững (hợp nhất các trạng thái này có thể là nhiệm vụ không cần thiết.)

Vì vậy, khi tổng hợp gốc với tất cả các con của nó phù hợp với bộ nhớ - mọi thứ đều ổn. Và ngay khi bạn không thể cụ thể hóa tất cả các thực thể, có những rắc rối.

Tôi muốn biết các phương pháp tiếp cận cho các tình huống như vậy là gì. Có thể không có vấn đề gì cả và đó chỉ là do sự hiểu lầm của tôi về chủ đề này.


1
Điều gì khiến bạn nghĩ rằng bạn phải tải tất cả các tệp và nội dung của chúng chứ không chỉ là "FileInfo"?
Euphoric

@Euphoric. Chà, đôi khi điều đó là không thể. Dù sao có một vấn đề khác. Làm cách nào để cung cấp tính nhất quán của FileInfo và các thực thể Tệp tương ứng được thay đổi trong giao dịch hiện tại? Có lẽ CQRS giải quyết câu hỏi này ... chưa nhìn vào nó.
Pavel Voronin

1
Thật hữu ích khi hiểu rằng DDD không phải là một kỹ thuật lập trình, mà là một kỹ thuật thiết kế. Quá nhiều người coi nó như một phương pháp mã hóa. Các thuật ngữ như "gốc tổng hợp" làm trầm trọng thêm vấn đề, bởi vì chúng mang lại ấn tượng về trọng lượng kỹ thuật, trong khi thực tế chúng không thực sự nói nhiều đến các kỹ thuật lập trình. Kỹ thuật lập trình không thay đổi nhiều trong DDD; trong khi DDD không thông báo mã và kiến ​​trúc của bạn, bạn vẫn có mã và kiến ​​trúc tách biệt với nó.
Robert Harvey

@RobertHarvey Dường như với tôi rằng DDD đòi hỏi các kỹ thuật lập trình phức tạp hơn. Ít nhất là khi nói đến trường hợp góc. Tôi coi DDD chủ yếu như một cách để tách (và bản địa hóa) logic kinh doanh khỏi mã cơ sở hạ tầng không thể tránh khỏi, hoạt động ngầm đằng sau hậu trường. Đối với tôi DDD = tốt + cơ sở hạ tầng ngầm. Hầu hết các câu hỏi tôi có liên quan đến DDD liên quan đến phần cuối cùng.
Pavel Voronin

2
Tại sao bạn nói: "Ranh giới giao dịch được đặt bên ngoài liên quan đến logic kinh doanh"? Nhiệm vụ của root tổng hợp là duy trì một ranh giới giao dịch. Ngoài ra, bạn không phải tải nội dung của các tập tin. Bạn chỉ có thể tải dữ liệu meta.
Esben Skov Pedersen

Câu trả lời:


20

Câu trả lời của tôi thiên vị với cuốn sách tuyệt vời về Thiết kế hướng theo miền của Vaughn Vernon (phải đọc)

1. Ưu tiên tập hợp nhỏ.

Nếu tôi mô hình hóa miền của bạn, tôi sẽ mô hình hóa Directorydưới dạng tổng hợp và Filetổng hợp khác.

2. Tổng hợp tài liệu tham khảo theo id.

Do đó Directorysẽ có một bộ sưu tập các FileIdđối tượng giá trị.

3. Sử dụng các nhà máy để tạo tập hợp.

Đối với một trường hợp đơn giản, một phương pháp nhà máy có thể là đủ Directory.addFile(FileName fileName). Tuy nhiên, đối với các trường hợp phức tạp hơn, tôi sẽ sử dụng một nhà máy tên miền.
Nhà máy miền có thể xác nhận rằng fileNamelà duy nhất sử dụng một FileRepositoryvà một UniquefileNameValidatordịch vụ cơ sở hạ tầng.

Tại sao mô hình Filenhư một tổng hợp riêng biệt?

Bởi vì Directorieskhông được làm bằng Files. a Fileđược liên kết với một số nhất định Directory. Ngoài ra, hãy nghĩ về một thư mục có hàng ngàn tập tin. Tải tất cả các đối tượng này vào bộ nhớ mỗi khi một thư mục được tìm nạp là một trình diệt hiệu năng.

Mô hình tập hợp của bạn theo trường hợp sử dụng của bạn. Nếu bạn biết rằng sẽ không bao giờ có nhiều hơn 2-3 tệp trong một thư mục thì bạn có thể mô hình hóa tất cả chúng thành một tổng hợp duy nhất, nhưng theo kinh nghiệm của tôi, các quy tắc kinh doanh luôn thay đổi và sẽ trả tiền nếu mô hình của bạn đủ linh hoạt để phù hợp với thay đổi.

Bắt buộc đọc Thiết kế tổng hợp hiệu quả của Vaughn Vernon


2
Lưu ý rằng thực sự triển khai thư mục thực thường được thực hiện như thế này (các tập hợp riêng biệt, được tham chiếu bởi id của chúng). Ví dụ: "Tệp" được tham chiếu đơn giản từ thư mục của chúng inodetrên các hệ thống Unix.
Alexander Langer

1
Cuối cùng tôi đã đọc cuốn sách được đề nghị. Cuốn sách tuyệt vời, cảm ơn bạn. Tuy nhiên, nó vẫn chưa hoàn toàn rõ ràng. Chỉ có một Filetên đã cho có thể tồn tại Directory, tức là Directorycó bất biến: Tên duy nhất. Ít nhất nó là quan trọng cho Directory, nhưng không phải cho File. Trên thực tế @AlexanderLanger đã đúng: 'Tệp' có thể được tham chiếu bởi nhiều 'Thư mục'. Và Tên có lẽ là tài sản của tài liệu tham khảo này chứ không phải của Filechính nó. Đồng ý. Sau đó, đổi tên chức năng thuộc về Directory, nhưng một lần nữa, không nên lưu trữ hàng ngàn danh tính được tham chiếu.
Pavel Voronin

Và ngay cả khi chúng tôi đã làm, chúng tôi sẽ cần phải kiểm tra tên. Từ đây có vẻ hợp lý để tạo một phương thức trong kho thư mục : bool ContainsFileOfName(int folderId, string fileName). Sau đó, chữ ký phương thức 'Đổi tên' có thể là như sau: void Rename(int fileId, string newName)trong đó một số IFolderService(kho chứa kết thúc tốt đẹp) được giải quyết và hỏi liệu tên đó có tồn tại không.
Pavel Voronin

1

Đây không phải là một câu hỏi DDD mỗi se. Câu hỏi chính ở đây là về bối cảnh đồng bộ hóa (ở đây là một gốc tổng hợp).

Quay lại chủ đề: Thư mục sẽ chặn một số đối tượng đồng bộ hóa tên tệp và thực hiện kiểm tra xem tên tệp đã cho có được phép là O (n) trong trường hợp xấu nhất hay không.


1

Mặc dù một số người có thể nói rằng hãy cố gắng thay đổi thiết kế của bạn, luôn có một nhu cầu trong đó AR sẽ có một danh sách lớn các đối tượng đơn giản. Và để lưu trữ chúng trong bộ nhớ không phải là điều tốt nhất để làm từ góc độ hiệu suất, tuy nhiên, tất cả những gì bạn cần làm trong những trường hợp như vậy là duy trì ranh giới giao dịch. Một giải pháp đơn giản như sau:

  1. Giữ AR của thư mục đơn giản và đặt cột phiên bản.
  2. Có mỗi tệp (giả sử hàng) tham chiếu gốc tổng hợp, nói cách khác, để giữ id của thư mục.
  3. Luôn thực hiện các thay đổi của các tệp, chẳng hạn như đổi tên, thêm, xóa, thông qua AR. Nói cách khác, nếu bạn muốn thêm một tệp, tải AR và sử dụng một phương thức trong AR để thực hiện thay đổi. Giả sử bạn đang sử dụng mẫu kho lưu trữ, addFile () sẽ tạo một tệp mới, thay đổi phiên bản của thư mục. Lưu chúng dưới dạng UoW. Nếu người khác đã thay đổi AR, bạn sẽ gặp lỗi do Cột Phiên bản (phiên bản AR).
  4. Bất kỳ thay đổi nào đối với chính tệp, như Chỉnh sửa tệp hoặc đổi tên tệp, nên được thực hiện thông qua AR. Vì vậy, phiên bản được giữ trong AR. Điều này có nghĩa là về cơ bản không có đường dẫn thực thi nào khác trong mã của bạn thay đổi tệp, ngoại trừ AR sở hữu.

Một số hạn chế:

  1. Các tập tin chỉ nên thuộc về một AR. Nếu đây không phải là trường hợp, thì mô hình hóa mối quan hệ của Thư mục -> Tệp dưới dạng ngăn chặn và không phải chính tệp.
  2. Bạn không thể di chuyển một tệp từ thư mục này sang thư mục khác, trừ khi bạn thực hiện thay đổi này trong UoW, nói cách khác trong cùng một giao dịch. Đây là trường hợp đặc biệt, vì bạn nên gửi một yêu cầu sẽ kết thúc bằng hai lệnh, vì vậy cả hai AR sẽ được thay đổi, do đó hai phiên bản mới cho mỗi và có thể là hai sự kiện (đã xóa tệp, thêm tệp) và đây là một chút khó khăn vì bạn nên duy trì các đơn đặt hàng sự kiện cho hai AR mà đôi khi không dễ dàng.
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.