Với tất cả các dịch vụ này, làm thế nào tôi không bị thiếu máu?


90

Chúng ta vẽ ranh giới giữa ủy quyền và đóng gói logic kinh doanh ở đâu? Dường như với tôi rằng chúng ta càng ủy thác, chúng ta càng trở nên thiếu máu . Tuy nhiên, phái đoàn cũng khuyến khích tái sử dụng và hiệu trưởng DRY. Vì vậy, những gì là phù hợp để ủy quyền và những gì nên còn lại trong các mô hình miền của chúng tôi?

Lấy các mối quan tâm sau đây làm ví dụ:

Ủy quyền . Đối tượng miền có nên chịu trách nhiệm duy trì các quy tắc kiểm soát truy cập của mình (chẳng hạn như thuộc tính CanEdit) hoặc nên được ủy quyền cho một thành phần / dịch vụ khác chịu trách nhiệm quản lý quyền truy cập, ví dụ: IAuthorizationService.CanEdit (object)? Hay nó nên là sự kết hợp của cả hai? Có lẽ đối tượng miền có thuộc tính CanEdit ủy quyền cho một IAuthorizationService nội bộ để thực hiện công việc thực tế?

Xác nhận . Các cuộc thảo luận tương tự như trên liên quan đến xác nhận. Ai duy trì các quy tắc và ai chịu trách nhiệm đánh giá chúng? Một mặt, trạng thái của đối tượng phải thuộc về đối tượng đó và tính hợp lệ là trạng thái nhưng chúng tôi không muốn viết lại mã được sử dụng để đánh giá các quy tắc cho mọi đối tượng miền. Chúng ta có thể sử dụng tính kế thừa trong trường hợp này ...

Tạo đối tượng . Lớp nhà máy so với phương thức nhà máy so với 'mới' lên một ví dụ. Nếu chúng ta sử dụng một lớp nhà máy riêng biệt, chúng ta có thể cô lập và đóng gói logic tạo nhưng với chi phí mở trạng thái đối tượng của chúng ta cho nhà máy. Điều này có thể được quản lý nếu lớp miền của chúng ta nằm trong một cụm riêng biệt bằng cách hiển thị một hàm tạo bên trong được sử dụng bởi nhà máy nhưng điều này trở thành một vấn đề nếu có nhiều mẫu tạo. Và, nếu tất cả các nhà máy đang làm là gọi đúng nhà xây dựng, thì điểm cần có của nhà máy là gì?

Các phương thức xuất xưởng trên lớp loại bỏ vấn đề mở ra trạng thái bên trong của đối tượng nhưng vì chúng là tĩnh, chúng ta không thể phá vỡ các phụ thuộc thông qua việc tiêm giao diện nhà máy như chúng ta có thể với một lớp nhà máy riêng biệt.

Kiên trì . Người ta có thể lập luận rằng nếu đối tượng miền của chúng tôi sẽ tiết lộ CanEdit trong khi ủy thác trách nhiệm thực hiện kiểm tra ủy quyền cho một bên khác (IAuthorizationService) tại sao không có phương thức Lưu trên đối tượng miền của chúng tôi cũng làm điều tương tự? Điều này sẽ cho phép chúng ta đánh giá trạng thái bên trong của đối tượng để xác định xem hoạt động có thể được thực hiện mà không phá vỡ đóng gói. Tất nhiên, nó yêu cầu rằng chúng ta tiêm phiên bản kho lưu trữ vào đối tượng miền của mình, điều này có mùi một chút đối với tôi, vì vậy chúng ta có đưa ra một sự kiện miền thay thế và cho phép một trình xử lý thực hiện thao tác bền bỉ không?

Xem tôi đang đi đâu với điều này?

Rockford Lhotka có một cuộc thảo luận tuyệt vời về lý do anh ấy đi theo lộ trình Class-in-Charge cho khung CSLA của anh ấy và tôi có một chút lịch sử với khung đó và có thể thấy ý tưởng của anh ấy về các đối tượng kinh doanh song song với các đối tượng miền theo nhiều cách. Nhưng cố gắng để trở nên gắn bó hơn với những lý tưởng DDD tốt, tôi tự hỏi khi sự hợp tác trở nên quá nhiều.

