主頁 > 軟體設計 > 從業務開發中學習和理解架構設計

從業務開發中學習和理解架構設計

2022-07-22 09:15:52 軟體設計

 

 

前言

 

在軟體開發領域經常會接觸到架構這個詞匯,在我最初的印象中,架構是一個很高級的詞匯,它似乎代表了復雜的工程結構、高層次的抽象設計、最新的開發語言特性等等,對于當時只專注于寫業務邏輯的我來說,不免心生對架構的敬畏,作業中對架構的討論很少,出現則是一些高級晦澀的描述,但是從來沒有人清楚地解釋過架構做了哪些事,所以,架構到底是什么?架構和業務之間是什么關系?

 

當我們看一些關于架構的書籍或者資料,不免會接觸到一些對架構的定義或者描述,比如:約束、規則、邊界、物體關系、模型定義等等,但是懂得這些概念并不能幫助我們設計出來更好的架構,當我們套用設計原則進行架構設計時,不免會覺得空洞乏味,總覺得少了點什么,雖然我們為架構設計做了很多事,但是似乎什么也沒做,因為只針對架構設計本身來說,很難說清楚它所產生的價值,所以,好的架構設計的出發點是什么?好的架構應該是什么樣的呢?

 

去年我有一個任務:將我們當前工程的代碼進行重新的拆分和組合,以厘清模塊間的關系,控制工程中模塊依賴的復雜度,這看起來是一個很簡單的作業,找到一個不同于當前的且更合理的目錄劃分方案,就可以嘗試落地實施,但是這又是一個很困難的作業,因為我們首先要回答有哪些模塊、模塊間是什么依賴關系的問題,其實,回到任務的本身,我們并不是只想對代碼檔案進行重新的組織和劃分,我們的目標是業務模塊解耦合,定義并明確業務模塊間的依賴規則,面對這樣的目標,我們需要首先從業務視角更清晰地定義和劃分模塊,然后從工程結構視角確定模塊間的關系,所以,代碼目錄調整實際上是一個對業務場景、工程結構理解和設計的問題,代碼目錄的結構代表了我們的工程結構,也是業務場景劃分的抽象描述,更是模塊定義以及模塊依賴關系的展現,

 

在設計代碼目錄劃分方案的程序中,看了一些工程結構設計的資料,讀了一些關于架構設計的書,對于架構有了一些理解,本文是對這段學習和任務完成程序的思考和沉淀,我希望能夠回答上面提到的幾個問題:

 

1.架構到底是什么?架構和業務之間的關系

 

2.好的架構的設計出發點是什么?好的架構應該是什么樣的

 

什么是架構

 

架構的定義

 

首先架構是一個漢語詞匯,它的定義是:人們對一個結構內的元素及元素間關系的一種主觀映射的產物,從這個定義可以看出,傳統的架構在描述一個系統中有什么元素,以及元素之間關系,在建筑領域,架構也用于描述建筑物的結構,  

 

作為一個計算機領域的詞匯,架構的定義是:有關軟體整體結構與組件的抽象描述,用于指導大型軟體系統各個方面的設計,實際上也在定義有什么以及關系的問題,

 

 

 

從工程化解讀架構設計的作用

 

無論是在建筑領域還是計算機領域,我們通常會用工程描述這類作業的專案,比如我所在的部門是工程技術中心,我是一個工程類的程式員等,我們可以稱之為工程的作業專案包括:建筑工程、軍事工程、水利工程、生物工程、軟體工程等,而我們在完成專案的程序中,進行架構設計實際上就是推進實施工程化的一部分,那么進行工程架構設計會考慮哪些因素,它對實施工程化的作用是什么呢?

 

假設,讀者你現在是一位建筑工程師,負責建造一棟房屋,

 

雖然我們沒有真正的蓋過房子,但是在進行房屋的整體結構設計時,你一定會關心這些:

 

1.房屋用途,首先要明確這棟房子是干什么用的

 

2.房屋層數,和用途緊密相關,不同用途的房子層數也是不一樣的

 

3.房屋外觀,定義這棟房屋應該長什么樣

 

4.房屋的布局,定義這棟房屋應該怎么更好地被使用

 

等等,我們稱上面這幾個屬性是房屋的基礎能力,作為一個靠譜的建筑工程師,你一定還會著重地設計這些:

 

1.水電走向,這很重要,保證房屋的安全性和使用的便捷

 

2.承重和抗壓,房屋的使用壽命很大程度上依賴于此

 

