2008-10-22 35 views
20

Dường như quyết định làm cho các đối tượng của bạn nhận thức đầy đủ về vai trò của chúng trong hệ thống, và vẫn tránh có quá nhiều phụ thuộc trong mô hình miền trên cơ sở dữ liệu và các tầng dịch vụ? Ví dụ: Giả sử tôi có một thực thể có lịch sử sửa đổi và một số "bảng tra cứu" mà tham chiếu dữ liệu, đối tượng thực thể của bạn phải có các phương thức để lấy chi tiết từ một số bảng tra cứu, cho dù bằng cung cấp quyền truy cập vào các hàng của bảng tra cứu hoặc bằng cách ủy quyền các phương thức cho chúng, nhưng để làm như vậy, nó phụ thuộc vào lớp cơ sở dữ liệu để đọc dữ liệu từ các hàng đó. Ngoài ra, khi thực thể được lưu, nó cần phải biết không chỉ làm thế nào để tiết kiệm chính nó, mà còn để lưu các mục vào lịch sử sửa đổi. Có cần phải chuyển các tham chiếu tới hàng tá đối tượng lớp dữ liệu khác nhau và các đối tượng dịch vụ cho đối tượng mô hình không? Điều này có vẻ như làm cho logic phức tạp hơn nhiều để hiểu hơn là chỉ chuyển qua lại các mô hình mỏng cho các đối tượng lớp dịch vụ, nhưng tôi đã nghe nhiều "người khôn ngoan" đề xuất loại cấu trúc này.Làm cách nào để tránh các Mô hình Miền Không ổn định và duy trì Tách các Mối quan tâm?

Trả lời

19

Câu hỏi thực sự hay. Tôi đã dành khá nhiều thời gian để suy nghĩ về những chủ đề như vậy.

Bạn thể hiện thông tin chi tiết tuyệt vời bằng cách ghi nhận sự căng thẳng giữa mô hình miền biểu cảm và tách mối quan tâm. Điều này giống như sự căng thẳng trong câu hỏi mà tôi đã hỏi về Tell Don't Ask and Single Responsibility Principle.

Đây là quan điểm của tôi về chủ đề.

Mô hình miền thiếu máu do không chứa logic miền. Các đối tượng khác nhận và thiết lập dữ liệu bằng cách sử dụng một đối tượng miền thiếu máu. Những gì bạn mô tả không giống như logic miền với tôi. Nó có thể là, nhưng nói chung, bảng tra cứu và ngôn ngữ kỹ thuật khác là nhiều khả năng các điều khoản có nghĩa là một cái gì đó cho chúng tôi nhưng không nhất thiết phải bất cứ điều gì cho khách hàng. Nếu điều này không chính xác, vui lòng làm rõ.

Dù sao, việc xây dựng và kiên trì các đối tượng miền không được chứa trong chính các đối tượng miền vì đó không phải là logic miền.

Vì vậy, để trả lời câu hỏi, không, bạn không nên tiêm toàn bộ các đối tượng/khái niệm không thuộc miền như bảng tra cứu và các chi tiết cơ sở hạ tầng khác. Đây là một sự rò rỉ của một mối quan tâm khác. Các mẫu Nhà máy và Kho lưu trữ từ Thiết kế theo hướng miền phù hợp nhất để giữ những mối quan tâm này ngoài chính mô hình miền. Tuy nhiên, lưu ý rằng nếu bạn không có bất kỳ logic miền nào, thì bạn sẽ kết thúc với các đối tượng miền thiếu máu, ví dụ như các túi xiềng xích và bộ định vị không có trí tuệ, là cách some shops claim to do SOA/service layers.

Vậy làm cách nào để tận dụng tối đa cả hai thế giới? Làm thế nào để bạn tập trung miền của bạn đối tượng chỉ logic miền, trong khi vẫn giữ giao diện người dùng, xây dựng, kiên trì, vv trên đường đi? Tôi khuyên bạn nên sử dụng kỹ thuật như Double Dispatch hoặc một số hình thức restricted method access.

Dưới đây là ví dụ về Công văn kép. Giả sử bạn có dòng mã này:

entity.saveIn(repository); 

Trong câu hỏi của bạn, saveIn() sẽ có tất cả các kiến ​​thức về lớp dữ liệu. Sử dụng hai công văn, saveIn() thực hiện điều này:

repository.saveEntity(this.foo, this.bar, this.baz); 

Và phương pháp saveEntity() của kho có tất cả các kiến ​​thức về làm thế nào để tiết kiệm trong lớp dữ liệu, như nó phải.

Ngoài thiết lập này, bạn có thể có:

repository.save(entity); 

mà chỉ gọi

entity.saveIn(this); 

Tôi đang đọc này và tôi nhận thấy rằng các thực thể vẫn còn mỏng vì nó chỉ đơn giản là cử sự kiên trì của nó đối với kho lưu trữ. Nhưng trong trường hợp này, thực thể được cho là mỏng vì bạn không mô tả bất kỳ logic miền nào khác. Trong tình huống này, bạn có thể nói "screw Double Dispatch, cho tôi accessors."

