Java進階:java字符串定位語句

正文

模塊(Module)、組件(Component)、包(Package),這些概念對于我們技術同學并不陌生,但并不是所有人都能理解其要義。

深入理解之后,我才發現,其背后的深意是分類思維。而這種分類也是應用架構的核心所在,通過不同粒度、不同層次的分類,把復雜的軟件系統實現控制在可以被理解、被維護的程度。否則,對于動則上100萬行代碼的軟件,人類根本沒有辦法理解和維護。

試想一個極端情況,假如沒有這些概念協助我們分類,我們把所有業務邏輯都寫在一個類里面,會是什么樣的結果呢?我們很多的“非人類”系統,正是因為沒有進行合理的分類造成的。

早期,我不喜歡JavaScript的一個重要原因,正是因為其缺少像Java中package和jar的概念,導致代碼的組織形式比較松散、隨意。這個問題直到ES6、React才得到比較好的解決,在此之前,前端工程師不得不依靠seaJS,requireJS這些框架來做模塊化、組件化的事情。

至此,你可能有疑問,分類有什么魔力?怎么就成了應用架構的核心了呢?客官別著急,由我細細道來。

分類的重要性

所謂分類,就是依據一定的標準對給定的事物進行組別的劃分。我們人類天生就有分類的本能,例如,當我們觀察下面這張圖的時候。

無論是誰,乍一看到上面的六個黑點,都會認為共有兩組墨點,每組三個。造成這種印象的原因主要是,人類大腦會自動將發現的所有事物以某種持續組織起來。基本上,大腦會認為同時發生的任何事物之間都存在某種關聯,并且會將這些事物按某種邏輯模式組織起來。

之所以我們大腦有這樣的本能,是因為人一次能夠理解的思想或概念的數量是有限的。正如喬治米勒在他的論文《奇妙的數字7》中提出的。人類大腦的短期記憶無法一次容納7個以上的記憶項目。所以,當信息量過大時,唯有歸類分組才能幫助我們去理解和處理問題。

其實,自古及今,人類一直在做著歸類/分類,早在春秋時期,《戰國策》中就提出過“物以類聚,人以群分”的概念。

在互聯網行業,我們會對客戶進行分類,然后針對不同的客戶進行分層運營,也是這個道理。

平常我們所說的分析和綜合的背后,其實就是分類能力。分析是在一個類里面找差異性,綜合是在不同事物中找聯系、找共同性,而這個共同性相當于分類的維度。

分類思維的能力,直接體現的就是看透事物本質的能力。

應用架構中的分類思維

概念定義

在討論架構之前,我們先來明確一下Module、Component和Package這幾個概念。

因為這些概念一直以來存在不小的歧義。通過Stack Overflow上幾十篇詢問這些概念差異的提問,以及五花八門的回答就能可見一斑。

在一篇Stack Overflow的帖子[1]中,我們看到這樣的回答:

The terms are similar. I generally think of a “module” as being larger than a “component”. A component is a single part, usually relatively small in scope, possibly general-purpose.

然而,另一篇Stack Overflow的帖子[2],卻有著不同的答案:

There is n o criteria to measure which one is greater than the other. One component can contain list of modules, and one module also can contain many co mponents.

在《實現領域驅動設計》一書中,作者有這樣的描述:

If you are using Java or C#, you are already familiar with Modules, though you know them by another name. Java calls them packages. C# calls them namespaces.

然而,在AngularJS的設計文檔[3]中,它對Module和Component是這樣定義的:

The module can be considered as a collection of components, Each component can use other components. One of many modules combines up to make an Application.

通過比較,結合我自己的認知,我更贊同AngularJS里面的定義,即Module是比Component更大的概念。比如在Maven中,Module是組成Application的第一級層次,而Component的粒度一般比Module要小,多個Component會組成一個Module。

因此,在進一步探討之前,我特意對這些概念做如下定義:

  • 應用(Application):應用系統,有多個Module組成,用方框表示。

  • 模塊(Module):一個Module是有一組Component構成,用正方體表示。

  • 組件(Component):表示一個可以獨立提供某方面功能的物件,用UML的組件圖表示。

  • 包(Package):Package相對比較tricky,它是一種組織形式,和粒度不是一個維度的,也就是說,一個Component可以包含多個Package,一個Package也可以包含多個Component。