Nếu tôi kết thúc với một IAuthorizationService, IValidator, IFactory và IRep repository cho tổng hợp gốc của tôi, thì còn lại gì? Là có một phương thức Xuất bản thay đổi trạng thái của đối tượng từ Dự thảo thành Xuất bản đủ để coi lớp là một đối tượng miền không thiếu máu?

Suy nghĩ của bạn?


Câu hỏi tuyệt vời. Tôi không có câu trả lời cho bạn vì tôi hầu như luôn bị thiếu máu hoàn toàn trong thiết kế vì cùng một lý do - sử dụng / tiêu thụ / phơi bày các dịch vụ từ / đến nhiều bối cảnh khác nhau hoặc các ứng dụng khác nhau.
hromanko

Câu hỏi tuyệt vời, rất thích nhìn thấy chú, martinfowler, ericevans et al để kêu gọi về điều này. Bây giờ cho tôi đi xa và có một suy nghĩ lâu dài
Martijn Verburg

Tôi thấy mình phát triển đến một mô hình thiếu máu mọi lúc; và vì vậy tôi đang vật lộn với điều tương tự chính xác này. Câu hỏi tuyệt vời!
L-Four

Đây cũng là kinh nghiệm của tôi với DDD. Chúng tôi đang làm việc ở nơi tôi làm việc và chúng tôi luôn bị thiếu máu. Tôi trước đây (và vẫn thực sự) sử dụng Csla. Kiến trúc sư của chúng tôi không thích rằng chúng tôi bị thiếu máu, nhưng đã không thể cho tôi một câu trả lời tốt cho những gì đối tượng nên làm nếu tất cả những gì bạn chỉ ra không thể được thực hiện trong đối tượng. Vào cuối ngày, cố gắng trở thành DDD thuần túy dường như tạo ra nhiều công việc hơn giá trị của nó. Cá nhân tôi nghĩ rằng Csla và DDD hòa hợp với nhau (họ có vẻ giống nhau về hiệu trưởng), nếu bạn sẵn sàng để lại giáo điều DDD phía sau.
Andy

Dưới đây là một ví dụ về một số kỹ thuật được sử dụng khi mô hình hóa miền từ phối cảnh hành vi (không lấy dữ liệu làm trung tâm): Medium.com/@wrong.about/ Kẻ
Zapadlo

Câu trả lời:


66

Hầu hết sự nhầm lẫn dường như xoay quanh chức năng hoàn toàn không tồn tại trong mô hình miền:

  • Sự kiên trì không bao giờ nên có trong mô hình miền. Chưa bao giờ. Đó là lý do bạn dựa vào các kiểu trừu tượng, chẳng hạn như IRepositorynếu một phần của mô hình cần phải làm một cái gì đó như lấy một phần khác của mô hình và sử dụng phép nội xạ phụ thuộc hoặc một số kỹ thuật tương tự để kết nối việc thực hiện. Vì vậy, đình công mà từ hồ sơ.

  • Ủy quyền thường không phải một phần của mô hình miền của bạn, trừ khi nó thực sự là một phần của miền, ví dụ: nếu bạn đang viết phần mềm bảo mật. Các cơ chế của những người được phép thực hiện những gì trong một ứng dụng thường được xử lý ở "cạnh" của tầng doanh nghiệp / miền, các phần công khai mà các phần UI và Tích hợp thực sự được phép nói chuyện - Bộ điều khiển trong MVC, Dịch vụ hoặc chính hệ thống nhắn tin trong một SOA ... bạn sẽ có được hình ảnh.

  • Các nhà máy (và tôi cho rằng bạn có nghĩa là các nhà máy trừu tượng ở đây) không thực sự xấu trong mô hình miền nhưng chúng hầu như không cần thiết. Thông thường bạn chỉ có một nhà máy khi cơ chế bên trong của việc tạo đối tượng có thể thay đổi. Nhưng bạn chỉ có một triển khai mô hình miền, điều đó có nghĩa là sẽ chỉ có một loại nhà máy luôn gọi cùng các hàm tạo và mã khởi tạo khác.

    Bạn có thể có các nhà máy "tiện lợi" nếu muốn - các lớp đóng gói các kết hợp phổ biến của các tham số của nhà xây dựng, v.v. - nhưng nói một cách trung thực, nếu bạn có nhiều nhà máy ngồi trong mô hình miền của mình thì bạn chỉ lãng phí các dòng mã.

