2013-07-22 69 views
2

什麼是將域對象/實體與持久層組合的乾淨方式沒有 ORM框架支持?具有乾淨持久層的域類/實體(DAO,工廠,...)

我有域類/實體zcl_documentzcl_document_request(1:n)。我希望域類僅包含核心域邏輯,基礎設施,沒有「助手」,沒有持久性/加載機制。

正在ABAP,我已經定義爲暴露作爲公共只讀屬性data每個實體「乾淨」 structureszs_documentzs_docreq(我們在ABAP畢竟)。通過這種方式,我不需要一堆實體上的getter,並最小化核心域邏輯的方法。

爲了得到一個薄持久性層,我已經定義DAO其中γ-接口readsavefind_by_x爲每個數據庫表(包括可選的文本表和內容)。它們的返回類型始終是structure或結構表,而不是實體對象本身。所以我有一個可測試/可替換的薄持久層。這個持久層現在也可用於大量數據處理的報告中,因爲我不需要創建對象實例或對象圖,我可以使用(希望清理)結構。

要實例化實體,通常每個實體都有一個公共靜態的create(工廠)方法,它採用「乾淨」結構,驗證並生成其實例。與其他對象具有基本關聯的實體更難於create,因爲也必須創建相關對象。這些實體獲得他們自己的zcl_document_request_manager(承擔命名)。經理知道如何create(工廠)和save該實體,包括所有關聯的對象。因此它也是實體的一個friend

工廠是唯一知道DAO的地方,讓實體自己保持清潔的基礎設施/持久性的東西。加載是急切地完成的,我不知道如何在實體中沒有太多的基礎設施管理代碼的情況下創建透明的延遲加載。

使用它看起來像下面這樣:

create object lo_docreq_mng exporting dao, dao, dao, dao,... 

lt_docreq = docreq_dao->find_by_x(...) // table of structure 

foreach lt_docreq as ls_docreq // structure 
    lo_docreq = lo_docreq_mng=>create(ls_docreq) // factory => instance 

    lo_doc = lo_docreq->get_document() // was created with document-instance 

    lo_docreq->do_something_mutating().  
    lo_docreq_mng->save(lo_docreq) // save including dependent objects 

這是可行的或者是有一些氣味? 任何評論贊賞。

+0

在我瞭解您的請求的情況下,在ABAP中不使用現有的ORM的原因是什麼?已經涵蓋了您需要的大部分內容? – vwegert

+0

我認爲持久化類很醜,並且會產生大量get/set。我不想擁有強烈持久性的類。相反,如果可能的話,我希望獲得具有薄持久層的稍微乾淨的域類... – hotzen

+0

「我認爲持久類很醜陋」 - 我不這麼認爲,那將是它的結束除非你有一些嚴重的問題:-) – vwegert

回答

2

我喜歡你的方法。我會改變一些事情:

1),讓您的域的用戶對象乾淨的建築代碼,你可以提供一個docreq級返回實體的列表,而不是結構:

lt_doc = doc_qry->find_by_x(...) // table of entities 
foreach lt_doc as lo_doc 
    lo_doc->do_something_mutating().  
    lo_doc_mng->save(lo_doc) // save including dependent objects 

的用法不太容易出錯,並闡明瞭代碼中的業務邏輯。而且由於希望您的實體經常被使用,您可以簡化其他開發人員的使用。

2)也許你也可以擺脫save-Method。爲什麼你必須明確調用save?根據我的經驗,將保存或放棄某些內容的決定放置到正在運行的事務(頂級報告或正在運行的UI)的控制器中。但不應將其放入某種業務或服務方法/功能中。

3)我不會去靜態方法。首先,他們很容易實現,而且也爲以後的變化,他們可能會成爲地獄

,並就有關使用ORM的討論:我不會混淆持久層和業務邏輯,因爲它降低了可測試性。僅將ABAP-ORM用作持久層並沒有太大的好處。爲什麼在類中包裝數據並將其用作簡單的abap結構(在大多數情況下)?另一方面它缺乏一個很好的DQL。

0

我知道這是一個老問題,但在我最近的項目中,我一直在試圖爲這個相同的問題提出一個很好的解決方案。

我一般同意你的方法,並遵循一個非常類似於你的方法,除非我沒有定義任何DAO類型的對象。大多數情況下,我不只是定義一個管理員類,而是定義兩個獨立的類:一個用於管理數據庫檢索/保存的存儲庫和一個用於創建新的有效實例的工廠。這只是爲了不違反SRP(另外,我傾向於將它們定義爲接口)。這也與編寫單元測試一起玩得很好。

正如你已經提到的那樣,最大的問題是急切地加載關係,一旦開始處理大量數據,關係就會迅速爆炸。解決方案可能是存儲庫應該知道每個實體的唯一標識符(即數據庫中的主鍵),並且只能在實例化時獲得這些標識符,但實際上我還沒有實現它。

+0

今天我將放棄建模作爲ABAP中的普通對象,而是使用BOPF的服務層方法。儘管它的API /接口非常通用,非常技術性且有些醜陋,但它比自己構建持久性以及與事務,高性能緩衝,急切/懶惰加載和批量操作作鬥爭具有巨大的優勢 – hotzen

+0

感謝您的答覆。 BOPF目前不是我所熟悉的,但從它的聲音來看,這是值得研究的。 –