等等,我們稱上面的這幾個屬性是安全性和性能,

 

另外一方面,你大概不會關心房屋的裝修風格、地板顏色、衣柜品牌等等因素,我們稱這些為應用細節,

 

總結來說,進行房屋的工程架構設計時更多地關系底層設計,而不在乎過多的技術細節,

 

所以,我們可以給架構的作用下一個定義:在明確用途的基礎上定義使用的規則和約束,提供了基礎的支撐能力,并保障安全性、性能和使用周期,

 

軟體架構設計的原則和要求

 

到目前為止,我們已經明確了在做架構設計時必須遵循的前提和原則:明確用途,此外也對架構設計提出要求:提供基礎能力、保障安全性、性能等,

 

同樣的,引申到計算機領域,當我們進行軟體架構設計時也必須遵循的原則有:

 

1.架構設計一定要從業務場景出發

 

這實際上就是明確用途的大前提,架構設計一定是要從業務出發、面向業務變化的,只有在我們明確了我們的業務場景和業務目標后,在此基礎上進行的架構設計才是能真正產生業務價值的,一個脫離了業務場景而設計的架構,無論多么新穎和高級,也絕不是一個好的架構,

 

2.架構設計一定要落到業務場景中去驗證

 

我們不能只從基礎能力、安全性或者性能方面去評判一個架構的好壞,架構對業務開發的支持能力,面向業務變化時的靈活度以及持續演進能力等都是評判的因素,

 

此外,我們要求軟體架構必須是靈活的,能夠滿足未來業務持續發展的要求,

 

業務場景是不斷變化的,架構也要具有跟隨業務形態不斷演進的能力,架構設計的核心是保證面向業務變化時有足夠靈活的回應力,這要求架構設計能夠識別到業務的核心領域,所以,無論是面向當前還是面向未來,架構設計都需要真正地識別和理解業務問題,

 

架構設計的原則

 

本章節介紹幾個軟體架構設計時可以遵循的原則,實際上在進行功能模塊設計也可以參考這些設計原則,

 

SRP 單一職責原則

 

1.一個函式只負責完成一個功能

 

2.任何一個模塊只對某一類行為者負責

 

3.一個類或者函式應該有且僅有一個被改變的理由

 

在實際的編碼中,我們還是可以看到很多違反單一職責的例子的,比如超長的函式體,一個函式內做了很多事,實際上就是負責了太多的功能,很多的變更都要修改這個函式,這導致很難控制變更影響的范圍,

 

我們可以將大函式拆分成小函式,小函式體負責的功能更加單一,相應的也會更加靈活,所以我們建議大家多寫一些小的函式體,但是不要在函式拆分的程序中進行過度的封裝和抽象,

 

OCP 開閉原則

 

1.易于擴展,抗拒修改

 

模塊要易于擴展,控制修改,這是我們在初學編程語言時就會被教育到的設計原則,開閉原則幫助我們設計更加靈活的模塊,同時還能控制模塊變更的影響范圍,

 

LSP 里氏替換原則

 

1.所有參考父類的地方都可以替換成子類,而行為不發生改變

 

使用里氏替換原則可以保證父類的復用性,它主要是用來判斷抽象和繼承關系設計是否合理,即某個類是否應該具有某個屬性,以及一個類到底是不是另外一個類的子類,

 

舉一個典型的例子,乘馬是乘馬,乘白馬也是乘馬,乘黑馬也是乘馬,那么白馬和黑馬就是馬的子類,是符合LSP的,

 

下面是兩個典型的違反LSP原則的例子,也是網上也特別常見的例子,

 

第一個是正方形不是矩形,

class Rectangle {
 public:
     int32_t getWidth() const {return width;}
     int32_t getHeight() const {return height;}

     virtual void setWidth(int32_t w) {
         width = w;
     }
     virtual void setHeight(int32_t h) {
       height = h;
    }
private:
    int32_t width = 0;
    int32_t height = 0;

};
class Square : public Rectangle {
 public:
     void setWidth(int32_t w) override {
         Rectangle::setWidth(w);
         Rectangle::setHeight(w);
     }
     void setHeight(int32_t h) override {
          //
     }
 };

 void reSize(Rectangle rect) {
     while (rect.getHeight() <= rect.getWidth()){
         rect.setHeight(rect.getWidth() + 1);
    }
 }

正方形類Square繼承自矩形類Rectangle,并且重寫了函式setWidth和setHeight,在函式reSize中,將父類Rectangle物件替換成子類Square后,將會出現死回圈,程式出現例外,不符合LSP原則,

 