Vì vậy, một khi bạn xoay sở tất cả những thứ đó, điều đó chỉ để lại xác nhận. Đó là điều duy nhất khó khăn.

Xác nhận một phần của mô hình miền của bạn nhưng nó cũng là một phần của mọi thành phần khác của ứng dụng. Giao diện người dùng và cơ sở dữ liệu của bạn sẽ có các quy tắc xác thực tương tự nhưng khác nhau, dựa trên một mô hình khái niệm tương tự nhưng khác nhau. Nó không thực sự xác định liệu các đối tượng có cần phải có một Validatephương thức hay không, nhưng ngay cả khi chúng thực hiện, chúng thường sẽ ủy thác nó cho một lớp trình xác nhận (không phải giao diện - xác thực không phải là trừu tượng trong mô hình miền, nó là cơ bản).

Hãy nhớ rằng trình xác nhận vẫn là một phần kỹ thuật của mô hình; nó không cần phải được gắn vào một gốc tổng hợp vì nó không chứa bất kỳ dữ liệu hoặc trạng thái nào. Các mô hình miền là những thứ mang tính khái niệm, thường là dịch vật lý cho một hội đồng hoặc một tập hợp các hội đồng. Đừng căng thẳng về vấn đề "thiếu máu" nếu mã ủy nhiệm của bạn nằm rất gần với mô hình đối tượng; nó vẫn còn tính

Tất cả điều này thực sự xuất hiện là nếu bạn định làm DDD, bạn phải hiểu tên miền là gì . Nếu bạn vẫn đang nói về những thứ như sự kiên trì và ủy quyền thì bạn đã đi sai hướng. Miền đại diện cho trạng thái hoạt động của một hệ thống - các đối tượng và thuộc tính vật lý và khái niệm. Bất cứ điều gì không liên quan trực tiếp đến các đối tượng và bản thân các mối quan hệ đều không thuộc về mô hình miền, giai đoạn.

Theo nguyên tắc thông thường, khi xem xét liệu một thứ gì đó có thuộc mô hình miền hay không, hãy tự hỏi mình câu hỏi sau:

"Chức năng này có thể thay đổi vì lý do kỹ thuật thuần túy không?" Nói cách khác, không phải do bất kỳ thay đổi quan sát nào đối với doanh nghiệp hoặc tên miền trong thế giới thực?

Nếu câu trả lời là "có", thì nó không thuộc về mô hình miền. Nó không phải là một phần của miền.

Có một cơ hội rất tốt rằng, một ngày nào đó, bạn sẽ thay đổi cơ sở hạ tầng ủy quyền và kiên trì của mình. Do đó, chúng không phải là một phần của miền, chúng là một phần của ứng dụng. Điều này cũng áp dụng cho các thuật toán, như sắp xếp và tìm kiếm; bạn không nên chuyển và triển khai mã tìm kiếm nhị phân vào mô hình miền của mình, vì miền của bạn chỉ liên quan đến khái niệm trừu tượng của tìm kiếm, chứ không phải cách thức hoạt động.

Nếu, sau khi bạn loại bỏ tất cả những thứ không quan trọng, bạn thấy rằng mô hình miền thực sự thiếu máu , thì đó sẽ là một dấu hiệu khá tốt cho thấy DDD đơn giản là mô hình sai cho dự án của bạn.

Một số lĩnh vực thực sự thiếu máu. Các ứng dụng đánh dấu trang xã hội không thực sự có nhiều "miền" để nói đến; tất cả các đối tượng của bạn về cơ bản chỉ là dữ liệu không có chức năng. Mặt khác, một hệ thống Bán hàng và CRM có một miền khá nặng; Khi bạn tải lên một Ratethực thể thì có một kỳ vọng hợp lý rằng bạn thực sự có thể thực hiện công việc với tỷ lệ đó, chẳng hạn như áp dụng nó cho số lượng đặt hàng và tìm ra mức giảm giá khối lượng và mã khuyến mãi và tất cả những thứ thú vị đó.

