逻辑建模与物理建模_架构层和建模域逻辑
邏輯建模與物理建模
在討論用于建模域邏輯(例如事務腳本,表模塊,域模型)的PoEAA模式時,我注意到人們對域模型模式是最好的印象(盡管印象不對)。 因此,他們開始將其應用于所有內容。
不配領域模型模式
讓我們成為現實。 大多數子系統都是基于CRUD的。 系統的僅特定部分需要域模型實現模式。 或者,換句話說,應用程序的某些部分僅需要數據上的表格和一些驗證邏輯(例如,必填/必填字段,數字的最小/最大值,文本的最小/最大長度)。 對于這些,領域模型是不值得的。
對于這些,也許貧血領域模型會很好地適合。
貧血領域模型并不像聽起來那樣糟糕
貧血領域模型并不像聽起來那樣糟糕。 在那兒,我說了(至少在我的博客文章中如此)。
但是看起來怎么樣?
package com.acme.bc.domain.model; ... @Entity class Person {@Id ... private Long id;private String firstName;private String lastName;// ...// getters and setters } ... interface PersonRepository /* extends CrudRepository<Person, Long> */ {// CRUD methods (e.g. find, find/pagination, update, delete) }package com.acme.bc.infrastructure.persistence; ... class PersonRepositoryJpa implements PersonRepository {... }
在表示層中,控制器可以訪問存儲庫。 該存儲庫負責提取持久性詳細信息。
package com.acme.bc.interfaces.web;@Controller class PersonsController {private PersonRepository personRepository;public PersonsController(PersonRepository personRepository) {...}// ... }在這種情況下,將Person類暴露給表示層是完全可以的。 表示層可以直接使用它,因為它具有一個公共的零參數構造函數,獲取器和設置器,而視圖很可能需要這些構造器。
那里有。 一個簡單的基于CRUD的應用程序。
您還需要服務層嗎? 否。您還需要DTO (數據傳輸對象)嗎? 不需要。在這種簡單的CRUD情況下,您不需要其他服務或DTO 。
是的,此Person看起來像域實體。 不過,這并不包含邏輯,并且只是用來傳輸數據。 因此,它實際上只是一個DTO。 但這沒關系,因為它可以完成保存持久性存儲和檢索的數據的工作。
現在, 如果業務邏輯開始變得更加復雜,則最初貧乏的領域模型中的某些實體可能會變得更加富有行為。 如果是這樣的話,這些實體可以值得一個領域模型模式。
貧血領域模型的替代品
作為貧血領域模型(如上所述)的替代方法,可以將這些類移出領域邏輯層并移入表示層。 而不是命名
PersonRepository ,現在命名為
PersonDao 。
package com.acme.bc.interfaces.web;@Entity class Person {...}@Controller class PersonsController {private PersonDao personDao;public PersonsController(PersonDao personDao) {...}// ... }interface PersonDao /* extends CrudRepository<Person, Long> */ {// CRUD methods (e.g. find, find/pagination, update, delete) }package com.acme.bc.infrastructure.persistence;class PersonDaoJpa implements PersonDao {... }
太多分層
我認為,如果您必須通過不增加價值的強制性應用程序服務,那將是一個過大的殺傷力。
package com.acme.bc.interfaces.web; ... @Controller class PersonsController {private PersonService personService;public PersonsController(PersonService personService) {...}// ... }package com.acme.bc.application; ... @Service class PersonService {private PersonRepository personRepository;public PersonService(PersonRepository personRepository) {...}// expose repository CRUD methods and pass to repository// no value add }將存儲庫保留在domain.model包中。 將存儲庫實現放置在另一個包中(例如, infrastructure.persistence )。 但為什么?
domain.model包是定義存儲庫的位置。 域模型中的元素指示存儲庫接口定義中需要哪些方法。 因此,存儲庫定義放置在domain.model包中。 存儲庫實現需要遵循添加的新方法(或刪除未使用的方法)。 此包裝遵循依賴關系反轉原理。 infrastructure.persistence程序包取決于domain.model程序包,而不是相反。
交易申請服務
那么,什么時候應用服務合適? 應用程序服務負責驅動工作流程和協調事務管理(例如,通過使用Spring中的聲明性事務管理支持)。
如果您發現簡單的CRUD應用程序需要在表示層控制器中啟動事務,那么將它們移至應用程序服務中可能是一個好兆頭。 當控制器需要更新多個不具有單個根的實體時,通常會發生這種情況。 這里通常的示例是在銀行帳戶之間轉移金額。 需要進行交易以確保借方和貸??方都成功或都失敗。
package sample.domain.model; ... @Entity class Account {...} ... interface AccountRepository {...}package sample.interfaces.web; ... @Controller class AccountsController {private AccountRepository accountRepository;...@Transactionalpublic ... transfer(...) {...} }
如果看到了這一點,那么最好將其(從表示層)移至應用程序層服務。
package sample.interfaces.web; ... @Controller class AccountsController {private AccountRepository accountRepository;private TransferService transferService;...public ... transfer(...) {...} }package sample.application; ... @Service @Transactional class TransferService {private AccountRepository accountRepository;...public ... transfer(...) {...} }package sample.domain.model; ... @Entity class Account {...} ... interface AccountRepository {...}復雜邏輯的域模型模式(僅)
我將以重復輸入記帳為例。 但我敢肯定,還有更適合的復雜邏輯。
假設我們將日記帳分錄和科目建模為域實體。 該帳戶包含余額(金額)。 但這并不是一個簡單的設定。 需要創建日記帳分錄。 過帳日記帳分錄時,它將影響指定的帳戶。 然后,該帳戶將更新其余額。
package ….accounting.domain.model; ... /** Immutable */ @Entity class JournalEntry {// zero-sum items@ElementCollectionprivate Collection<JournalEntryItem> items;... } ... /** A value object */ @Embeddable class JournalEntryItem {...} ... interface JournalEntryRepository {...} ... @Entity class Account {...} ... interface AccountRepository {...} ... @Entity class AccountTransaction {...} ... interface AccountTransactionRepository {...}現在,在這種情況下,一個簡單的實現將有一個表示層控制器創建一個日記帳分錄對象,并使用一個存儲庫來保存它。 并且在某個時間點(或如果使用自動過賬),將創建相應的帳戶交易,并更新帳戶余額。 所有這些都需要匯總成一個事務(即全有或全無)。
同樣,此事務理想地移至應用程序服務。
package ….accounting.application;@Service @Transactional class PostingService {...}如果需要允許用戶瀏覽日記帳分錄和帳戶交易,則表示層控制器可以直接使用相應的存儲庫。 如果域實體不適合于視圖技術(例如,它不遵循JavaBean命名約定),則表示層可以定義適合于視圖的DTO。 小心! 不要僅僅為了滿足表示層的需求而更改域實體。
package ….interfaces.web;@Controller class AccountsController {private AccountRepository accountRepository;private AccountTransactionRepository accountTransactionRepository;private PostingService postingService;... }即將結束...
所以你有它。 希望這篇文章可以闡明何時(以及何時不)使用域模型模式。
現在我想我要感冒了。
翻譯自: https://www.javacodegeeks.com/2016/10/architectural-layers-modeling-domain-logic.html
邏輯建模與物理建模
總結
以上是生活随笔為你收集整理的逻辑建模与物理建模_架构层和建模域逻辑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【IT之家开箱】华为 Mate 60 R
- 下一篇: 华为Mate60 RS非凡大师配置公布!