基于上面的定義,他們的表示法(Notation)是這樣的:

應用架構的要素

關于架構的定義有很多,我最喜歡,也是最簡潔的定義是:

即架構是一種結構,是由物件(Components)+ 物件之間的關系 + 指導原則組成的。

應用架構也是如此,從大的層面來說,企業級應用都逃不過如下圖所示的三層結構,即前端、后端和數據庫。

對于后端開發來說,應用層是我們的主戰場,也是整個系統最復雜的部分(當然,前端也不簡單),所有的業務邏輯都匯聚在此。所以,對于應用層,我們需要進行進一步拆分,而不僅僅是在這里寫業務邏輯就完事了。

對應用層的進一步分層,就形成了COLA所提倡的四層結構,對應到Maven中,就是有4個Module,編譯打包之后會有4個Jar。一個典型的應用,其Module呈現出如下的結構:

<modules>?????????<module>cloudstore-adapter</module>?<!--Adapter?層-->??????????<module>cloudstore-app</module>??<!--App?層-->??????????<module>cloudstore-domain</module>??<!--Domain?層-->??????????<module>cloudstore-infrastructure</module>??<!--Infra?層-->??????????<module>cloudstore-client</module>??<!--RPC?SDK-->??????????<module>start</module>??<!--SpringBoot啟動-->??</modules>?

當業務變得復雜時,這種分層結構自然比沒有分層要好。這也是COLA一直致力要去解決的問題——控制復雜度。

從COLA 1.0的事無巨細,到COLA 3.0的化繁為簡。我漸漸明白,COLA作為應用架構,其核心不是去提供功能,而是提供基模(Archetype)。

在1.0的時候,COLA提供了Interceptor能力,提供了Event Bus能力,提供了擴展點能力。一個是我認為大家“需要”這些,另一個是感覺NB的框架就應該面面俱到,沒有幾個高級功能都不好意思開源。事實證明,我犯了一個慣性錯誤——過度設計。Interceptor完全可以用AOP替代,內部事件和擴展點很少被用到。所以在COLA 3.0的時候,果斷的去掉了這些“雞肋”,只保留了擴展點功能。

回歸到架構的本質,COLA的核心應該是規定應用的結構和規范,即應用架構基模(Archetype)。而不是去糾結那些錦上添花的功能。

升級到COLA 3.1

實際上,這樣的回歸工作,COLA 3.0已經做的差不多了。在這次3.1的升級中,除了進一步去除了Event Bus的功能之外,最重要的就是重新規范了分包策略,和擴充了原來控制層(Controller)的職責。

分包策略調整

分層是一種在功能維度上的橫向切分,即每一層都有自己的職責。

  • Adapter層:路由用戶request + 適配response。

  • App層:接收請求,聯合domain層一起做業務處理。

  • Domain層:領域模型 + 領域能力。

  • Infrastructure層:技術細節(DB,Search,RPC…) + 防腐(Anti-corruption)。

分層處理沒有問題,只是這種功能劃分,會帶來一個問題,即領域維度的內聚性會收到影響。當一個application只負責一個領域的時候沒有問題。然而,當一個application包含多個業務領域的時候,這種內聚性缺失的弊端就比較明顯了。

更好的分包策略是按領域劃分,而不是按功能。因為,領域更內聚,功能是為領域服務的,應該歸屬于領域。

然而,不巧的是,在COLA應用架構里面,我們要綜合橫向功能維度的劃分,和縱向領域維度的劃分,兩個都很好,兩個都想要。怎么辦?我們可以采用物理劃分和邏輯劃分相結合的辦法。

橫向上,我們用Module做有層次劃分,屬于物理劃分。縱向上,通過Package來進行邏輯劃分。最后,形成一個如下的結構:

按照這個思想去分包,在工程中,Module下的頂層package不再是功能,而是領域:

按照領域的分包策略至少會帶來兩個好處:

  • 系統的可理解性和可維護性更好,用白話說,就是找東西更好找了。

  • 方便以后的拆分,比如下單域(Order)變得越來越復雜,需要拆出去,我們只需要把Order下面的東西遷移到一個新應用就好了。

用Adatper代替Controller