Đối tượng miền mà chỉ cần giữ dữ liệu thường làm có nghĩa là bạn có một mô hình miền thiếu máu, nhưng điều đó không nhất thiết có nghĩa là bạn đã tạo ra một thiết kế xấu - nó chỉ có thể có nghĩa là miền riêng của mình là thiếu máu và rằng bạn nên sử dụng một phương pháp khác nhau.


2
Ngoài ra, @SonOfPirate, đôi khi bạn không muốn thay đổi toàn bộ mô hình bảo mật của mình; bảo mật dựa trên vai trò thường bị lỗi thời đối với bảo mật dựa trên quyền hoặc yêu cầu hoặc có thể bạn thậm chí muốn bảo mật cấp trường. Hãy tưởng tượng bạn đang cố gắng làm lại toàn bộ mô hình miền của mình nếu điều này xảy ra.
Aaronaught

1
@SonOfPirate: Có vẻ như bạn vẫn còn hơi bế tắc với mô hình "tầng kinh doanh" cũ trong đó có một "tầng giữa" về cơ bản là một lớp veneer mỏng trên lớp dữ liệu, thực hiện các quy tắc kinh doanh khác nhau và thường là các quy tắc bảo mật . Đó không phải là lớp miền. Miền là thứ mà mọi thứ khác phụ thuộc vào, nó đại diện cho các đối tượng và mối quan hệ trong thế giới thực mà hệ thống có nghĩa là quản lý.
Aaronaught

1
@ LaurentBourgault-Roy: Xin lỗi, tôi không tin bạn. Mọi công ty đều có thể nói rằng về mọi ứng dụng; Rốt cuộc, thay đổi một cơ sở dữ liệu khó khăn. Điều đó không làm cho nó trở thành một phần của miền của bạn và logic kinh doanh được kết hợp với lớp kiên trì chỉ có nghĩa là sự trừu tượng kém. Một mô hình miền là tập trung vào hành vi, đó là chính xác những gì kiên trì không phải là . Đây không phải là một chủ đề mà mọi người có thể phát minh ra định nghĩa của riêng họ; nó được phát âm khá rõ ràng trong DDD. Bạn thường không cần một mô hình miền cho CRUD hoặc các ứng dụng báo cáo, nhưng bạn cũng không nên tuyên bố rằng bạn có một mô hình khi bạn không.
Aaronaught

1
Ủy quyền hoàn toàn thuộc về lớp miền. Ai quyết định những quyền nào tồn tại? Các doanh nghiệp làm. Ai quyết định ai có thể làm gì? Các doanh nghiệp làm. Chúng tôi vừa có một yêu cầu tính năng vài tuần trước để thay đổi ủy quyền cần thiết để chỉnh sửa một đối tượng cụ thể trong hệ thống của chúng tôi. Nếu một mẫu dựa trên mẫu chính, thì cần có các đặc quyền cao hơn để chỉnh sửa (ghi đè các giá trị từ bản gốc) mẫu so với thông thường bạn cần. Logic đó thuộc về đâu nếu không thuộc miền?
Andy

1
Một loại ủy quyền khác có thể là giới hạn tài khoản của khách hàng. Những người làm dịch vụ khách hàng bình thường có thể nâng nó lên một điểm nhất định, nhưng có thể giới hạn cao hơn cần sự chấp thuận của ban quản lý. Đó là logic ủy quyền.
Andy

6

Ủy quyền. Đối tượng miền có nên chịu trách nhiệm duy trì các quy tắc kiểm soát truy cập của nó không

Không. Ủy quyền là một mối quan tâm đối với chính nó. Các lệnh không hợp lệ do thiếu quyền nên bị từ chối trước miền, càng sớm càng tốt - điều đó có nghĩa là chúng ta thậm chí sẽ muốn kiểm tra ủy quyền của một lệnh tiềm năng để xây dựng giao diện người dùng (để không thậm chí hiển thị cho người dùng tùy chọn chỉnh sửa).

Chia sẻ chiến lược ủy quyền giữa các lớp (trong UI và hơn thế nữa trong trình xử lý dịch vụ hoặc lệnh) sẽ dễ dàng hơn khi ủy quyền được thành phần tách biệt với mô hình miền.

