2011-01-16 40 views
13

Chúng tôi đang xem xét các mẫu ứng dụng web (Java) dài của chúng tôi. Trong quá khứ, chúng ta đã phải chịu đựng một mô hình đối tượng quá thiếu máu và cách ly quá mức giữa các bộ điều khiển, dịch vụ và DAO, với các đối tượng giá trị đơn giản (về cơ bản chỉ là các túi dữ liệu) di chuyển giữa chúng. Chúng tôi đã sử dụng ORM được khai báo (XML) được quản lý (Hibernate) cho sự kiên trì. Tất cả quản lý thực thể đã diễn ra trong DAO.DDD: Nơi đặt logic bền bỉ và khi nào thì sử dụng ánh xạ ORM

Khi cố gắng chuyển sang mô hình miền phong phú hơn, chúng tôi thấy mình đang vật lộn với cách tốt nhất để thiết kế lớp kiên trì. Tôi đã dành rất nhiều thời gian đọc và suy nghĩ về các mẫu Thiết kế điều khiển miền. Tuy nhiên, tôi muốn một số lời khuyên.

Thứ nhất, những điều tôi tự tin thêm về:

  • Chúng tôi sẽ có bộ điều khiển "mỏng" ở phía trước mà chỉ đối phó với HTTP và HTML - các hình thức xử lý, xác nhận, UI logic.

  • Chúng tôi sẽ có một lớp dịch vụ logic nghiệp vụ phi trạng thái thực hiện các thuật toán hoặc logic phổ biến, không biết về giao diện người dùng, nhưng rất ý thức (và ủy quyền) mô hình miền.

  • Chúng tôi sẽ có mô hình tên miền phong phú hơn chứa trạng thái, mối quan hệ và logic vốn có cho các đối tượng trong mô hình miền đó.

Câu hỏi đặt ra xung quanh sự kiên trì. Trước đây, các dịch vụ của chúng tôi sẽ được tiêm (thông qua Spring) với DAO, và sẽ sử dụng các phương thức DAO như find() và save() để thực hiện sự kiên trì. Tuy nhiên, một mô hình miền phong phú hơn dường như ngụ ý rằng các đối tượng nên biết cách lưu và xóa bản thân, và có lẽ các dịch vụ cấp cao hơn nên biết cách định vị các đối tượng miền (truy vấn).

Ở đây, một số câu hỏi và những bất ổn phát sinh:

  • Chúng ta muốn tiêm DAO thành các đối tượng miền, do đó họ có thể làm "this.someDao.save (this)" trong một tiết kiệm() phương pháp? Đây là một chút khó xử vì các đối tượng miền không phải là các trình đơn, vì vậy chúng tôi sẽ cần các nhà máy hoặc thiết lập sau xây dựng của DAO. Khi tải các thực thể từ một cơ sở dữ liệu, điều này trở nên lộn xộn. Tôi biết mùa xuân AOP có thể được sử dụng cho điều này, nhưng tôi không thể làm cho nó hoạt động (sử dụng Play! Framework, một dòng thử nghiệm khác) và nó có vẻ khá lộn xộn và huyền diệu.

  • Thay vào đó, chúng tôi có giữ DAO (kho lưu trữ?) Hoàn toàn riêng biệt, ngang bằng với các dịch vụ logic nghiệp vụ không quốc tịch không? Điều này có thể làm cho một số ý nghĩa, nhưng nó có nghĩa là nếu "lưu" hoặc "xóa" là các hoạt động vốn có của một đối tượng miền, đối tượng miền không thể diễn tả chúng.

  • Chúng tôi chỉ phân phối hoàn toàn với DAO và sử dụng JPA để cho phép các thực thể tự quản lý.

Đây là sự tinh tế tiếp theo: Khá thuận tiện khi ánh xạ đối tượng sử dụng JPA. Vở kịch! framework cũng cung cấp cho chúng ta một lớp cơ sở thực thể tốt, với các hoạt động như save() và delete(). Tuy nhiên, điều này có nghĩa rằng các thực thể mô hình miền của chúng tôi được gắn chặt chẽ với cấu trúc cơ sở dữ liệu và chúng ta đang truyền các đối tượng xung quanh với một lượng lớn logic tồn tại, có lẽ tất cả các con đường lên đến lớp xem. Nếu không có gì khác, điều này sẽ làm cho mô hình miền ít có thể sử dụng lại được trong các ngữ cảnh khác.Nếu chúng ta muốn tránh điều này, thì chúng ta cần một loại ánh xạ DAO - hoặc sử dụng JDBC đơn giản (hoặc ít nhất là JdbcTemplate của Spring), hoặc sử dụng một hệ thống phân cấp song song của các thực thể cơ sở dữ liệu và các thực thể "kinh doanh", với DAO mãi mãi sao chép thông tin từ một hệ thống phân cấp này sang cấu trúc phân cấp khác.