Controller這個名字主要是來自于MVC,因為是MVC,所以自帶了Web應用的烙印。然而,隨著mobile的興起,現在很少有應用僅僅只支持Web端,通常的標配是Web,Mobile,WAP三端都要支持。

在這樣的背景下,狹義的控制層已經不能滿足需求了,因為在這一層,不僅僅要做路由轉發,還要做多端適配,類似于六邊形架構中的Driving Adapter的角色。鑒于此,我們使用適配層(Adapter)替換掉了Controller,一方面,是為了呼應六邊形架構;另一方面,的確也是需要做多端適配。

基于這樣的變化,我重構了COLA Archetype,把Adapter作為一個層次凸顯出來。實際上,Infrastructure也是適配器,是對技術實現的適配(或者叫解耦),比如,我需要數據來幫助構造Domain Entity,但是我不care這個數據是來自于DB、RPC還是Search,或者說,我可以在這些技術實現中進行自由切換,而不影響我Domain層和App層的穩定性。

改造后的COLA在架構風格,模塊、組件以及分包策略上都會有所調整,具體變化請參考下面兩張圖。

COLA架構圖:

COLA3.1

COLA組件關系圖:

組織架構中的分類思維

這么重要的思維能力,其應用肯定不僅僅局限于架構設計的范疇。開篇已經說過了,分類是我們人類的本能,是分析和綜合問題的重要手段。

生產關系決定生產力,好的組織結構會助力業務發展,反之,則會拖業務的后退。因此,大公司的CEO每年都會花很多時間在組織設計上,這也是為什么,在大廠,每年我們都會看到不小的組織調整。

看到一篇文章《蘋果公司的組織架構是怎樣的》[4],里面介紹了蘋果成功和其優秀的組織架構有關系。如下圖所示,傳統企業偏向于業務型組織,而高科技企業偏向于職能型組織。

image

有沒有感覺蘋果的組織架構,和我們的COLA思想是一樣的:),物理上,按照職能劃分;邏輯上,按照業務和產品劃分。

蘋果這樣的組織設計,是因為它是技術和創新驅動的公司,協作成本不是最大的問題,缺少專業性(技術不行),缺少創新才是攸關生死的大問題。所以他寧肯犧牲協同效率,也要確保專業性,也就是說,做攝像頭的只做攝像頭,做iOS的只做iOS,技術leader直接向CEO匯報,可以決定產品的發展方向。因為他們在這個領域更專業。

很早以前,史蒂夫·喬布斯就有這樣的觀點:蘋果公司的經理們應該是他們管理領域的專家。在 1984 年的一次采訪中,他說:

我們在蘋果經歷了那個階段,當時我們出去想,哦,我們要成為一家大公司,讓我們雇傭專業的管理人員。我們出去雇了一群專業的管理人員。一點也不管用……他們知道如何管理,但他們在專業方面什么都不知道。如果你是一個偉大的人,為什么你想為一個你什么都學不到的人工作?你知道什么是有趣的嗎?你知道誰是最好的經理嗎?他們是偉大的個人貢獻者,他們從來都不想成為一名管理者,但卻決定自己必須成為,因為沒有其他人能夠出色地完成工作。

說實話,看完這篇文章,我很感慨,一方面是佩服喬布斯的洞見能力,另一方面也為我們這個行業感到唏噓,業務技術也是技術啊,卻沒有一個像樣的培育發展技術的環境和土壤。

如今,業務技術Leader還有多少是專注在技術上呢,儼然都變成了業務Leader。如果技術Leader都變成了純管理者,那么誰去關心技術,誰去關心代碼,誰去關心工程師的成長呢?

分類學是科學也是藝術

最后,我還是要中庸一下,分類很重要,但同時也很難,帶有一定的主觀性。就像比爾.布萊森在《萬物簡史》里說的:

分類學有時候被描述成一門科學,有時候被描述成一種藝術,但實際上那是一個戰場。即使到了今天,那個體系比許多人認為的還要混亂。以描述生物基本結構的門的劃分為例。許多生物學家堅持認為總數30個門,但有的認為20來個門,而愛德華在《生命的多樣性》一書里提出的數字高達令人吃驚的89門。

我們觀察事物的視角不同,對問題的認知程度不同,得出來的分類也會不同。就拿COLA來說,直到現在的3.1版本,我個人認為其分層和分包的方式才相對比較合理。然而,很有可能在后期的迭代中,分類方式又會改變。