Và vâng, bạn có thể, nhưng IMO nó cho thấy quá nhiều về cách thực thể của bạn được thực hiện, và những người truy cập là phiền nhiễu từ logic miền. Tôi nghĩ rằng lớp duy nhất cần phải có và bộ là một lớp có tên kết thúc bằng "Accessor".

Tôi sẽ kết thúc việc này sớm. Cá nhân, tôi không viết các thực thể của mình với các phương thức saveIn(), bởi vì tôi nghĩ rằng thậm chí chỉ có một phương thức saveIn() có xu hướng phân tán đối tượng miền với sự xao lãng. Tôi sử dụng mẫu lớp bạn bè, quyền truy cập gói riêng tư hoặc có thể là Builder pattern.

OK, tôi đã hoàn tất. Như tôi đã nói, tôi đã bị ám ảnh về chủ đề này khá một chút.

+2

Tóm lại, bạn đang đề xuất truy cập kho lưu trữ từ miền? – aaimnr

0

Hãy thử "mẫu kho lưu trữ" và "Thiết kế định hướng tên miền". DDD gợi ý để xác định các thực thể nhất định là Tổng hợp của các đối tượng khác. Mỗi Tổng hợp được đóng gói. Các thực thể là "kiên trì không biết gì". Tất cả các mã liên quan đến persistence được đặt trong một đối tượng kho lưu trữ để quản lý truy cập dữ liệu cho thực thể. Bằng cách này bạn không phải trộn mã liên quan đến sự kiên trì với logic nghiệp vụ của bạn. Nếu bạn quan tâm đến DDD, hãy kiểm tra cuốn sách evic evans.

+1

Nó không trả lời câu hỏi. Câu hỏi đặt ra là "Kho lưu trữ có nên được đưa vào miền" không? Nếu có, nó sẽ phá vỡ Tách mối quan tâm. Mặt khác, nếu những hành động đó sẽ được thực hiện bởi dịch vụ, nó có thể dẫn đến Mô hình miền thiếu máu. – aaimnr

1

"mô hình mỏng cho đối tượng lớp dịch vụ" là những gì bạn làm khi bạn thực sự muốn viết lớp dịch vụ.

ORM là những gì bạn làm khi bạn không muốn viết lớp dịch vụ.

Khi bạn làm việc với ORM, bạn vẫn nhận thức được thực tế là điều hướng có thể liên quan đến truy vấn nhưng bạn không ở trên đó.

Bảng tra cứu có thể là một chiếc nạng quan hệ được sử dụng khi không có mô hình đối tượng hoàn chỉnh. Thay vì những thứ liên quan đến mọi thứ, bạn có mã, mà phải được tra cứu. Trong nhiều trường hợp, các mã được phân tách thành nhiều hơn một nhóm chuỗi tĩnh với các khóa cơ sở dữ liệu. Và các phương pháp có liên quan sẽ phát ra ở những nơi kỳ lạ trong phần mềm.

Tuy nhiên, nếu có mô hình đối tượng hoàn chỉnh hơn, chúng tôi có các lớp thứ nhất thay vì các giá trị tra cứu thoái hóa này. Ví dụ: tôi có một số giao dịch kinh doanh có một trong số n "gói giá" khác nhau - một loại mô hình định giá. Ngay bây giờ, cơ sở dữ liệu quan hệ kế thừa có kế hoạch tỷ lệ như một bảng tra cứu với một mã, một số số định giá và (đôi khi) một mô tả.

[Mọi người đều biết mã - mã số là thiêng liêng. Không ai chắc chắn những gì mô tả thích hợp nên được. Nhưng họ biết mã số.]

Nhưng thực sự, "kế hoạch tỷ lệ" là một đối tượng được liên kết với hợp đồng; kế hoạch tỷ lệ có phương pháp tính giá cuối cùng. Khi một ứng dụng yêu cầu hợp đồng cho một mức giá, hợp đồng ủy nhiệm một số công việc định giá cho đối tượng kế hoạch tỷ lệ liên quan.

Có thể có một số truy vấn cơ sở dữ liệu đang diễn ra để tra cứu kế hoạch tỷ lệ khi tạo ra giá hợp đồng, nhưng điều đó ngẫu nhiên với trách nhiệm của hai nhóm.

1

Tôi bực mình với DeadBeef - trong đó có sự căng thẳng. Tôi không thực sự thấy mặc dù mô hình miền là 'thiếu máu' đơn giản chỉ vì nó không tự lưu.

Phải có nhiều hơn thế nữa. I E. Đó là thiếu máu do dịch vụ đang thực hiện tất cả các quy tắc kinh doanh chứ không phải thực thể tên miền.

Service(IRepository) injected 

Save(){ 

DomainEntity.DoSomething(); 
Repository.Save(DomainEntity); 

} 

'Do Something' is the business logic of the domain entity. 

**This would be anemic**: 
Service(IRepository) injected 

Save(){ 

if(DomainEntity.IsSomething) 
    DomainEntity.SetItProperty(); 
Repository.Save(DomainEntity); 

} 

Xem sự khác biệt kế thừa? Tôi làm :)

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