Một phần khó khăn có thể gặp phải là ủy quyền theo ngữ cảnh, trong đó một lệnh có thể hoặc không được phép không chỉ dựa trên vai trò của người dùng mà còn cả dữ liệu / quy tắc kinh doanh.

Thẩm định. Các cuộc thảo luận tương tự như trên liên quan đến xác nhận.

Tôi cũng sẽ nói không, không phải trong miền (chủ yếu). Xác nhận xảy ra trong các bối cảnh khác nhau và các quy tắc xác nhận thường khác nhau giữa các bối cảnh. Ít khi có một ý nghĩa đơn giản, tuyệt đối về giá trị hoặc không hợp lệ khi xem xét dữ liệu được gói gọn bởi một tổng hợp.

Ngoài ra, giống như ủy quyền, chúng tôi sử dụng logic xác thực qua các lớp - trong giao diện người dùng, trong trình xử lý dịch vụ hoặc lệnh, v.v. Một lần nữa, việc sử dụng DRY với xác nhận sẽ dễ dàng hơn nếu đó là một thành phần riêng biệt. Từ một điểm thực tế, xác nhận (đặc biệt là khi sử dụng khung) yêu cầu phơi bày dữ liệu mà nếu không thì phải đóng gói và nó thường yêu cầu các thuộc tính tùy chỉnh được gắn vào các trường và thuộc tính. Tôi rất thích những thứ này ở trên các lớp khác ngoài các mô hình miền của tôi.

Tôi thà sao chép một số thuộc tính trong một vài lớp tương tự hơn là cố gắng ép các yêu cầu cho khung xác thực vào các thực thể của tôi. Điều đó chắc chắn kết thúc việc tạo ra một mớ hỗn độn của các lớp thực thể.

Tạo đối tượng. Lớp nhà máy so với phương thức nhà máy so với 'mới' lên một ví dụ.

Tôi sử dụng một lớp của cảm ứng. Trong các dự án gần đây của tôi, đây là một lệnh + xử lý để tạo một cái gì đó, tức là CreateNewAccountCommand. Một lựa chọn thay thế có thể là luôn luôn sử dụng một nhà máy (mặc dù điều đó có thể gây khó xử nếu phần còn lại của một hoạt động thực thể được phơi bày bởi một lớp dịch vụ tách biệt với lớp nhà máy).

Tuy nhiên, nói chung, tôi cố gắng linh hoạt hơn với các lựa chọn thiết kế để tạo đối tượng. newlà dễ dàng và quen thuộc nhưng không phải lúc nào cũng đủ. Tôi nghĩ rằng sử dụng phán đoán ở đây và cho phép các phần khác nhau của một hệ thống sử dụng các chiến lược khác nhau khi cần là điều quan trọng.

Kiên trì. ... tại sao không có phương thức Save trên đối tượng miền của chúng tôi

Điều này hiếm khi là một ý tưởng tốt; Tôi nghĩ rằng có rất nhiều kinh nghiệm được chia sẻ để hỗ trợ điều đó.

Nếu tôi kết thúc với một IAuthorizationService, IValidator, IFactory và IRep repository cho tổng hợp gốc của tôi, thì còn lại gì? Là có một phương thức Xuất bản thay đổi trạng thái của đối tượng từ Dự thảo thành Xuất bản đủ để coi lớp là một đối tượng miền không thiếu máu ???

Có lẽ một mô hình miền không phải là lựa chọn chính xác cho phần này trong ứng dụng của bạn.


2
"Một phần khó khăn có thể gặp phải là ủy quyền theo ngữ cảnh, trong đó một lệnh có thể hoặc không được phép không chỉ dựa trên vai trò của người dùng mà còn cả dữ liệu / quy tắc kinh doanh." - Và làm thế nào để bạn tiếp cận điều này? Nhiều lần hơn không, đối với tôi, ít nhất, các quy tắc ủy quyền của chúng tôi là sự kết hợp giữa vai trò và trạng thái hiện tại.
SonOfPirate