Lựa chọn thiết kế phù hợp ở đây là gì?

Martin

+3

Theo thiết kế do miền điều khiển - đối tượng miền phải kiên trì không biết gì. –

Trả lời

1

Tôi không phải là một chuyên gia về Java, nhưng tôi sử dụng NHibernate trong mã NET của tôi vì vậy kinh nghiệm của tôi nên có thể dịch trực tiếp với thế giới Java.

Khi sử dụng ORM (như Hibernate bạn đã đề cập) để xây dựng ứng dụng Thiết kế theo hướng miền, một trong những thực hành tốt (tôi sẽ không nói tốt nhất) là tạo các dịch vụ ứng dụng giữa giao diện người dùng và tên miền. Chúng tương tự như các đối tượng kinh doanh không quốc tịch mà bạn đã đề cập, nhưng hầu như không chứa logic. Họ sẽ trông như thế này:

public void SayHello(int id, String helloString) 
{ 
    SomeDomainObject target = domainObjectRepository.findById(id); //This uses Hibernate to load the object. 

    target.sayHello(helloString); //There is a single domain object method invocation per application service method. 

    domainObjectRepository.Save(target); //This one is optional. Hibernate should already know that this object needs saving because it tracks changes. 
} 

Mọi thay đổi đối tượng chứa DomainObject (cũng thêm đối tượng vào bộ sưu tập) sẽ được xử lý bởi Hibernate.

Bạn cũng sẽ cần một số loại AOP để chặn các lời gọi phương thức dịch vụ ứng dụng và tạo phiên Hibernate trước khi phương thức thực hiện và lưu thay đổi sau khi phương thức kết thúc mà không có ngoại lệ.

Có một ví dụ thực sự tốt về cách thực hiện DDD trong Java here. Nó dựa trên vấn đề mẫu của Eric Evans ''Blue Book'. Mã mẫu lớp ứng dụng logic là here.

3

Câu hỏi và nghi ngờ của bạn đổ chuông báo động thú vị ở đây, tôi nghĩ bạn đã đi quá xa trong việc diễn giải một "mô hình tên miền phong phú". Giàu có không đi xa như ngụ ý rằng logic bền bỉ phải được xử lý bởi các đối tượng miền, nói cách khác, không, họ không nên biết cách lưu và xóa chúng (ít nhất là không rõ ràng, mặc dù Hibernate thực sự thêm một số logic bền bỉ minh bạch). Điều này thường được gọi là sự thiếu hiểu biết.

Tôi khuyên bạn nên giữ hệ thống tiêm DAO hiện tại (một điều tốt đẹp để thử nghiệm đơn vị) và để lớp kiên trì như đang cố gắng di chuyển một số logic nghiệp vụ đến các thực thể của bạn nơi phù hợp với. Một điểm khởi đầu tốt để làm điều đó là để xác định Tổng hợp và thiết lập Roots tổng hợp của bạn. Chúng thường chứa nhiều logic kinh doanh hơn các thực thể khác. Tuy nhiên, điều này không có nghĩa là đối tượng miền phải chứa tất cả logic (đặc biệt không phải là logic cần thiết bởi nhiều đối tượng khác trong ứng dụng, thường nằm trong Dịch vụ).

+0

Vâng, điểm công bằng. Nhưng nhìn vào phần cuối của câu hỏi của tôi: Một cái gì đó như Hibernate/JPA làm cho nó dễ dàng hơn nhiều để đối phó với sự kiên trì. Tuy nhiên, nếu chúng ta làm điều này trên mô hình miền, thì nó có logic này được xây dựng. Nếu không, thì chúng ta sẽ cần phải bỏ qua ORM hoàn toàn, hoặc có một hệ thống phân cấp song song của các đối tượng "ánh xạ" và "miền" đối tượng và người lập bản đồ dữ liệu giữa chúng. – optilude

+0

Sử dụng JPA không có nghĩa là các đối tượng miền phải duy trì bản thân - chỉ chứa các mô tả về cách ánh xạ bản thân đến các bảng cơ sở dữ liệu và trong vấn đề này, JPA ít dè dặt hơn so với Hibernate thuần túy. – guillaume31

+0

Vì vậy, tôi không khuyên bạn nên tiêm DAO vào các đối tượng miền. Trên JPA và DDD, bạn có thể tìm thấy 2 bài đăng trên blog thú vị này: http: //debasishg.blogspot.com/2007/10/domain-modeling-with-jpa-gotchas-part-4.html http://debasishg.blogspot.com/2007/10//domain-modeling-what-exactly-is-rich.html Tôi sẽ không đi theo cách "phân cấp song song" vì nó giới thiệu sự phức tạp chưa được thực hiện so với chỉ các POJO. – guillaume31

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