所以正方形不是矩形,第二個是鴕鳥不是鳥,

 

class Bird {
public:
     int32_t getVelocity() const {return velocity;}
 private:
     int32_t velocity = 0; // 飛行速度
 };

 class Ostrich : public Bird {
 };
void crossRiver(Bird bird) {
     int32_t distance = 1000;
     int32_t elapsed = distance / bird.getVelocity();
 }

鳥類Brid具有飛行速度的屬性,鴕鳥類Ostrich繼承自類Brid,飛行速度默認為0,在函式crossRiver中,將基類Brid物件替換成子類Ostrich物件后,獲取的飛行速度為0,出現了除0例外,不符合LSP原則,

 

所以鴕鳥不是鳥,

 

在這兩個例子中,結合里氏替換原則, 我們得出了兩個奇怪的結論,違背了幾何學和生物學的常識,其實問題在于我們對抽象和介面的設計上,比如前一個例子中reSize函式,它的條件判斷是有問題的,對于一個矩形物件,寬高不一定非得相等,所以將寬高相等作為回圈的條件是不合理的,

 

對于后一個例子,飛行并不是鳥類的統一特征,所以抽象的鳥類不應該擁有飛行速度這個屬性,也不應該具有飛行的介面,那么我們應該怎么處理這個問題呢,準確來說,鳥類可以具有是否可以飛行的介面,然后有一個速度屬性,可以飛行的鳥回傳飛行速度,而鴕鳥回傳行走速度,

 

所以,里氏替換原則用于驗證我們的介面和抽象設計是否合理,同時也可以驗證繼承關系是否合理,

 

ISP 介面隔離原則

 

1.不依賴于自己不需要的東西

 

2.使用介面類的方式細化功能模塊,每個介面類負責某一類明確的功能

 

指導我們進行介面設計的原則,類似于單一職責原則,多個單一的介面負責的功能更簡單,更易于維護,這比一個龐大的介面要好,在做介面設計時要盡量保證介面的小巧、簡潔和正交,這樣給業務層提供了更多的靈活性,一個大的介面可能會做業務層并不希望做的事,同時當業務層需要擴展功能時也會使變更影響的范圍過大,

 

DIP 依賴反轉原則(依賴倒置)

 

1.為了保證系統的靈活性(易于修改)和穩定性(修改影響范圍小),在依賴關系中應該避免參考具體的類

 

2.介面比實作更穩定,所以盡量避免修改函式實作時對依賴該介面的模塊的影響

 

3.繼承關系是依賴關系中最強的,盡量避免繼承自有具體實作的類

 

這個原則目的在于降低使模塊間的耦合度,并且使底層模塊更易于被修改和替換,當下層功能發生變化時可以控制對上層業務的影響范圍,使得整體系統更加穩定和靈活,

 

DIP原則在后面章節介紹架構設計方法時也會多次提到,

 

以上這五個設計原則統稱為SOLID原則,在《整潔架構之道》中有比較詳細的介紹,

 

奧卡姆剃刀原則

 

奧卡姆剃刀原則不是在軟體開發領域提出的,而是在哲學領域提出的,奧卡姆剃刀原則對科學和哲學的發展都極為重要,因為它告訴人們理論應該盡量簡潔,理論中一切不影響結論的多余部分都應該被剔除掉,

 

正如奧卡姆剃刀原則的精髓一樣,它的描述非常簡潔有力:如非必要,勿增物體,

 

我們也可以稱它為簡單即為美原則,通俗的描述是:用盡量少的步驟完成一件事,或者,如果對于一個事物有兩種解釋,采用最簡單或能被證偽的那種,正是因為奧卡姆剃刀原則,我們才更加相信哥白尼的日心說,更相信牛頓和愛因斯坦,否則,地球是宇宙中心的理論也沒錯,只是其他行星和恒星環繞地球的軌道公式也太復雜了,而且也容易被自然現象證偽,

 

在眾多的介紹軟體設計方法的書籍和資料中也多次提到過奧卡姆剃刀原則,應用到軟體開發領域,它確實給了我們很大的啟示,設想一下我們是不是遇到過這樣的場景:

 

1.費力地向別人解釋某個模塊為什么那么設計

 

2.為某段代碼加的注釋比代碼都多

 

3.為了解決一個問題而引入一個新的模塊

 