組織架構的分類方式也是一樣,按照業務和職能劃分,都可以。關鍵看其分類是否匹配你組織的特性,沒有最好的分類,只有最合適的。

面試準備+復習資料分享:

為了應付面試也刷了很多的面試題與資料,現在就分享給有需要的讀者朋友,資料我只截取出來一部分哦,有需要的可以來找我獲取哈

獲取方式:點擊藍色字體即可免費獲取

秋招|美團java一面二面HR面面經,分享攢攢人品

合適的。

面試準備+復習資料分享:

為了應付面試也刷了很多的面試題與資料,現在就分享給有需要的讀者朋友,資料我只截取出來一部分哦,有需要的可以來找我獲取哈

獲取方式:點擊藍色字體即可免費獲取

[外鏈圖片轉存中…(img-sKDIcF6O-1627017679002)]

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/385525.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/385525.shtml
英文地址,請注明出處:http://en.pswp.cn/news/385525.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

有名管道

一、有名管道 1. 為何提出有名管道的說法&#xff0c;目的是為了克服無名管道的不足之處&#xff1a; 無名管道只能是用于具有親緣關系的進程之間&#xff0c;這就限制了無名管道的使用范圍。有名管道可以使互不相關的兩個進程互相通信&#xff0c;有名管道可以通過路徑名來指…

Java進階:mysql的事務隔離級別面試題

一面&#xff1a; 阿里巴巴面試答案文末可以領取&#xff01; 1. 觸發新生代GC&#xff0c;如果存活對象總量大于survivor區容量&#xff0c;咋辦 2. 如果任務很多&#xff0c;線程池的阻塞隊列會撐爆內存的哪個區域 3. 棧在堆上嗎 4. GC root有哪些 5. 實例變量可以是GC…

有名管道(二)

一、從FIFO中讀取數據&#xff1a; 約定&#xff1a;如果一個進程為了從FIFO中讀取數據而以阻塞的方式打開FIFO&#xff0c;則稱內核為該進程的讀操作設置了阻塞標志。 如果有進程為寫而打開FIIF&#xff08;寫端存在&#xff09;&#xff0c;且當前FIFO內沒有數據&#xff0…

Java面試2021,java數據可視化項目

AOP簡介 AOP (Aspect Oriented Programing) 稱為&#xff1a;面向切面編程&#xff0c;它是一種編程思想。AOP 是 OOP&#xff08;面向對象編程 Object Oriented Programming)的思想延續 AOP采取橫向抽取機制&#xff0c;取代了傳統縱向繼承體系重復性代碼的編寫方式&#xff0…

gcc的使用

一、gcc編譯過程示意圖 分析&#xff1a; hello程序是一個高級&#xff23;語言程序&#xff0c;這種形式容易被人讀懂。為了在系統上運行hello.c程序&#xff0c;每條&#xff23;語句都必須轉化為低級機器指令。然后將這些指令打包成可執行目標文件格式&#xff0c;并以二進…

Java面試2021,java黑馬百度云

線程是否要鎖住同步資源 鎖住 悲觀鎖不鎖住 樂觀鎖 鎖住同步資源失敗 線程是否要阻塞 阻塞不阻塞自旋鎖&#xff0c;適應性自旋鎖 多個線程競爭同步資源的流程細節有沒有區別 不鎖住資源&#xff0c;多個線程只有一個能修改資源成功&#xff0c;其它線程會重試無鎖同一個線…

gdb使用

[sunbinlocalhost ~]$ gcc -Wall -g simple.c -o simple [sunbinlocalhost ~]$ ./simple Entering main ... result[1-100] 5050 result[1-10] 55 Exiting main ... [sunbinlocalhost ~]$ gdb simple 啟動gdb GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-110.el7 Copyrigh…

oppoJava面試題,java聲明全局變量的關鍵字

螞蟻一面 ??就做了?道算法題&#xff0c;要求兩?時內完成&#xff0c;給了?度為N的有重復元素的數組&#xff0c;要求輸出第10?的數。典型的TopK問題&#xff0c;快排算法搞定。算法題要注意的是合法性校驗、邊界條件以及異常的處理。另外&#xff0c;如果要寫測試?例&…

System V 消息隊列

