產(chǎn)品經(jīng)理,你居然不懂高內(nèi)聚和低耦合?看我怎么教會你
編輯導(dǎo)語:聊起系統(tǒng)架構(gòu)時,架構(gòu)師們總是喜歡提及“高內(nèi)聚”和“低耦合”,這在系統(tǒng)設(shè)計中是十分重要的概念,也是產(chǎn)品經(jīng)理需要進(jìn)行學(xué)習(xí)和思考以推動業(yè)務(wù)更好開展的必備技能點。作者用生動的故事作為案例,分享了他對于高內(nèi)聚和低耦合的理解,一起來看。
在和架構(gòu)師們討論系統(tǒng)設(shè)計時,總是能處處聽到“高內(nèi)聚”和“低耦合”的聲音,仿佛這就是技術(shù)和產(chǎn)品之間的一道墻,初級和高級之間的一條溝。但如果了解了它們的原理,也就不那么神奇了,要知道,這兩個詞并不是研發(fā)專用。作為產(chǎn)品經(jīng)理,我們對這兩個詞的理解甚至可以比架構(gòu)師們更寬廣,拽起概念來可以比他們更酷。
本文木筆用一個故事開始,再用一個故事結(jié)束,和你聊聊我眼里的高內(nèi)聚和低耦合,往下看!
聊起系統(tǒng)架構(gòu)時,架構(gòu)師們總是喜歡把“高內(nèi)聚”和“低耦合”掛在嘴邊,一副拽拽不可一世的姿態(tài),讓不懂的人聽的一愣一愣的,仿佛這就是技術(shù)和產(chǎn)品之間的一道墻,初級和高級之間的一條溝。那到底什么是高內(nèi)聚和低耦合,對系統(tǒng)設(shè)計又有什么影響?其實,了解它們的原理以后,也就不過如此。
今天,木筆從一個美好的北漂故事說起,聊聊我自己對這兩個詞兒的理解,相信你看完本文以后,也能和這些架構(gòu)師互拽一下了,而且,產(chǎn)品經(jīng)理眼中的高內(nèi)聚和低耦合不應(yīng)該局限在系統(tǒng)設(shè)計本身,還應(yīng)該向更源頭的業(yè)務(wù)方向思考,從業(yè)務(wù)層面做內(nèi)聚和解耦。
在和架構(gòu)師互拽時,我就一個要求,要拽得酷一點,氣勢上一定不能輸,即便臉被打腫,也要保持迷人的微笑和傲人的姿態(tài),不要給咱產(chǎn)品經(jīng)理丟臉。
一、從北京愛情故事說起
故事是這樣開始的:
老陳、老張、老李三人是大學(xué)同學(xué),大學(xué)畢業(yè)后相約一起到北京闖蕩,由于初入社會工資比較低,為了省房租,3個人便一起合租,在一個房間里擺了兩張上下鋪,延續(xù)了大學(xué)宿舍的生活方式,每天下班后就一起喝酒、吹牛、打游戲,周末時間充裕就一起唱歌打球吃火鍋,北漂雖然窮苦,但日子過的好不快活。
這樣快意江湖的日子持續(xù)了三年,三條單身狗各自交了女朋友,偶爾某一位的女朋友過來,其它兩位就要出去避一避風(fēng)頭,很不方便,于是三人一合計,租了一個大的三居室,每個人一間,這樣既能解決女朋友過來小聚的問題,三人也能繼續(xù)一起逍遙。隨著住宿條件的提升,以及小情侶們感情的升溫,為了克服相思之苦,也為了最大化節(jié)省國家資源,小情侶們想方設(shè)法克服重重阻礙同居到一起了,這樣原本3個人的房子里住起了6個人。
自從3個人變成3家6口人以后,原本的快活日子開始慢慢起了微妙變化,起因在于房間的隔音效果不怎么好,而火爆脾氣的老陳和女朋友總是吵架,而且經(jīng)常鬧到大半夜,嚴(yán)重影響了隔壁的老李和老張,時間一長,兩家小媳婦兒就有意見了。加上三家也經(jīng)常因為廚房和衛(wèi)生間的使用發(fā)生沖突,小媳婦兒們之間的事情,處理起來再也不像以前3個大老爺們那么簡單粗暴了,一旦處理不好,后果大家都懂……
半年以后,為了避免女友之間的矛盾進(jìn)一步加大變得不可開交,老張、老李和老陳最終決定不再續(xù)租,三人各自帶女友出去租單間了,周末有空才到一起聚會。這樣一來,雖然老陳還是經(jīng)常和女友吵架,依舊睡的晚,但三家合租時候遇到的所有的問題都就此化解了,沒有了沖突,三位女友見面以后反倒比之前合租時更加親切了……
故事講完了,如果你也曾有過幾位類似的室友和經(jīng)歷,那么你無疑是幸運的,因為那些恰同學(xué)少年一起合租的日子就像曇花,美妙而短暫,那些一起為夢想窮開心的日子終將成為人生旅途中最珍貴的一段回憶,而它也終將隨時光一去不返。
不過本文的重點不是為緬懷青春,而是想從故事中提煉出我們需要的主干:高內(nèi)聚和低耦合。我們從資源分配角度來分析為何最早3個人合租的時候關(guān)系很好,變3家合租以后,就會出現(xiàn)矛盾,而后來各自分開住以后,關(guān)系又變好了呢?先思考3秒鐘….
二、什么是高內(nèi)聚和低耦合
把故事暫放一邊,我們先理解一下什么是內(nèi)聚和耦合。
所謂內(nèi)聚,指某一個事物內(nèi)部各要素之間的緊密聯(lián)系程度。如果相同的要素越集中,說明內(nèi)聚越高,反之則越低。比如人身體里的五臟六腑,彼此之間從出生就相互協(xié)作,如果換成其他人的器官,就會出現(xiàn)排斥現(xiàn)象,這就是高內(nèi)聚。
所謂耦合,指不同事物之間的依賴性。如果彼此的依賴性越強,說明耦合性越高,反之則越低。還拿人體舉例,心臟負(fù)責(zé)供血,肺負(fù)責(zé)呼吸,肝臟負(fù)責(zé)代謝,彼此之間分工明確,各司其職,即便某一部位生病了,只需要針對性治療,不影響其它部位,這就是低耦合。
了解完概念以后,我們再回來分析一下故事的結(jié)局:為何最早3個人合租的時候關(guān)系很好,變3家合租以后,就會出現(xiàn)矛盾,而后來各自分開住以后,關(guān)系又變好了呢?
答案揭曉:最初3個人合租時,省錢最重要,人少感情鐵,事情簡單,所以不會有大的矛盾。而變成3家以后就成了3個不同的家庭,每個家庭的計劃和訴求不一樣,省錢已經(jīng)不是第一訴求了,同在一個屋檐下,老陳和女朋友的家事免不了會影響到老張和老李兩家,加上大家平時共用廚房、衛(wèi)生間等公共資源,只要一家在使用,其它兩家就會受到影響,而老陳、老張、老李的女朋友之間并不像他們?nèi)酥耙粯由顔我磺矣兄詈竦母星榛A(chǔ),久而久之,自然就出現(xiàn)矛盾了。
最后隨著三家分開以后,自己過自己的生活,再也不會影響到其它兩家,矛盾自然就沒有了,隨著偶爾的聯(lián)絡(luò)聚會,還會增進(jìn)彼此的感情。
▲老陳、老張和老王的合租
這就是高內(nèi)聚和低耦合的原理。最初三人合租時,人少、有感情基礎(chǔ),省錢第一,不存在內(nèi)聚和耦合問題;三家6人合租時,彼此之間依賴太多,任何一家的舉動都會影響到其它兩家,耦合性太高,所以容易出問題;分開以后,每家獨自負(fù)責(zé)自己的生活,不再依賴別人,內(nèi)聚性變高了,同時只有周末才會相互聯(lián)絡(luò),耦合性降低了,所以關(guān)系更親近了。
看看,是不是和我們的系統(tǒng)設(shè)計一樣一樣的?當(dāng)系統(tǒng)很小時,為節(jié)約資源,大家在一起共用一套資源,這樣效率最高,而隨著系統(tǒng)和團隊的復(fù)雜度逐漸提升,彼此之間的依賴越來越高,就會經(jīng)常出現(xiàn)資源問題和發(fā)展瓶頸,到最后,為了解決耦合性高的問題,只能對系統(tǒng)和團隊進(jìn)行拆分,各司其職,最終演變成了標(biāo)準(zhǔn)的高內(nèi)聚和低耦合模型。
三、如何實現(xiàn)高內(nèi)聚和低耦合
從定義上,我們應(yīng)該清楚了高內(nèi)聚和低耦合其實說的是兩件事,一件事對內(nèi)(高內(nèi)聚),一件事對外(低耦合)。站在產(chǎn)品的視角,高內(nèi)聚和低耦合不應(yīng)該只局限于系統(tǒng)設(shè)計層面,那樣就顯得比較狹隘了,正確的解讀應(yīng)該立為業(yè)務(wù)和系統(tǒng)兩個層面。
▲高內(nèi)聚與低耦合示例
1. 業(yè)務(wù)層面
無論是業(yè)務(wù)部門的責(zé)任分工、流程的規(guī)劃和設(shè)計,還是作業(yè)現(xiàn)場的管理,都需要遵循高內(nèi)聚和低耦合,我們應(yīng)該盡量將相同的職能、流程和運營工作盡量集中式管理,而不同職能、流程和運營之間責(zé)任和邊界清晰,溝通協(xié)作順暢且不相互影響,具體體現(xiàn)為:
(1)各部門和崗位分工明確,各司其職。例如采購、倉儲和配送,雖然交集很多,但在定人定崗時,就應(yīng)該是不同的崗位角色,即便有的公司很小,可以一人身兼數(shù)職,但也要清楚,只是一個人做了多個崗位的事,而不是多個職能融合成了一個崗位。
(2)各項流程清晰,職責(zé)單一。在設(shè)計業(yè)務(wù)流程時,應(yīng)該考慮單一職能原則,每套流程解決一個核心業(yè)務(wù)場景,雖然很多時候人和功能可以復(fù)用,但在流程和規(guī)則層面還是要分開設(shè)計,不要混在一起。例如銷售出庫和退供應(yīng)商出庫,雖然都是出庫,系統(tǒng)功能和操作人都可以復(fù)用,但出庫的對象不同,應(yīng)該視為兩種業(yè)務(wù)流程。
(3)現(xiàn)場管理規(guī)章明確,流向清晰。在倉儲中心、物流中心的現(xiàn)場管理時,需要按照不同崗位、不同商品和不同業(yè)務(wù)形態(tài)規(guī)劃庫區(qū)、動線流向,制訂規(guī)章制度,例如收發(fā)貨區(qū)域管理、整件和散件區(qū)域管理、大件區(qū)和中小件區(qū)域管理等,讓每個流程對應(yīng)不同的規(guī)則,每個區(qū)域負(fù)責(zé)不同的存儲形態(tài),每個崗位操作不同的業(yè)務(wù)單據(jù),彼此之間能無縫銜接卻又不相互干擾。
2. 系統(tǒng)層面
在做系統(tǒng)設(shè)計時,需要保證相同的系統(tǒng)和功能模塊盡量內(nèi)聚,系統(tǒng)和功能模塊之間盡量解耦,體現(xiàn)為:
- 系統(tǒng)和模塊職能單一,邊界清晰。在規(guī)劃系統(tǒng)時,應(yīng)該做到每個系統(tǒng),以及每個系統(tǒng)下的每個功能模塊都有很清晰的職責(zé),核心職責(zé)只有一個,并且和其它模塊之間有比較清晰的邊界,避免模棱兩可。例如庫存模塊負(fù)責(zé)處理所有庫存相關(guān)事宜,入庫模塊負(fù)責(zé)處理入庫業(yè)務(wù)流程,二者的邊界在入庫上架時對庫存的處理,由入庫模塊觸發(fā),庫存模塊做執(zhí)行。
- 數(shù)據(jù)和邏輯統(tǒng)一,唯一主責(zé)方。每個數(shù)據(jù)和邏輯的操作應(yīng)該只有一個主責(zé)方,當(dāng)其它模塊需要操作此數(shù)據(jù)時,應(yīng)該由此模塊授權(quán)并通過接口服務(wù)的方式互通,如此可以最大化的保證數(shù)據(jù)和功能的完整和安全。例如入庫和出庫都需要操作庫存,但庫存的邏輯統(tǒng)一由庫存模塊來處理,出入庫操作庫存需要通過庫存模塊提供的接口來交互,千萬不要把庫存的處理直接交給入庫和出庫模塊來各自處理。
- 與盡量少的系統(tǒng)交互,降低系統(tǒng)之間的復(fù)雜性。參考軟件設(shè)計原則里的迪米特法則:只與你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers),盡量避免多個系統(tǒng)之間相互交互,形成了笛卡爾積和網(wǎng)狀結(jié)構(gòu)。比如上方有3個ERP,都需要要與下方的3個WMS系統(tǒng)做交互,這個時候就應(yīng)該考慮通過一個中間的系統(tǒng)來對上承接3個ERP,對下對接3個WMS系統(tǒng),不要讓每個ERP分別與每個WMS形成笛卡爾積。
當(dāng)然,高內(nèi)聚和低耦合的設(shè)計雖然看起來更合理,但在實現(xiàn)時還是要因時制宜,因為高內(nèi)聚和低耦合的實現(xiàn)一定會帶來人力成本和系統(tǒng)實現(xiàn)成本的增加,就像北漂故事中一樣,老陳老張和老李三家分開以后,確實實現(xiàn)了高內(nèi)聚和低耦合,但每個人都需要自己租單間,還需要置配生活用品和廚房用具,總成本一定比合租時要高,比起最初三人合租一間房時就更高得多了。
在設(shè)計流程和系統(tǒng)時,我們應(yīng)該根據(jù)實際情況來定奪,沒必要照本宣科過度設(shè)計,在此,木筆提供幾個思考建議:
- 系統(tǒng)設(shè)計來源于業(yè)務(wù),做系統(tǒng)的內(nèi)聚和耦合之前,先從業(yè)務(wù)層面進(jìn)行梳理,讓業(yè)務(wù)先做好高內(nèi)聚和低耦合,很多時候問題不是出在系統(tǒng)上,而是業(yè)務(wù)側(cè)沒有做好內(nèi)聚和解耦。
- 當(dāng)業(yè)務(wù)發(fā)展初期,流程和系統(tǒng)相對簡單且未來尚不清晰時,需要快速試錯,可以不用太考慮內(nèi)聚和耦合(適當(dāng)兼顧就行),先以成本最低的方式支持業(yè)務(wù),等業(yè)務(wù)慢慢清晰以后再繼續(xù)調(diào)整也不遲,千萬不要過度設(shè)計,用10萬單的規(guī)模架構(gòu)太承接1000單的業(yè)務(wù),實打?qū)嵉睦速M。
- 如果業(yè)務(wù)相對穩(wěn)定,長期不變,適當(dāng)耦合會更合理,比如商品的基本屬性、訂單的關(guān)鍵信息、地址庫信息等,沒必要為了低耦合,每次都做接口交互,這樣比較浪費性能。
- 當(dāng)業(yè)務(wù)體量和團隊規(guī)模都很小時,適合合租模式,一套系統(tǒng)中考慮按模塊做高內(nèi)聚和低耦合最合理;而當(dāng)業(yè)務(wù)規(guī)模較大時,適合分開自住模式,分成多套系統(tǒng),各系統(tǒng)內(nèi)部高內(nèi)聚,系統(tǒng)間低耦合更合理。
四、小Q的故事分享
最后,我們分享一個小Q的故事來加強對高內(nèi)聚和低耦合的理解。
小Q最近有點煩,事情經(jīng)過是這樣的:
上個月自己剛?cè)肼毩薢公司負(fù)責(zé)倉儲系統(tǒng)的產(chǎn)品工作,剛?cè)肼毦陀龅角叭萎a(chǎn)品經(jīng)理離職,兩人在交接的過程中才知道這套WMS系統(tǒng)是前不久才開發(fā)上線的,但因為系統(tǒng)問題較多,導(dǎo)致系統(tǒng)庫存記錄的嚴(yán)重不準(zhǔn),才1個月就產(chǎn)生了1000多萬的賬實差異,而且差異越來越大,已經(jīng)嚴(yán)重影響了公司的銷售,每天被銷售部門、倉儲部門和財務(wù)部門多方逼著解決,前任實在頂不住壓力了,所以才提了離職,后來公司才招了小Q入職……原來如此。如果要評出職場上最坑的事,這種入職即背鍋一定能排進(jìn)前三。
小Q剛開始還沒意識到問題的嚴(yán)重性,直到被倉儲業(yè)務(wù)方在郵件里將盤點差異直接抄送CEO,并點名要求技術(shù)部門為庫存差異負(fù)責(zé)并責(zé)令修復(fù)系統(tǒng)問題,限期1個月。為了不惹火上身,小Q當(dāng)即提出離職,被領(lǐng)導(dǎo)好說歹說挽留下來,并為其增加了績效獎金,因為目前最專業(yè)的人只有小Q了,只能死馬當(dāng)作活馬醫(yī)。重賞之下,兩人商定以1個月為限,領(lǐng)導(dǎo)答應(yīng)給小Q協(xié)調(diào)足夠的資源來解決此問題。
小Q拉上研發(fā)經(jīng)理和測試經(jīng)理成立了專項組,先從業(yè)務(wù)的差異數(shù)據(jù)開始著手,從差異最大的業(yè)務(wù)開始排查,不多久便根據(jù)自己的經(jīng)驗發(fā)現(xiàn)了問題的根本:新的WMS系統(tǒng)研發(fā)團隊都沒有庫存處理相關(guān)經(jīng)驗,在做庫存處理設(shè)計時,都是在各個業(yè)務(wù)模塊中自行處理,各自模塊負(fù)責(zé)自己模塊的庫存加減,直接操作庫存表,這樣看起來各業(yè)務(wù)之間互不干預(yù),似乎很解耦很合理。
但大家都忽略了一個現(xiàn)實:業(yè)務(wù)是并行的,在入庫的時還可能在做出庫、盤點等業(yè)務(wù),雖然每個業(yè)務(wù)都是各自開展,但一旦針對某一個SKU同時操作多個業(yè)務(wù)時,庫存的處理就會相互牽制,往往上一個業(yè)務(wù)還沒處理完庫存,下個業(yè)務(wù)又對庫存操作了變更,這就產(chǎn)生了庫存的操作錯亂,所以產(chǎn)生了庫存差異。看起來解耦的設(shè)計,實際上是各種業(yè)務(wù)和庫存的處理高度耦合導(dǎo)致的問題。
▲Z公司的庫存處理現(xiàn)狀
這么嚴(yán)重的問題,測試時為什么沒有發(fā)現(xiàn)呢?因為測試時樣本太少,根本沒有測到這種業(yè)務(wù)并發(fā)的情況。
找到問題根本以后,小Q稍微松了一口氣,根據(jù)經(jīng)驗很快出具了一個庫存解決方案:將庫存的處理單獨抽出來做成公共服務(wù),整個系統(tǒng)只能基于此服務(wù)操作庫存表,保證前一個業(yè)務(wù)加減完成后再執(zhí)行下一個業(yè)務(wù)操作,并記錄詳細(xì)的庫存變更流水日志。
對外則提供公共的庫存的加減公共服務(wù),這樣各倉儲業(yè)務(wù)環(huán)節(jié)只需要處理業(yè)務(wù)邏輯,在需要變更庫存時再調(diào)用庫存服務(wù)完成對庫存的處理,不用再關(guān)注庫存的底層邏輯了,如此才是真正的各業(yè)務(wù)內(nèi)部高內(nèi)聚(每個業(yè)務(wù)只關(guān)注處理自己的業(yè)務(wù)邏輯),業(yè)務(wù)和庫存之間低耦合(通過唯一接口交互)。
▲小Q改造后的庫存處理方案
方案出具以后,技術(shù)團隊用1周時間完成了庫存的重構(gòu),并按照差異大小排序,將各業(yè)務(wù)逐一往新的庫存服務(wù)中遷移,雖然業(yè)務(wù)仍然在天天緊逼,但看著庫存差異在一天天縮小,小Q知道自己的新方案湊效了,如此下去,不到1個月,庫存問題就能得到徹底根治了…
案例也分享完了,以上就是我個人對高內(nèi)聚和低耦合的一些見解了,最后想說的是,高內(nèi)聚和低耦合的設(shè)計只是最終的實現(xiàn)形式,而它們更多的價值體現(xiàn)在我們梳理過程中的一種結(jié)構(gòu)化思維方式,這是一種放諸四海都有用的方法。在做內(nèi)聚時,我們要學(xué)會歸納、抽象,讓相同的業(yè)務(wù)和功能盡量緊湊,在做耦合時,我們要學(xué)會將聯(lián)系比較密切的流程、邏輯和功能拆分、剝離再重組和內(nèi)聚,切忌藕斷絲連。
我的文章分享完了,觀點如上,夠不夠出去拽一下,就看你的了。
#專欄作者#
木筆,產(chǎn)品一俗生,深耕于供應(yīng)鏈領(lǐng)域,微信公眾號:供應(yīng)鏈產(chǎn)品筆記
本文原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載
題圖來自Unsplash,基于CC0協(xié)議
作者寫的文章都很棒啊,大部分的文章,都已簡單易懂的例子帶入,淺入深出,贊。
其實普通產(chǎn)品經(jīng)理只要記住:業(yè)務(wù)高內(nèi)聚,功能低耦合。即在業(yè)務(wù)高度相關(guān)的,在頁面表現(xiàn)層,業(yè)務(wù)流程清晰聚合。功能實現(xiàn)上各個子功能相互獨立,各成單元
老粉了,案例很清晰。給木筆點贊??
還收徒嗎?
內(nèi)聚越高獨立性越高,可以這樣簡單的理解嗎?
每個模塊之間相互聯(lián)系的緊密程度,模塊之間聯(lián)系越緊密,則耦合性越高,模塊的獨立性就越差!反之同理
單模塊聯(lián)系的越緊密(高內(nèi)聚),各模塊之間影響的越少(低耦合)
高內(nèi)聚和低耦合,更多的價值體現(xiàn)在梳理過程中的一種結(jié)構(gòu)化思維方式
您好,想請問一下博主,庫存服務(wù)相當(dāng)于中間介,那具體是怎么設(shè)計邏輯的呢,可能我沒啥經(jīng)驗有點疑惑。是類似隊列出入棧嗎,入庫加庫存是1,出庫減庫存是2,處理順序必須是1-2-3-…。
而在【入庫】的業(yè)務(wù)前端,實際是沒有修改功能的是么,之前是怎么操作刪減庫存的現(xiàn)在還是怎么操作,但不同的是,發(fā)起的請求要經(jīng)過中間介處理后再生效是么,這其中是有等待時間嗎
按我以前做訂單系統(tǒng)的庫存來說,即使下單時是有庫存的,但是實際到配庫環(huán)節(jié)就不一定能有庫存了,是需要通過統(tǒng)一的中間介處理之后再生效的。配庫的時候會根據(jù)下單時間來排優(yōu)先級
我也是這么理解的,讓中間介去解耦,避免同時進(jìn)行加減庫存操作,按隊列執(zhí)行,并且記錄每一行命令用來做業(yè)務(wù)核對
我覺得不是這樣的,如果下單的時候有庫存,最后配庫的時候按時間來排優(yōu)先級,這樣會有一個問題:由系統(tǒng)按照時間來決定訂單的出庫順序,無法讓人按照重要程度決定出庫順序,會非常影響業(yè)務(wù)的。
我理解上公共服務(wù)中心是一個中間件,業(yè)務(wù)出入單據(jù)需要通過中間件去更新庫存,中間件的能力包括:讀取庫存數(shù)、更新庫存數(shù)、更新出入活動記錄。當(dāng)然我只知道能力,具體怎么實現(xiàn)我也不清楚
出入庫單據(jù)通過中間件更新庫存數(shù)的方法對比出入庫單據(jù)直接更新庫存數(shù)的方法的優(yōu)勢是:第一,賬實清晰,第二,減少出入庫庫單據(jù)之間的耦合程度
同感。庫存服務(wù)類似訂單處理中心,所有出入庫訂單統(tǒng)一有它處理,統(tǒng)一調(diào)用。
學(xué)到了!深入淺出,文章寫的很到位,很容易就看懂理解了!