@SonOfPirate: trình xử lý sự kiện lắng nghe các sự kiện miền và cập nhật các bảng rất cụ thể cho các nhu cầu của các truy vấn kiểm tra ủy quyền. Logic xem xét trạng thái và xác định xem vai trò hoặc cá nhân có được ủy quyền hay không tồn tại trong trình xử lý sự kiện (vì vậy các bảng hầu như luôn luôn là có / không đơn giản, làm cho việc kiểm tra xác thực đơn giản là tra cứu đơn giản). Ngoài ra, ngay khi bất kỳ logic nào được sử dụng ở nhiều nơi, nó sẽ được tái cấu trúc ra khỏi trình xử lý và vào một dịch vụ chia sẻ.
quentin-starin

1
Nói chung, trong vài năm qua, tôi đã tiến xa hơn và cố gắng hợp nhất mọi thứ thành một đối tượng kinh doanh hoặc tên miền. Kinh nghiệm của tôi dường như là làm cho mọi thứ trở nên chi tiết hơn và ít kết nối hơn là một chiến thắng lâu dài. Vì vậy, trong một khía cạnh, phương pháp này đặt logic kinh doanh bên ngoài miền (ở một mức độ), nó cũng hỗ trợ sửa đổi nhanh sau này. Đó là tất cả về nổi bật một sự cân bằng.
quentin-starin

4
Tham khảo câu trả lời tại đây: Tôi đã thấy Mẫu trạng thái rất hữu ích khi xử lý các xác nhận phụ thuộc vào cả quyền và quy tắc kinh doanh. Tạo một trạng thái trừu tượng được đưa vào mô hình miền và hiển thị các phương thức lấy đối tượng miền làm tham số và xác thực các hành động cụ thể của miền. Bằng cách này nếu quy tắc cấp phép của bạn thay đổi (vì hầu như chúng luôn luôn làm như vậy), bạn không bao giờ phải loay hoay với mô hình để điều chỉnh nó, bởi vì các cài đặt trạng thái nằm trong thành phần bảo mật của bạn.
Aaronaught

1
Tiếp tục với chủ đề ủy quyền, hãy để tôi ném một ví dụ hữu hình lên bàn để xem bạn (cả hai) sẽ xử lý nó như thế nào. Tôi có một hoạt động Xuất bản trên đối tượng miền của mình yêu cầu người dùng ở vai trò Nhà xuất bản VÀ đối tượng đó ở trạng thái nhất định. Tôi muốn ẩn hoặc tắt nút "Xuất bản" trong giao diện người dùng. Làm thế nào bạn sẽ thực hiện điều này?
SonOfPirate

4

OK, ở đây đi cho tôi. Tôi sẽ giải quyết điều này bằng cách nói rằng:

  • Tối ưu hóa sớm (và bao gồm thiết kế) thường có thể gây ra vấn đề.

  • IANMF (Tôi không phải Martin Fowler);)

  • Một bí mật nhỏ dơ bẩn là trên các dự án có quy mô nhỏ (thậm chí là những dự án có kích thước trung bình), sự nhất quán trong cách tiếp cận của bạn sẽ có vấn đề.

Ủy quyền

Đối với tôi Xác thực và Ủy quyền luôn là mối quan tâm xuyên suốt. Trong thế giới Java nhỏ bé hạnh phúc của tôi, điều đó được ủy thác cho bảo mật Spring hoặc khung công tác Apache Shiro.

Xác nhận Đối với tôi xác nhận là một phần của đối tượng, vì tôi thấy nó là định nghĩa đối tượng là gì.

ví dụ: Một đối tượng Xe hơi có 4 bánh xe (OK có một số trường hợp ngoại lệ kỳ lạ, nhưng bây giờ chúng ta hãy bỏ qua Xe 3 bánh kỳ lạ). Một chiếc xe đơn giản là không hợp lệ trừ khi nó có 4 (trong thế giới của tôi), vì vậy việc xác nhận là một phần của định nghĩa của Xe là gì. Điều đó không có nghĩa là bạn không thể có các lớp xác nhận người trợ giúp.

Trong thế giới Java hạnh phúc của tôi, tôi sử dụng các khung xác thực Bean và sử dụng các chú thích đơn giản trên hầu hết các trường Bean của tôi. Sau đó, thật dễ dàng để xác thực đối tượng của bạn cho dù bạn đang ở lớp nào.