一、System V 消息隊列 有一個隊列&#xff0c;隊列存放各種消息。每個進程可以把數據封存在消息中&#xff0c;再放入隊列。每個進程都可以拿到消息隊列&#xff0c;再從中取出/放入消息。 消息隊列也有管道一樣的不足&#xff0c;就是每個消息的最大長度是有上限的&#xf…

oppoJava面試題,java連接數據庫詳細步驟

美團一面&#xff08;50分鐘左右&#xff09; 進程和線程死鎖的必要條件網絡&#xff0c;七層協議TCP和UDP的區別hashmap 詳細講一下hashmap底層是如何解決hash沖突的hashmap和linkedhashmap數據庫的索引&#xff0c;為什么推薦自增id&#xff0c;有什么優點MySQL的引擎&#…

基本TCP套接字編程

1. socket函數原型&#xff1a; #include <sys/socket.h> int socket(int domain, int type, int protocol);2. bind函數原型&#xff1a; #include <sys/socket.h> int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);參數&#xff1a; ? st…

oppoJava面試題,騰訊社招三面多久聯系

梳理知識點&#xff0c;是快速提升技術的關鍵 前面講過&#xff0c;快速提升自己的技術硬實力其實是有方法的。大致就是梳理知識點夯實基礎進階深入學習實戰&#xff0c;下面我會一點點跟大家剖析&#xff0c;本文干貨滿滿&#xff0c;大家仔細閱讀。 ①梳理知識必備&#xff1…

oppoJava面試!傳智播客java基礎案例教程

零基礎如何學習Java&#xff1f; 首先&#xff0c;你要明白一點&#xff0c;Java入門不難&#xff01; 無論你是從事哪個行業&#xff0c;興趣一定是最好的老師&#xff0c;也是你學習的動力。 學習方式1&#xff1a;自學 自學模式其實我個人不建議絕大部分的人選擇&#x…

Redis高級項目實戰!北京java編程入門培訓

Dubbo面試專題 JVM面試專題 Java并發面試專題 Kafka面試專題 MongDB面試專題 MyBatis面試專題 MySQL面試專題 Netty面試專題 RabbitMQ面試專題 Redis面試專題 Spring Cloud面試專題 SpringBoot面試專題 zookeeper面試專題 最后 給大家送一個小福利 資料都是免費分享的&#xf…

poll函數

#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);參數&#xff1a; fds&#xff1a;監聽的文件描述符【數組】 struct pllfd {int fd; 待監聽的文件描述符short events; 待監聽的文件描述符對應的監聽事件short revents; 傳入時&…

Redis高級項目實戰,java配置jdk環境時

Spring Security觀后感——手繪思維腦(供參考) Spring Security手繪思維腦圖 手繪的思維導圖&#xff0c;是我自己根據自身的情況讀完這套阿里出品的Spring Security王者晉級文檔之后所繪的&#xff0c;相當于是一個知識的總結與梳理&#xff0c;我將其分為***“核心組件”與“…

select函數(一)

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 參數&#xff1a; nfds&#xff1a;監控的文件描述符集里最大文件描述符加1&#xff0c;因為此參數會告訴內核檢測前多少個文件文件描述符readfs&#xff1a;監控有讀…

Redis高級項目實戰,阿里P7級別面試經驗總結

第一次壓測 慘不忍睹&#xff0c;平均響應時間150ms&#xff0c;而且在這次壓測過程中還發現其它的問題&#xff0c;后臺報錯&#xff0c;經查是OpenSearch每秒查詢次數限制 優化代碼與配置 1、修改OpenSearch配置&#xff0c;并且將壓測環境中的OpenSearch連接地址改為內網地…

Makefile用法鏈接

Makefile的編寫及四個特殊符號的意義、$、$^、$ <font face"字體" size"字號" color"顏色">這里是需要突出顯示的內容</font> <font color#0099ff size12 face"黑體">黑體</font>

Redis高頻面試筆記:java版本號比較算法

1.三重心智模型 先給大家科普一個概念&#xff0c;“三重心智模型”。 認知科學家斯坦諾維奇&#xff0c;將人的心智模式&#xff0c;分成了三個部分。 第一層是自主心智&#xff0c;自主心智是我們通過進化與內隱學習獲得。比如&#xff0c;我們看到蛇就會害怕&#xff0c;情…