DDD - Tổng hợp gốc với số lượng lớn trẻ em


10

Tôi sẽ mở đầu câu hỏi này bằng cách nói rằng tôi còn khá mới với DDD vì vậy tôi có thể đang mắc một số lỗi cơ bản ở đây!

Tôi làm việc trong một dự án liên quan đến các khái niệm về Tài khoản và Giao dịch (theo nghĩa tài chính). Tài khoản có thể có nhiều Giao dịch được nhập vào.

Dường như đối với tôi, Tài khoản và Giao dịch đều là Thực thể và Tài khoản là gốc tổng hợp có chứa Giao dịch do Giao dịch không thể tồn tại mà không có Tài khoản.

Tuy nhiên, khi tôi đến để áp dụng điều này trong mã, tôi ngay lập tức gặp một vấn đề. Trong nhiều trường hợp, việc tôi có một danh sách mọi Giao dịch trong Tài khoản mọi lúc không hữu ích lắm. Tôi quan tâm đến việc có thể thực hiện những việc như tính toán số dư Tài khoản và thực thi các bất biến như giới hạn tín dụng, nhưng tôi cũng muốn có thể dễ dàng làm việc với một tập hợp Giao dịch (ví dụ: hiển thị các giao dịch nằm trong phạm vi ngày).

Trong trường hợp sau, nếu tôi đang sử dụng, TransactionRepositorytôi có thể truy cập hiệu quả những đối tượng tôi cần mà không cần tải toàn bộ danh sách (có khả năng rất lớn). Tuy nhiên, điều này sẽ cho phép những thứ khác ngoài Tài khoản hoạt động với Giao dịch, điều đó có nghĩa là tôi đã phá vỡ khái niệm Tài khoản dưới dạng gốc tổng hợp.

Làm thế nào để mọi người xử lý loại tình huống này? Bạn có chấp nhận bộ nhớ và hiệu suất của việc tải một số lượng lớn trẻ em tiềm năng cho một gốc tổng hợp không?

Câu trả lời:


9

Tôi khuyên bạn nên cẩn thận với quy tắc "không thể tồn tại mà không có" . Điều này nói về khái niệm thành phần trong thiết kế UML / OO và có thể là một trong những cách tiếp cận được quy định để thiết kế Uẩn trong sổ xanh DDD ban đầu (không chắc về điều đó) nhưng phần lớn đã được sửa đổi kể từ đó. Nó có thể là một ý tưởng tốt hơn để xem tổng hợp của bạn từ quan điểm ranh giới nhất quán giao dịch .

Ý tưởng là không làm cho tổng hợp của bạn quá lớn, nơi bạn sẽ gặp các vấn đề về hiệu suất như vấn đề bạn chỉ ra, cũng không quá nhỏ, vì một số bất biến chắc chắn sẽ kéo dài nhiều tổng hợp - gây ra các vấn đề về khóa và đồng thời tổng hợp.

Kích thước tổng hợp phù hợp lý tưởng sẽ phù hợp với các đường viền của những gì bạn sửa đổi trong một giao dịch kinh doanh nhất định, không hơn không kém. Trong ví dụ của bạn, nếu không có nhiều bất biến tên miền trải rộng trên nhiều giao dịch tài chính, thì việc tạo Transactionmột Tập hợp gốc theo đúng nghĩa của nó có thể là giải pháp tốt nhất.


Cảm ơn bạn, tôi sẽ đọc lên ranh giới nhất quán. Tôi nghĩ rằng đề xuất của bạn về việc thực hiện Giao dịch gốc tổng hợp của riêng mình có thể là một cách tốt; như bạn nói tôi không có nhiều bất biến kéo dài qua nhiều giao dịch.
krixon

7

tl; dr - phá vỡ các quy tắc nếu bạn cần. DDD không thể giải quyết tất cả các vấn đề; trong thực tế, các ý tưởng đối tượng mà nó đưa ra là lời khuyên tốt và một khởi đầu tốt, nhưng thực sự là lựa chọn tồi cho một số vấn đề kinh doanh. Hãy coi đó là một gợi ý cho cách làm việc.


Đối với vấn đề tải tất cả trẻ em (giao dịch) với cha mẹ (tài khoản) - Có vẻ như bạn đã gặp phải vấn đề n + 1 (một cái gì đó với google) mà nhiều ORM đã giải quyết.

Bạn có thể giải quyết nó bằng cách lười tải trẻ em (giao dịch) - chỉ khi cần thiết.

Nhưng có vẻ như bạn đã biết rằng bằng cách đề cập rằng bạn có thể sử dụng một Trình lưu trữ giao dịch để giải quyết vấn đề.

Để 'che giấu' dữ liệu đó để chỉ Tài khoản mới có thể sử dụng dữ liệu đó, bạn thậm chí không cần lưu trữ dữ liệu đó ở nơi mà bất kỳ ai khác sẽ không làm thế nào để khử lưu trữ dữ liệu đó, như bảng quan hệ công khai. Bạn có thể lưu nó với 'tài liệu' tài khoản trong tài liệu DB. Dù bằng cách nào, nếu ai đó đã cố gắng hết sức họ vẫn có thể xem dữ liệu. Và 'làm việc' với nó. Và khi bạn không tìm kiếm, họ sẽ làm!

