<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      領域驅動開發實踐之路:我們是如何從領域驅動開發當中獲益的

      2017-11-01 16:47  敏捷的水  閱讀(3693)  評論(6)    收藏  舉報

      領域驅動設計,遇見你之前

      我們公司推行和實踐敏捷已經很多年了,SCRUM已經成功應用于大部分項目,得益與業界敏捷開發大師以及國內很多優秀工程師的分享和宣傳,我們使用了很多優秀的軟件開發實踐,比如測試驅動開發(TDD),行為驅動開發(BDD), 持續集成(CI)等等為我們帶來了很多收益。由于我們公司以做項目為主,雖然這些軟件實踐確實能很好的提高軟件交付質量和效率,但是要想用好這些實踐,涉及到的因素很多,常見的如下:

      • Scrum里需要Product Owner, 客戶方很少能有一個比較符合Scrum里提到的Product Owner來定義需求為As a role I want to do something so that I can get some benefit.

      • 行為驅動開發BDD對客戶方要求更高,客戶需要寫Specific, Scenaro, Given...When...Then. 我做過一個項目,客戶開始寫BDD,而且也能寫出比較高質量的BDD, 但是客戶后來就不寫了,覺得寫的麻煩。

      • 我們主要使用.NET,雖然大家都熟悉面向對象,熟悉類,接口,繼承,封裝等等,但是面對一個項目的時候,如何對業務就行合適的抽象,正確使用面向對象依然是非常大的挑戰。

      • 由于使用敏捷,不再像之前傳統開發過程中有詳細的需求說明書(假定那個需求說明書及時更新,且描述準確易于理解), 強調的是可工作的軟件,但是很多業務邏輯很難通過界面來體現,雖然有User story, 但是就像第一步PO很難寫出符合SMART原則的用戶故事,常出現的情況,就是PO說一個需求的大意,程序員就“秒懂”了,最后也確實開發出了經過驗收測試的軟件,但是因為有測試和Feedback的修復,這一類的需求就“丟失”了。

      • 人員變動,軟件行業成員變動是很正常的現象,但是很多小團隊一個蘿卜一個坑,如果沒有好的方法,項目的相關context就丟失了,且不說有的人走的時候沒有心思做交接,就算想好好做交接,也只能是最大程度減少項目相關內容不能很好傳遞。

      幾年前,當我開始做分公司的時候,剛開始我一直在致力于敏捷的推行,好的軟件開發實踐的實踐,很多同事的軟件技能大幅提升,比如熟悉了很多Clean Code的東西,單元測試的重要性和好處,持續集成,Gitflow等的好處。但是有幾個問題一直是我在考慮的問題

      1. 如何減少客戶反饋的bug, 雖然敏捷強調客戶頻繁互動和反饋來讓錯誤無限靠近開發的時間,但是能把事情一次做對而不是多次改對依然能大幅提高項目提交速度,也就節省了客戶的成本,提高了開發程序員的效率。
      2. 人員變更時候的知識傳遞,雖然清晰的軟件架構,整潔的代碼,高的單元測試覆蓋率能大幅加快新的人員理解項目的速度,但是看用戶故事,單元測試以及散落在很多類中的代碼(單一職責的時候,我們會有大量類,注意:這里不是說不要單一職責)對中途加入項目的人依然是需要較長時間熟悉項目和代碼。
      3. 提高開發人員軟件技能,提高開發效率從而提高對客戶的產出,然后開發人員的薪水自然能有對應的提升是做為一個分公司負責人的第一責任,員工第一嘛!另一個方面,我認為相對簡單的項目,比如一些CRUD項目,一些前端項目比如Angular/React的項目報價越來越低。主要是研究前端以及學習這些框架的畢業生越來越多(注:這里并沒有任何貶低前端的意思,現在前端要想做好也需要很多技能和設計思想), 我們必須去接一些"不好做"的項目,也就是業務復雜,需求復雜類的,這類項目才能提升程序員的能力而且報價相對較高。

      追求軟件卓越,原來,我一直強調質量和效率的重要性,但是大家很難理解和應用,突然有一天,我想到(也許從別的地方看到的),軟件最重要的是要解決兩個問題:

      1. 做正確的事情 (Do Right Thing)

      2. 把事情做正確 (Do Thing Right)

      初遇領域驅動設計

      做正確的事情 (Do Right Thing)

      把事情做正確 (Do Thing Right)

      一直在我腦海里,然后簡單的CRUD項目越來越沒競爭力,程序員的報價難以提高,自然薪水就會有瓶頸,而我也想解決這樣的問題,突然有一天我看到了另一句話:我選擇做這件事,不是因為他簡單,而是因為他難,這句話對我觸動很大。我的腦海里就一直縈繞著“簡單”,“復雜”,“麻煩”, 于是我要做的事情就是下面三個:

      做正確的事情 (Do Right Thing)

      把事情做正確 (Do Thing Right)

      做難的事情 (Do Hard Thing)

      我就在網上搜索Complex, Software 等,一本叫做Domain Driven Design的這本書出現在我面前,Domain Driven Design這個詞語早就聽說過,但是更吸引我的是副標題 "Tackling complexity in the heart of software", 我就大概看了一下書,里面的戰略設計正好提供了解決復雜業務的方法,統一語言,Bounded Context, 界限上下文,設計就是代碼,代碼就是設計等等。 我相信這正是解決 做難的事情做正確的事情 但是對戰略有些了解,怎么去實現呢?一直沒有一個好的例子來幫助大家如何使用領域驅動設計,直到一本《實現領域驅動設計》這本書的出現,才真的讓我們有了打通任督二脈的機會。

      實踐領域驅動設計

      有了《領域驅動設計》和《實現領域驅動設計》兩大神器,也只是向美女要了個聯系方式和家庭住址而已,中間還隔了一個漫長的日落和日出,沒有正式的項目,我們永遠是在岸上游泳,雖然我們也在項目里開始或多或少使用了領域的一些概念,但是我們應該知道基于數據驅動(Database Driven) 是很難成功應用領域驅動設計的。正好這個時候公司來了一個項目(客戶是Fortune Global 500), 他們的架構師指定要求使用領域驅動設計,這讓我非常興奮,讓我們有機會對復雜業務進行領域驅動開發的實踐。

      就像實現領域驅動力說的一樣,領域驅動主要有兩大塊兒戰略設計和戰術設計。

      戰略設計 (Do Right Things)

      Ubiquitous language

      領域驅動開發讓業務專家(Domain Expert)和開發人員一起來梳理業務,而雙方有效溝通的方式是使用通用語言,在這個項目里,一開始我們就定義了很多詞匯表, 就是我們自己的通用語言。

      Bounded Context 和 Domain

      有了通用語言,詞匯表 每一個詞匯一定是有邊界的,不同的邊界內是不一樣,比如你愛人在你家這個Bounded Context是你的Wife, 但是如果她是一個老師,那么在學校這個邊界里就是一個Teacher. 我們經過多次討論,采取的方法是拆成多個子系統(Bounded Context,是不是很像現在的微服務?),每個子系統進行自治。

      隨后我們把一個個業務抽象為領域對象(Domain Model), 每一個Domain對領域進行自治。而模型里的屬性和行為表達為業務專家都可以理解的代碼,用比如Job.Publish(). 雖然這里面最終產生了聚合根、實體、值對象等,但是我們和業務專家溝通的時候盡量不要說這些詞匯,比如我們可以說, 在招聘這塊兒,職位是不是必須經過公司進行管理,那樣我們就知道 Job是屬于公司這個聚合根。 對領域進行“通用”(類名,方法名等都用自然語言表達)建模,業務人員可以直接讀懂我們的代碼,從而可以知道是否表達了業務需求。

      戰術設計 (Do Things Right)

      在戰術設計方面,由于業務行為和規則都在領域里,而且系統被拆分成多個子系統,這對技術實現上帶來了非常大的挑戰,尤其是大部分人都是有牢固的基于數據驅動開發的思想。 技術上有不同實現方式,但是一開始我們選擇了“最佳實踐”(實現領域驅動設計),也就是使用了Event Source和CQRS, 但是這條路是陡峭的。

      Event Sourcing

      Event Sourcing 就是我們不記錄數據的最終狀態,我們記錄對數據的每一次改變(Event),而讀取的時候我們把這些改變從頭再來一遍來取得數據狀態,比如你有100塊錢,現在剩下10塊了,我們記錄的不是money.total=10, 而是記錄你每一次取錢的記錄,然后從100塊開始一步步重放你取錢的過程,來得到10.

      一開始,我們寫的過程中,時常回想起數據驅動的好,(每次開始一個新東西的時候,是不是很熟悉的感覺?),覺得用Event Sourcing各種麻煩,直到后來隨著系統的復雜性不斷增加,我們才感覺到帶來了非常大的好處, 這個隨后單獨來說。

      CQRS

      由于使用了EventSourcing, 對數據查詢,尤其是跨業務(aggregate)的查詢非常麻煩,很難像關系數據那樣有查詢優勢,CQRS是解決這一問題非常好的方法,CQRS讓查詢和寫入分開,把界面需要查詢的數據進行原樣寫入,原樣的意思就是界面顯示什么樣的,就提前保存成什么樣的,類似于原來的緩存,沒有任何join操作,這樣查詢是非常高效的。

      實踐領域驅動過程中面臨的技術挑戰

      最大的挑戰當然是戰略設計部分 就是正確的劃分Bounded Context和領域建模,這個部分這里難以幾句話說清楚,只能多實踐,多向大師學習,比如試試Event Storming的方式。

      然后,如果團隊沒有任何領域驅動開發的經驗,千萬不要低估技術部分的挑戰,并不是很多人說的技術部分不重要,如果實現不好,領域驅動很難落地。我們遇到一些典型問題,當然后來都很好的解決。

      1. 開發人員認為EventSourcing不重要,比如,原來你要發布一個Job, 你可能只需要改一個屬性Job.Status="Published", 但是現在你需要定義一個JobPublishedEvent的事件,很多時候一次改變需要定義很多事件,比如CompanyNameChangedEvent, CompanyEmployeeAddeedEvent. 最重要的是事件的粒度如何定義?

      2. 由于根據Bounded Context拆分成一個個子系統,系統之間的交互比較麻煩。原來在一個Controller里直接調用不同的Repository來改變數據的方式就很不適用了。

      3. 由于使用CQRS,查詢必須要單獨保存QueryModel, 這相對傳統的數據庫驅動的開發方法,寫和讀都是同一個數據庫更加麻煩。

      4. 事件的版本管理,比如事件改名,刪除和增加都需要考慮重放事件重建領域對象的影響。

      5. CQRS如何保證數據的及時性和一致性,比如我在一個公司詳細頁面修改了一個公司名字,然后點擊保存按鈕導航到公司列表頁面,這個時候QueryModel可能還沒有更新過來,這些如何解決一致性的問題。

      領域驅動開發如何讓我們和客戶共同獲益的

      1. 做正確的事情(Do Right Things): 領域專家高效的和團隊溝通,確保建立了正確的反映業務規則的模型,而開發人員有了直接可以使用的代碼,而且可以因為Domain有了數據和行為,非常方便的進行單元測試,因為Domain不依賴第三方的數據存儲等,可以確保實現了業務。

      2. 大大提高了溝通的效率,我們知道一圖勝千言,而對開發人員來說,少廢話,Show me the code! 不但代碼對程序員更容易讀,而且Code(領域對象)就是最新的需求. 可以跑起來的需求。

      3. 大大提高新成員進入項目的速度,最主要的是看領域模型以及對領域模型的測試,幾乎就知道了系統的所有的業務規則。

      4. 領域驅動的技術部分給系統增加功能或擴展帶來了極大的遍歷,舉幾個例子:

        a. 由于使用了事件溯源,我們很容易查詢歷史數據。我們只需要指定一個時間點,我們重放事件的時候重放到這個時間點就可以了。

        b. 操作日志,原來如果我們想記錄操作日志我們代碼里遍布都是Log, 而現在我們只需要重發事件,想看什么日志就看什么日志,而這些就只需要我們回放數據庫存儲的事件流就可以了。

        c. 系統之間的通信,我們只需要發布事件就可以了,其它系統訂閱我們的事件就可以,我們和其它系統之間沒有直接依賴。

        d. 大大提高了系統增加新功能的方便性,很多時候增加新功能就是訂閱事件就可以了。

        f. CQRS, Query model極大的提高了系統的查詢性能,而且當我需要新的界面的時候,我不需要對寫入端代碼進行任何修改,包括類文件都不用修改,是不是符合對修改關閉,對擴展開放(OCP)? 我們只需要建一個類似新的EventHandler,然后重放對應的事件就可以了。

        e. 因為使用了事件溯源,系統之間通過事件集成,比如通過消息隊列發布和訂閱事件,這可以大大增加系統的抗壓能力,我們可以把事件放入隊列,后續處理系統即使不能及時處理也不會讓前端系統崩潰。

        f. 系統性能大福提高,在寫入端只有插入操作,沒有修改操作,在讀取端只有Read操作,那么何須鎖表,何須開啟事務?由此一來,輸出存儲和讀取的瓶頸可以大大緩解。

      5. 開發人員可以更集中的處理業務,由于一切都是事件,實現玩基礎庫后,開發人員可以忽略數據存儲,大部分時間都是在寫業務代碼,不關心數據怎么存儲,數據存儲部分就倆操作 AggregateRoot.Get(id), AggregateRoot.Save(), EventPublish.Pubish(CompanyNameChangedEvent), 而事件訂閱端只需要增加一個EventHandler就可以了。

      6. 系統很好進行了解耦,業務邏輯集中在領域中,不會像之前的開發里面業務邏輯充斥在很多地方,修改一些功能的時候,不得不如履薄冰,生怕哪里給破壞了,或者哪里沒考慮全。

      7. 不用過于擔心開發人員,尤其初級開發人員不正確的代碼遍布系統多個部分,對其它功能的影響可以大大減低,Review代碼其實主要Review業務實現的單獨的類,不用擔心很多技術實現部分不正確,因為基礎庫寫好了,這樣可以適當均衡團隊成員組成來降低項目開發成本。

      最后,系統更加容易修改和增加新功能,不正好支持了敏捷開發的“擁抱變化”嗎?

      總結

      領域驅動開發好處多多,概念比較多,門檻相對較高,對人員要求較高,團隊里至少需要有領路人,不然代價會比較大。 尤其慎用Event Sourcing, 而領域驅動尤其適合業務相對復雜的項目。 對那些很小的項目,CRUD仍然是好的選擇。

      最后,如果你對領域驅動比較感興趣,歡迎與我聯系探討 wangdeshui@outlook.com

      主站蜘蛛池模板: 国产精品高清中文字幕| 人妻丝袜无码专区视频网站| 久久久久久久一线毛片| 亚洲人ⅴsaⅴ国产精品| 麻豆麻豆麻豆麻豆麻豆麻豆| 成人乱码一区二区三区四区| 成人性能视频在线| 久久96热人妻偷产精品| 国内精品久久人妻无码不卡| 亚洲日韩av无码| 欧美激情内射喷水高潮| 婷婷六月天在线| 无遮挡高潮国产免费观看| 欧美性猛交xxxx乱大交极品| 亚洲av二区国产精品| 国产精品免费AⅤ片在线观看 | 亚洲国产欧美一区二区好看电影| 99久久国语露脸精品国产| 欧美日本在线一区二区三区| 蜜臀AⅤ永久无码精品| 亚洲精品日韩久久精品| 男人扒开添女人下部免费视频| 成人做爰www网站视频| 国产精品白浆在线观看免费| 国产精品黄在线观看免费| 亚洲av无码专区在线亚| 婷婷丁香五月亚洲中文字幕| 国产精品久久久久久福利| 放荡的少妇2欧美版| 久久国产免费直播| 国产一区二区三区不卡自拍| 99RE6在线观看国产精品| 中文字幕结果国产精品| 欧美极品色午夜在线视频| 极品蜜桃臀一区二区av| 欧美大bbbb流白水| japanese无码中文字幕| 少妇午夜啪爽嗷嗷叫视频| 久久亚洲国产精品久久| 色欲AV无码一区二区人妻| 国产人与禽zoz0性伦多活几年 |