-設計原則和設計模式,互聯網開發者們共同的追求程序員
多年來,筆者一直從事傳統軟件企業的軟件開發和項目管理工做。筆者發如今衆多的傳統軟件企業中,評判優秀開發者的標準每每是技能的熟練程度,基本上都是以梭代碼的速度論英雄。有人評價說,這種開發能夠稱之爲cv編程,即ctrl+c和ctrl+v編程爲主。這種開發每每對開發者的技能要求並無想象中的那麼高,因爲工時和合同的限制,不得不壓縮開發時間,經過靠密集的勞動力資源、較高的工做強度來完成項目的開發。這種模式,經過簡單的複用歷史代碼,能夠更快的輸出結果,對於中小型企業和一些外包企業來講,也意味着更快的項目完成速度、而越快作完項目,也意味着能夠越快收回合同款,儘快開始下一個項目。數據庫
然而,也必須認可,在這種模式下,代碼的質量取決於項目管理者對於技術和代碼的把握能力,若是攤上不懂技術的項目管理者以及對於代碼質量沒有要求的研發人員,可能最終輸出的代碼,將成爲一團亂麻,只能在一個個項目中無窮次的積累,直到遇到一羣優秀的開發人員費勁心力把體系重構爲止。編程
而當今互聯網時代下,面向互聯網的應用開發,再也不追求短時間成效,更在意長期技術的沉澱,這個過程當中,也對開發者提出了更高的要求。互聯網行業的開發者,不只僅要求代碼梭得快,還在意編寫代碼編寫的質量,誰能編寫出更加優美的代碼,每每也更容易受人歡迎。因而,做爲優美代碼代名詞的SOLID設計原則和不少種設計模式實際上成爲了很是基礎的一種能力,甚至於許多資深的開發者,常常會樂此不疲的進行各類代碼的重構,也是期待可以更好的將設計模式揉碎了,應用到代碼中,更好的實現高內聚、低耦合的目標。設計模式
在著名小紅書《Head First》一書中,描述了多種設計模式,這些由資深IT技術大牛們抽象化出來的最佳代碼實踐,初讀起來也許簡單明瞭,可是細細品味起來,卻意味深長。緩存
在傳統軟件開發實踐工程中,每每會下意識的使用New關鍵字產生對象實例。經過這種方式進行代碼的編寫,當然會帶來代碼上的開發速度,可是一樣也會給對象的生成帶來一些問題。例如,對象的構造,每每附帶了許多複雜的條件:如須要進行一些初始值的設置,如須要初始化與之相關的子類,或者須要預先執行許多初始化方法,那麼就可能意味着代碼的構造中會產生一系列複雜、與主流程無關的代碼。如何讓輕鬆方便的構造代碼、而不去關心具體的實現細節呢?spa
工廠模式成爲解決問題的方案,經過工廠模式,適當的建立接口,將代碼中的具體過程進行屏蔽,從而提升了代碼的靈活性。又分爲靜態工廠、簡單工廠模式、工廠方法模式、抽象工廠模式等多種不一樣的模式。例如,咱們可能會編寫一段下面的代碼。 設計
1 public abstract class FactoryPizzaStore 2 { 3 public Pizza OrderPizza(string type) 4 { 5 6 Pizza pizza = CreatePizza(type); 7 return pizza; 8 } 9 public abstract Pizza CreatePizza(string type); 10 }
咱們能夠看到,這只是一段最普通的工廠代碼,定義了一個抽象對象,若是須要實現成員,只需繼承此對象,並重載方法,這種方法能夠很是便捷的將內部對象的建立過程進行封裝,實現了代碼內聚性的顯著提升。code
在領域驅動中,將工廠模式引入其中,讓其產生了不一樣的含義。在上一章,咱們瞭解到,隨着軟件系統複雜性的顯著提升,維護模型實例的生命週期變成了一件很是困難的事情,所以經過引入一個聚合Aggregate對象,能夠有效的將複雜的模型複雜的生命週期的各個階段進行封裝,經過一系列固定的規則,實現了對數據更加的控制。而這種控制,則是經過工廠模式和倉儲模式來實現的。這兩種模式,實現了對Aggregate對象的操做,實現了複雜的生命週期轉換複雜性的良好封裝。對象
一個複雜的軟件系統,每每如同生產一臺汽車,它由許多個不一樣的部件組成,每一個部件間經過一系列複雜的協同運動來實現總體的職能。對於用戶而言,汽車是如何裝配的,並非他所關心的問題,他只在意如何駕駛這輛汽車。這意味着,裝配過程,應該與對象要執行的工做分開。軟件系統一樣如此,咱們設計了一個複雜的聚合對象,這個對象內部有大量的實體或者值對象。若是開發者須要使用這個對象,必須按照一系列規則來進行操做。blog
在這個聚合對象的生命週期中,若是將建立的過程按照調用的場景,分拆到不一樣的環節中,可能使代碼的耦合性急劇提升,帶來的將是後期高昂的更改爲本。
在領域驅動設計中,複雜對象的建立過程每每是領域層的核心職能,可是,對於這個複雜對象建立過程,又顯然不能有簡單的Service對象來實現,所以,須要引入工廠模式。封裝建立複雜對象或聚合對象
的所有規則,並經過提供相關接口、建立對象的抽象視圖,讓建立的過程符合規則。
在領域工廠模式中,每每有如下要求:
一、建立過程的原子性、知足建立所需的全部規則。因爲咱們引入工廠的目的,是爲了將複雜的常見過程進行封裝,所以咱們應當確保建立過程要產生一致狀態的對象。例如建立實體,應當知足聚合的所有規則、建立值對象,應該被設置爲默認的參數,若是沒法建立參數,應該拋出異常,或者提供處理機制,確保不會影響代碼的執行。
二、工廠模式是一種抽象對象,而不是具體對象。意味着這個過程,不會產生具體對象,也就避免了與下層對象間沒必要要的耦合。
工廠模式不只僅能夠應用於對象生命週期的開始階段,也能夠在對象的重建過程當中發揮做用,例如在使用關係型數據庫和非關係數據庫組成的複雜體系中,經過對象映射技術,能夠實現對現有數據的裝載。
在軟件系統研發過程當中,咱們一般須要使用SQL語句,直接調用基礎設施層中的某個方法,實現了一系列數據轉換。有時候,咱們會引入AutoMap組件,實現從實體層到模型層對象的封裝,這種模式普遍存在於咱們的開發過程當中,可是若是直接訪問基礎設施層,則可能增長對於數據庫沒必要要的操做,並致使模型的價值無關緊要。並且隨着開發過程的推動,有可能會傾向於直接使用屢次遍歷的方式,提取具體對象,而忽略了Aggregate,並使得實體層成爲單純的數據容器。
所以,經過引入倉儲模式,能夠爲咱們的實現過程提供便利。經過倉儲模式,封裝一系列數據庫操做的方法,讓咱們的注意力更關注於模型中。客戶端經過查詢方法,向倉儲中請求對象,而後再返回用戶所需的對象。
這段代碼大概是這樣的:
public interface IRepository<T> where T : EntityBase { T GetById(int id); IEnumerable<T> List(); IEnumerable<T> List(Expression<Func<T, bool>> predicate); void Add(T entity); void Delete(T entity); void Edit(T entity); }
倉儲的引入有不少優勢:
一、爲訪問者提供簡單的模型,可用來獲取持久化對象並管理他們的生命週期。
二、實現數據源解耦。
三、實現了對象訪問策略的分離。
四、便捷的訪問內存對象,減小對數據庫的吞吐壓力。
在倉儲的設計過程當中,應當注意一下事項:
一、對類型進行抽象。倉儲的目的是爲了傳遞具備特定類型的實例,但並不是每一個對象都有一個倉儲來與之對應。
二、充分解耦。倉儲聚合不一樣的查詢方法,例如將關係數據庫和緩存數據庫的查詢方法進行封裝,使得代碼的過程變得易於操縱。
三、事務可控。提供事務操做的方式,便於用戶自行實現事務的管理。
在領域驅動設計中,經過在領域層中靈活的應用倉儲模式和工廠模式,實現對象的建立過程和傳遞過程的不一樣階段,可讓代碼的執行過程更加的簡潔、關係更加的清晰,這也將客觀上有利於咱們編寫出更加優秀的代碼。