Vì vậy, bạn có thể thiết lập quyền, nhưng sau đó, bạn phải chạy 'tài khoản' như một quy trình riêng biệt.

Điều bạn thực sự nhận ra ở đây là DDD và việc sử dụng thuần túy mô hình đối tượng đôi khi sẽ đưa bạn vào một góc. Thực tế, tất nhiên, bạn không phải sử dụng 'tổng hợp' / gốc tổng hợp để hưởng lợi từ các nguyên tắc thiết kế của DDD. Đó chỉ là một thứ bạn có thể sử dụng khi gặp tình huống phù hợp với những hạn chế của nó.

Ai đó có thể nói 'không tối ưu hóa sớm'. Tuy nhiên, ở đây trong trường hợp này, bạn biết câu trả lời - sẽ có đủ giao dịch để làm hỏng một phương thức sẽ giữ tất cả chúng mãi mãi với tài khoản.

Câu trả lời thực sự là bắt đầu đứng lên SOA. Tại nơi làm việc của tôi, chúng tôi đã xem các video 'Điện toán phân tán' của Udi Dahan và mua nServiceBus (chỉ là sự lựa chọn của chúng tôi). Tạo một dịch vụ cho các tài khoản - với quy trình riêng, hàng đợi tin nhắn, truy cập vào cơ sở dữ liệu quan hệ chỉ có thể nhìn thấy và ... viola, bạn có thể mã hóa các câu lệnh SQL trong chương trình và thậm chí ném vào một vài tập lệnh giao dịch Cobol (đùa tất nhiên) nhưng nghiêm túc có nhiều mối quan tâm tách biệt hơn so với snob / Java thông minh nhất từng có thể mơ ước.

Dù sao tôi cũng khuyên bạn nên mô hình hóa nó; bạn chỉ có thể có những lợi ích của tổng hợp gốc ở đây mà không gặp vấn đề gì bằng cách coi dịch vụ là một văn bản giới hạn nhỏ.

Điều này có một nhược điểm, tất nhiên. Bạn không thể chỉ RPC (dịch vụ web, SOAP hoặc REST) ​​vào và ra khỏi các dịch vụ và giữa chúng hoặc bạn có được một antipotype được gọi là "nút thắt" do khớp nối tạm thời. Bạn phải sử dụng mô hình đảo ngược của giao tiếp, còn gọi là 'Pub-Sub', nó giống như trình xử lý sự kiện và trình tạo sự kiện, nhưng (1) giữa các quy trình (bạn có thể đặt trên các máy riêng biệt nếu chúng bị quá tải trên một).

vấn đề thực sự là bạn không muốn một dịch vụ cần lấy dữ liệu từ một dịch vụ khác để 'chặn' hoặc chờ đợi - bạn phải kích hoạt và quên tin nhắn và để một người xử lý ở nơi khác trong chương trình của bạn chọn để xử lý xong. Điều này có nghĩa là bạn phải làm logic của bạn khác nhau. nServicebus tự động hóa mô hình 'saga' để trợ giúp một số điều này, nhưng cuối cùng, bạn phải phát triển một phong cách mã hóa khác. Bạn vẫn có thể làm tất cả, chỉ cần làm khác đi!

Cuốn sách "Các mô hình SOA" của Arnon Rotem-Gal-Oz trả lời nhiều câu hỏi về điều này. Bao gồm việc sử dụng 'mẫu dịch vụ hoạt động' để sao chép định kỳ dữ liệu từ các dịch vụ bên ngoài sang nhu cầu của bạn khi có nhu cầu (sẽ cần nhiều RPC hoặc liên kết không đáng tin cậy / không có trong hệ sinh thái xuất bản / đăng ký).

Chỉ cần xem trước, UI phải có RPC vào các dịch vụ. Báo cáo được tạo từ cơ sở dữ liệu báo cáo được cung cấp bởi cơ sở dữ liệu của dịch vụ. Một số người nói rằng các báo cáo là không cần thiết và vấn đề cần được giải quyết theo cách khác. Hãy hoài nghi về cuộc nói chuyện đó.

Cuối cùng, không phải tất cả mọi thứ đều có thể được phân loại thành một dịch vụ duy nhất. Thế giới không chạy theo mã ravioli! Vì vậy, bạn sẽ phải phá vỡ các quy tắc. Ngay cả khi bạn sẽ không bao giờ phải làm, các nhà phát triển mới của dự án sẽ làm điều đó khi bạn rời khỏi nó. Nhưng đừng lo lắng, nếu bạn làm những gì bạn có thể, 85% tuân theo các quy tắc sẽ làm cho một chương trình có thể duy trì hơn nhiều.

Wow, đã lâu rồi.


Cảm ơn đã trả lời chi tiết, tôi chắc chắn sẽ đọc một số thông tin về SOA.
krixon
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.