當我們費力說明和解釋某個代碼設計時,真正的問題并不在于我們解釋的不夠充分,或者聽眾不夠聰明理解不了,而在于代碼設計本身沒有很好地體現其業務語意,實際上過多的解釋和注釋都是多余的,是可以被奧卡姆剃刀砍掉的,

 

對于為了解決一個問題而引入一個模塊也是在作業中經常遇到的問題,有很多原因導致某些模塊變得腐化難以維護,比如最初的設計沒有很好地貼合業務場景;編碼規范不夠好,后面的修改也沒有遵守規則;接手者沒有完全理解作者的意圖就著手修改等等,而程式員也經常會有的一個想法是:當一個模塊難以維護了,最好的方法是用一個新模塊替換掉它,實際上這種方法并沒有觸及問題的本質,在沒有找到導致模塊腐化的原因之前,在沒有制定規范的模塊設計方案之前,我們都不能保證新模塊不會有舊模塊一樣的問題,所以,想開發新模塊替換掉舊模塊很大程度上是在逃避對舊模塊問題的思考,新模塊也很有可能淪落到舊模塊一樣的地步,如果回答不了這個矛盾的問題,還是用奧卡姆剃刀把新模塊剔除掉吧,新模塊是多余的,并沒有解決真正的問題,

 

奧卡姆剃刀原則保證解決問題的方法是簡單有效的,同時也約束我們應當思考更根本的問題,不能浮于問題表象采用最省力的方法,

 

其他的設計原則概覽

 

DRY(Dont Repeat Yourself):保證代碼的可復用性,避免代碼邏輯的重復

 

YAGNI(You Aint Gonna Need It):代碼應易于擴展,但要避免過度設計,不要撰寫當前用不到的代碼

 

KISS(Keep It Simple, Stupid):把事情想復雜,做簡單

 

POLA(Principle of Least Astonishment):最小驚奇原則,代碼應合乎邏輯和規范,給閱讀者最少的驚嚇,介面設計避免標新立異

 

常用的幾種架構設計

 

分層架構

 

分層架構是指基于具體的業務模型按照功能模塊將代碼進行分層組織,每一層代表了一組相關功能的集合,具體分為幾層沒有明確的規則,通常可以分為3-4層或者更多,在分層架構中,依賴關系是由上往下,上層依賴于下層,不能反向依賴,越往下的層次越通用,偏向于基礎能力,越往上層次越動態,偏向于業務,

 

分層架構設計按照依賴規則的嚴格程度分為嚴格型分層架構和松散型分層架構,嚴格型分層架構要求每一層只能訪問其直接依賴的層,不能訪問其間接依賴的層,松散型分層架構允許每一層訪問位于其下方的任意一層,嚴格型分層架構使得各個層之間的耦合度降到最低,但是靈活性不足,當上層需要訪問下面間接層的能力時必須從上往下層層穿透,松散型分層架構在保證依賴規則的前提下提供了足夠的靈活性,所以大部分分層架構都是松散型的,

 

分層架構設計簡潔易懂,對抽象事物按斬訓礎特征進行分類,符合我們的思維習慣,易于理解,分層架構設計保證每一層內部有較好的內聚性,減少了層與層之間的耦合度,易于基礎能力的沉淀和復用,也易于控制變更帶來的風險,

 

另外一方面,分層架構設計雖然定義了多個層,但是層與層之間的邊界并不是特別清晰,對于新增的模塊有可能難以確定應該放在哪一層,或者隨著業務邏輯的變化,未來可能需要調整模塊所屬的層次,分層架構中,上層模塊對下層模塊有直接的依賴,下層模塊的實作直接向上層模塊暴露,在修改或者替換下層模塊時需要修改上層模塊,對上層業務的影響較大,業務實作與基礎能力沒有完全解耦合,

 

六邊形架構

 

又稱為埠-配接器架構,為了解決具體實作依賴于基礎能力的問題,采用依賴倒置設計方法將工程分為內部和外部,內部是具體的業務邏輯,外部是依賴的基礎能力,內部業務邏輯不再直接依賴于外部基礎能力,而是都依賴于其抽象定義,使用依賴注入的方式將外部實作傳入內部業務邏輯中,內部和外部使用介面進行互動,內部業務邏輯訪問基礎能力時直接呼叫其抽象介面即可,

 

 

六邊形架構解決了業務邏輯直接依賴外部模塊的問題,它們都依賴于抽象,不依賴于直接的實作和細節,它們直接通過定義好的介面進行互動,因為業務邏輯和外部模塊沒有直接的依賴關系,在修改和替換外部模塊時只需要按照介面定義實作功能,不需要改動業務邏輯,

 