Tạo đối tượng

Tôi xem các lớp Factory một cách thận trọng. Quá thường xuyên tôi đã thấy xyxFactoryFactorylớp học;)

Tôi có xu hướng chỉ tạo một newđối tượng khi cần thiết, cho đến khi tôi gặp phải trường hợp Dependency Injection được bảo hành (và vì tôi cố gắng làm theo phương pháp TDD, điều này xảy ra thường xuyên hơn không).

Trong thế giới Java hạnh phúc của tôi ngày càng Guice, nhưng của Spring vẫn là Vua ở đây.

Kiên trì

Vì vậy, đây là một cuộc tranh luận diễn ra trong vòng tròn và vòng xuyến và tôi luôn có hai suy nghĩ về nó.

Một số người nói rằng nếu bạn nhìn vào vật thể theo cách 'thuần khiết', sự kiên trì không phải là một tài sản cốt lõi, nó chỉ là mối quan tâm bên ngoài.

Những người khác cho rằng các đối tượng miền của bạn hoàn toàn thực hiện giao diện 'có khả năng duy trì' (vâng tôi biết tôi đang trải dài ở đây). Vì vậy, thật tốt khi có các phương pháp khác nhau save, deletev.v. Đây được xem là một cách tiếp cận thực dụng và nhiều công nghệ ORM (JPA trong thế giới Java hạnh phúc của tôi) đối phó với các đối tượng theo cách này.

Từ mối quan tâm bảo mật xuyên suốt, tôi đảm bảo rằng chỉnh sửa / xóa / thêm / bất kỳ quyền nào được đặt chính xác trên dịch vụ gọi phương thức lưu / cập nhật / xóa trên đối tượng. Nếu tôi thực sự hoang tưởng, tôi thậm chí có thể đặt quyền trên chính đối tượng miền.

HTH!


2

Jimmy Nilsson chạm vào chủ đề này trong cuốn sách về DDD. Ông bắt đầu với một mô hình thiếu máu, đi đến các mô hình không thiếu máu trong một dự án sau đó và cuối cùng giải quyết trên các mô hình thiếu máu. Lý do của ông là các mô hình thiếu máu có thể được sử dụng lại trong nhiều dịch vụ với logic kinh doanh khác nhau.

Sự đánh đổi là thiếu khả năng khám phá. Các phương pháp bạn có thể sử dụng để vận hành trên các mô hình thiếu máu của mình được trải đều trên một tập hợp các dịch vụ được đặt ở nơi khác.


Âm thanh giống như một yêu cầu cụ thể - tái sử dụng cấu trúc dữ liệu (ứng suất 'dữ liệu') - dẫn đến phần chung đó được giảm xuống thành các DTO đơn giản.
Victor Sergienko

Mô hình thiếu máu cho phép tái sử dụng tốt hơn? Nghe giống như một DTO, và cá nhân tôi không cho rằng việc sử dụng lại các định nghĩa tài sản. Tôi muốn sử dụng lại nhiều hơn các hành vi.
Andy

@Andy - Tuy nhiên, tôi sẽ đồng ý nếu các hành vi của bạn nằm trong Dịch vụ Miền và chúng hoạt động trên các đối tượng thiếu máu (DTOs nếu bạn muốn) thì điều đó có làm tăng việc tái sử dụng các hành vi đó không? Chỉ chơi người ủng hộ của quỷ.
jpierson

@jpierson Tôi đã tìm thấy mặc dù các hành vi thường cụ thể cho một trường hợp sử dụng cụ thể. Nếu có sử dụng lại, nó sẽ thuộc về một lớp khác, nhưng người tiêu dùng sẽ không sử dụng các lớp đó, họ sẽ sử dụng các lớp cụ thể cho trường hợp sử dụng. Vì vậy, bất kỳ tái sử dụng là "đằng sau hậu trường", để nói. Ngoài ra, việc cố gắng sử dụng lại các mô hình thường khiến người tiêu dùng khó sử dụng hơn, vì vậy cuối cùng bạn sẽ tạo các mô hình xem / chỉnh sửa trong lớp UI. Thường thì sau đó bạn sẽ vi phạm DRY để cung cấp trải nghiệm người dùng phong phú hơn (ví dụ: DataAnnotations của các mô hình chỉnh sửa).
Andy

1
Tôi muốn các modles miền được xây dựng cho trường hợp sử dụng, được sử dụng lại theo ý nghĩa (nghĩa là có thể sử dụng lại mà không cần sửa đổi hành vi nhiều hay ít). Vì vậy, thay vì mô hình miền thiếu máu, lớp dịch vụ và mô hình chỉnh sửa, bạn có một mô hình miền có thể chỉnh sửa thông minh duy nhất. Dễ dàng hơn nhiều để sử dụng và bảo trì, tôi đã tìm thấy.
Andy

2

Câu hỏi này đã được hỏi từ lâu, nhưng nó được gắn thẻ với Thiết kế hướng miền. Tôi nghĩ rằng bản thân câu hỏi chứa một sự hiểu lầm cơ bản về toàn bộ thực tiễn và các câu trả lời, bao gồm cả câu trả lời được chấp nhận, duy trì một sự hiểu lầm cơ bản.

Không có "mô hình miền" trong kiến ​​trúc DDD.

Hãy lấy ủy quyền làm ví dụ. Hãy để tôi yêu cầu bạn suy nghĩ về một câu hỏi: hãy tưởng tượng hai người dùng khác nhau xác thực với hệ thống của bạn. Một người dùng có quyền thay đổi một Thực thể nhất định, nhưng người dùng khác thì không. Tại sao không?

Tôi ghét những ví dụ đơn giản và dễ hiểu bởi vì chúng thường gây nhầm lẫn nhiều hơn là chúng khai sáng. Nhưng hãy giả vờ rằng chúng ta có hai miền khác nhau. Đầu tiên là một nền tảng CMS cho một cơ quan tiếp thị. Cơ quan này có nhiều khách hàng rằng tất cả đều có nội dung trực tuyến cần được quản lý bởi các tác giả sao chép và họa sĩ đồ họa. Nội dung bao gồm các bài đăng trên blog cũng như các trang đích cho các khách hàng khác nhau.

Các lĩnh vực khác là quản lý hàng tồn kho cho một công ty giày. Hệ thống quản lý hàng tồn kho từ khi nó đến từ nhà sản xuất ở Pháp, đến các trung tâm phân phối ở lục địa Hoa Kỳ, đến các cửa hàng bán lẻ ở thị trường địa phương và cuối cùng là khách hàng mua giày tại cửa hàng bán lẻ.

Nếu bạn nghĩ rằng các quy tắc Ủy quyền là giống nhau cho cả hai công ty, thì có, đó sẽ là một ứng cử viên tốt cho dịch vụ bên ngoài miền. Nhưng tôi nghi ngờ rằng các quy tắc ủy quyền là như nhau. Ngay cả các khái niệm đằng sau người dùng sẽ khác nhau. Chắc chắn ngôn ngữ sẽ khác. Cơ quan tiếp thị có thể có các vai trò như tác giả bài đăng và chủ sở hữu tài sản, trong khi công ty giày có thể có các vai trò như nhân viên giao hàng hoặc quản lý kho hoặc quản lý cửa hàng.

Các khái niệm này có thể có tất cả các loại quy tắc cấp phép liên quan đến chúng cần được mô hình hóa trong miền. Nhưng điều đó không có nghĩa là tất cả chúng đều là một phần của cùng một mô hình ngay cả trong cùng một ứng dụng. Bởi vì hãy nhớ rằng có những bối cảnh giới hạn khác nhau.

Vì vậy, có lẽ người ta có thể coi một mô hình miền không thiếu máu trong bối cảnh Ủy quyền khác với bối cảnh định tuyến các lô hàng giày đến các cửa hàng có lượng hàng tồn kho thấp hoặc định tuyến khách truy cập đến trang đích phù hợp tùy thuộc vào quảng cáo họ đã nhấp.

Nếu bạn thấy mình có các mô hình miền thiếu máu, có lẽ bạn chỉ cần dành nhiều thời gian hơn cho việc lập bản đồ ngữ cảnh trước khi bạn bắt đầu viết mã.

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.