洋蔥圈架構(整潔架構)

 

洋蔥圈架構又稱為整潔架構,結合了分層架構、六邊形架構和領域驅動設計特點的架構設計方法,洋蔥圈架構是對六邊形架構的進一步擴展,依賴關系依然是外部依賴內部,參考領域驅動設計,將依賴層次劃分為3-4層甚至更多,從內向外依次為:領域模型、業務邏輯、領域服務、基礎能力、外部模塊等,

 

洋蔥圈架構具有六邊形架構的優點,采用依賴倒置的原則使內部業務模型不再直接依賴于外部基礎能力,外部模塊的變動和替換不影響內部業務邏輯,采用領域驅動設計的方法劃分物體和模型,利于業務規則的抽象和業務模型的建立,對未來業務迭代的支持較好,洋蔥圈架構使業務物體、業務模型和業務實作處在里層,保證了業務模型和實作的穩定,避免受到外部模塊變動的影響,

 

例如,使三方SDK或者資料庫系統屬于最外層,使用依賴注入的方法將它們的實作傳入內部邏輯,當替換三方SDK或者資料庫系統時,按照介面定義實作具體細節即可,不需要對內部邏輯進行改動,

 

領域驅動設計方法

 

領域驅動設計簡稱為DDD(Domain-Driven Design),準確來說它不是一個架構設計方法,而是一種以業務分析和劃分來驅動系統架構設計的軟體開發方法,它強調識別業務的核心問題域來確定問題邊界,同時將問題域進行分解降低分析的復雜度,DDD強調通過關注業務核心提升業務價值,

 

下面是DDD的一些核心概念,我們做一些簡單的介紹,

 

1.領域:有確定的范圍和邊界的業務問題域,實際上是我們要解決什么業務問題的抽象描述,比如提供給用戶當前位置、目的地位置且提供到達資訊是高德地圖的問題域,

 

2.子域:將大的問題域根據業務規則的不同拆分成的小問題域,比如高德地圖的問題域太大了,難以解決,我們可以將問題域拆分成定位、POI搜索、路線規劃等子問題域,

 

3.界限背景關系:領域之間的抽象邊界,封裝了領域內的概念、規則和模型,

 

4.物體:具有唯一標識的、存在生命周期的物件,比如展示給用戶可見的POI氣泡是一個物體,它有狀態和確定的生命周期,

 

5.值物件:沒有唯一標識和生命周期的物件,依附于物體而存在,比如POI資訊是值物件,本身沒有狀態,只能依附于POI氣泡這個物體而存在,

 

6.聚合:領域內一組物體、值物件的集合,封裝了集合與外界的互動

 

 

 使用DDD對業務問題進行分析和拆解后,可以采用任何一種架構設計方法,無論是分層架構、六邊形架構或者整潔架構等,但是DDD要求架構設計從實際的業務場景出發,理解業務的核心問題,架構需要明確概念、規則的設計,并且保證業務模型的穩定性,使用分層架構展現DDD的領域設計方法,將工程分為4層:基礎設施層、領域層、應用層和用戶介面層,

 

 

我們所用的架構方案

 

鷹巢

 

我所在的團隊——鷹巢業務組負責高德地圖規劃和導航的業務能力實作,它向下對接引擎層,包括定位引擎、導航引擎、渲染引擎等,向上對接前端JS層,除了承接功能龐大、邏輯復雜的導航業務外,鷹巢還負責引擎能力的封裝以及將這些封裝能力向上層JS透出,

 

在進行代碼目錄劃分之前,鷹巢的功能實作也是按照模塊化進行設計的,但是模塊之間并沒有明確的依賴關系,任何代碼都可以互相的參考,這也就導致了工程中各模塊之間有錯綜復雜的呼叫關系,很難以說清楚某一個模塊應該處于哪個位置,應該如何被參考,雖然我們一直將工程代碼分為框架層和業務層,但是框架層和業務層之間的依賴關系并不明確,業務層依賴框架層,框架層也依賴了業務層,并不符合分層架構的設計原則,所以鷹巢的工程架構不屬于分層架構,

 

在我們去年的代碼目錄劃分的作業中,我們最終參考領域驅動設計的方法對代碼目錄進行了重新的組織和劃分,將工程代碼整體上分為4層:基礎能力、業務層、工具層和接入層,以下是整體結構圖:

 

 

適配層與以下的4層不在同一個倉庫,它包含了與前端JS互動的必要能力封裝,按照模塊的劃分規則,我們可以說,鷹巢的工程架構屬于結合領域驅動設計的松散型分層架構,它的特點是:

 

1.按照領域驅動設計對工程代碼進行組織和劃分,在業務層按照不同業務領域劃分代碼模塊

 

2.采用分層架構設計將工程分為多層,上層依賴于下層,下層不能依賴于上層

 

3.上層任意模塊都可以呼叫下層任意模塊,屬于松散型架構,更加靈活

 

工程技術中心C++能力層(包括地圖引擎層)

 

在工程技術中心的語言能力框架中,從鷹巢、地圖引擎到基礎庫都是C++語言實作,使用統一的流程管控它們的開發、構建、集成,在引擎架構升級之前的相當長的一段時間內,它們都屬于松散型分層架構,以下是簡化版的結構圖:

 

 

 

實際上,包括引擎庫在內的C++層有幾十上百個代碼倉庫,層次眾多,且從上層到下層的依賴關系復雜,如果將所有的依賴關系繪制出來,將是一個復雜的網狀,雖然整體架構依然遵守了分層架構的設計原則:只能上層依賴下層,但是因為依賴層次和關系的復雜,導致下層代碼的改動對上層的影響很大,在構建時也經常出現庫版本不匹配的沖突,這使得上層業務層經常處于不穩定狀態,不利于上層業務的快速迭代,并且下層能力升級也必然需要上層業務層做大作業量的適配,

 

在去年的引擎架構升級中,抽離出抽象層,使得各個倉庫都依賴于抽象介面,不再依賴于具體的實作,抽象出來的抽象層包括:InterfaceApp、InterfaceAR、InterfaceARWalk、InterfaceHorus、InterfaceMap、InterfaceVMap、InterfaceTBT、InterfacePosEngine等,比如鷹巢和TBT都依賴于InterfaceTBT抽象層,使用依賴倒置的原則在App初始化時將TBT的實體化物件設定給鷹巢,鷹巢通過呼叫實體化物件的抽象介面訪問TBT的能力,同理,鷹巢和渲染都依賴于InterfaceMap抽象層,這種方式使得上層的業務層比較穩定,只要保證抽象層介面的穩定性,業務層基本上就不會受到下層改動的影響,而且,當下層進行能力升級時,只要按照抽象介面定義實作對應能力即可,不需要業務層做適配,

 

從這方面來講,在引擎架構升級后,引擎具有整潔架構的特征,但是并不能完全稱為整潔架構,因為從更大的視角來看(將基礎庫和Native層包括進去),依然是松散型的分層架構,所以,我們可以稱之為具有整潔架構特征的松散型分層架構,

 

總結

 

對于架構設計的學習和理解,我認為很難的一點是:即使懂得很多道理還是很難把事情做好,眾多的設計原則都是在不同業務場景下提出的,有些原則之間本身就是矛盾的,無論是架構設計方法還是設計原則,它們不是金科玉律,更不可能放之四海而皆準,它們的價值在于告訴我們應該摒棄什么,應該遵守什么,我們不用那些技術官僚的詞匯,用更接地氣的描述來說,設計原則也只是要求我們做到簡潔、規范和易于理解而已,架構設計并不高端,它本身所產生的價值并不明顯,真正能夠產生價值的在于我們當前正在走的路:如何理解我們的業務問題,

 

參考資料和書籍:

 

應用架構之道:分離業務邏輯和技術細節:https://www.cnblogs.com/alisystemsoftware/p/13846127.html

 

The Onion Architecture:https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/

 

《架構整潔之道》、《領域驅動設計-ThoughtWorks洞見》、《代碼精進之路-從碼農到工匠》、《UNIX編程藝術》

 

附錄:

 

工程:是指以某組設想的目標為依據,應用有關的科學知識和技術手段,通過有組織的一群人將某個(或某些)現有物體(自然的或人造的)轉化為具有預期使用價值的人造產品程序

 

工程化:是指以提高效率、降低成本、保證質量保證為目的從而促進多人合作,實作功能強大,健壯性好的專案的手段和措施

 

作 者 | 張東愛(當愛)

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/Learn-and-understand-architecture-design-from-business-development.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/500021.html

標籤:其他

上一篇:簡單易用的任務佇列-beanstalkd

下一篇:高并發組件了解

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more