類圖是怎樣煉成的?
類圖可以用來展示類的結構和與其他類的關系,是一個重要的結構建模的工具。
01
學過UML的人對類圖想必都不陌生,作為結構建模的核心工具,類圖充當著溝通現實世界與概念世界的橋梁。沒有學過UML的同學也不必擔心,在開始正文之前,我會先簡要介紹一下UML和類圖的基本概念。
什么是UML?
通俗地講,UML就是統一建模語言(Unified Modeling Language)。如果說咱們平時用的漢字是幫助日常溝通的,那么UML就是幫助我們將現實抽象化,對其中的結構和行為進行建模。
舉個簡單的例子:你是一個人,現在,你對另一個人說話。在這個過程中,你使用了一種名為交流的功能。而交流,是需要你的喉嚨、鼻腔、舌頭、口腔和嘴唇共同完成的,我們可以把它們統稱為發聲器官,而喉嚨這些小的部件就是發聲器官的結構。
功能是由結構驅動的,而功能在UML中屬于行為建模,由用例圖承擔。產品經理所熟知的用例模板其實是用例圖的補充說明,當然這一塊不在本篇文章的討論范圍之列。我們要討論的,是承擔結構建模的工具——類圖。
上圖是一張典型的類圖,由三部分組成(由上自下):類名、屬性、方法。
如果你是程序員出身,大概對這些很熟悉了——string是字符串,integer是整數,void為空,這些都代表屬性的數據類型。至于“+”和“-”,則代表著公有和私有的區別。
如果你不是程序員,也不用擔心,暫且拋開數據類型和底下的方法,只保留類名和屬性就好。
你可以忽略前面的加號,也可以把它當成一種慣例接受,這都不影響你對類圖本身的使用。
其實類圖本身很簡單,它本身只是把類具象化的一種工具。關鍵是要明白它為什么存在?有什么意義?要怎么用?
要解決這些問題,首先就得明白什么是類。
通俗地講,類就是現實世界的事物在概念世界的映射。
在理解這句話之前,我們需要明白一個隱秘的常識,即所有思維層面的活動都依賴于概念進行,我們不是在對實物思考著;而只是通過把它抽象化成概念,用概念在抽象世界中運行著。
當我們思考人的時候,我們是把人作為一種概念,存儲在自己的腦海里。我說你是一個人,但人本身在現實世界是沒有對應物的,你是人,他也是人,但你不是他,我無法用他來指涉你。
因為實體本身的制約,我們不得不把你和他抽象為一種共同的存在,用這種存在來指涉擁有共同特征的存在。這種存在就是類,而類本身就是一種概念。
拿人來說,人就是你、我、他在概念世界中的映射。換句話說,人就是類。
要知道,我們本來是沒有辦法思考實物的,因為實物就在那兒,我們不可能把它變成我們腦海中的物質材料,像廚子一樣做出一道思維大餐。
可是通過類,我們突然可以分析真實世界了,只要我們將它們抽象化,映射在概念世界就好。
如果我們了解到這一點,就該知道,我們無論要解決何種問題,首先要做的事,就是把問題抽象化、概念化。
當然,當我們將實物抽象化以后,就該用一種可視化的方式將其呈現出來,一來為了與共事者交流,二來我們也可以更輕松地進行邏輯推導——類圖就是一種很好的可視化方式。
如上面所講,簡化版類圖包含兩點:類名和屬性。
之所以有類名,是為了方便人們稱呼它,使這個類從虛無中顯現出來。我們無法稱呼一個沒有名字的存在,更無法去思考它。
畢竟,最虛無縹緲的東西,老子都要強曰道之后,我們才能去探究它。
而光有了名字還不夠,不同的兩件事物,完全可以有相同的名字。譬如你可以叫張三,我也可以叫張三,但我們倆其實是完全獨立的存在。
概念也是如此,單單把“人”提取出來,而不給它任何定義,那么我們怎么能知道“人”和“動物”這兩個類的區別是什么?而屬性,就是給類下定義的方式。
人這個類,有名字,有年齡,還有性別,職業,婚姻關系,住址……
而動物,則有物種,有年齡,有性別,有棲息地……
通過這些屬性,人與動物得以區別。
可是,如果你仔細品味一下的話,會發現人和動物的屬性有重合的地方。諸如年齡、性別什么的,人和動物都有啊。
為什么呢?
這就涉及到類與類之間的關系:繼承。
類與類之間是有簡單和復雜的區分的,而復雜的類往往繼承自簡單的類。譬如你是你父親的兒子,你比他懂得更多,但你也仍然繼承了他的一些特點。
而人和動物,都繼承了來自簡單類——生物的基本屬性。
人與動物,在繼承自生物這塊的屬性上,大同小異,而真正使他們做出區分的,是獨屬于其本身的那部分屬性。譬如人的婚姻關系,動物的棲息地。婚姻關系是社會形態下出現的新型關系,動物是無法演化出來的。同樣,動物的棲息地屬于族群概念,與人的住所(涉及所有權問題)又有天壤之別。
試想一下,倘若棲息地轉化成住所,那么動物的概念就不再適應,而必須演變成一種新的類:家養寵物。正是通過屬性的不同,類本身的區別才能進行精準的回答。
有的讀者看到這里可能會疑惑,我知道了類,對我有什么用呢?
這個問題的回答本來在開頭就應該闡明,但考慮到有的同學并不了解類是什么,因此放到第一部分的結尾來解答。
理由有三:
- 類是一種抽象建模的思維方式,它充當現實世界和概念世界的接口;使用這種方式,能讓我們在世界觀的層面上革新我們的方法論。
- 類屬性對于構建產品的信息結構有重要作用;一個產品呈現何種信息,取決于產品制作者對于類屬性的識別和定義。
- 類的識別決定著后端的數據用幾張表儲存,類屬性則決定著表上按照何種方式進行索引,或能否可以索引到,數據庫的建設關系產品穩定性以及后續的數據分析;如果產品制作者在一開始對類的定義模糊,那么后端在不清楚業務邏輯的情況下所采取的存儲方式往往會不如人意。
如果看到這里你覺得有必要進行類的學習,那么可以繼續看下去,第二部分我會著重分析一下如何進行類的定義。
02
這一部分主要談類的定義。
其實在定義之前還有一個步驟,即類的識別。但在多數的場景下,識別是一件自然而然的事情。譬如你看到一個發光以照明的存在,會把它識別為燈;看到四輪驅動的存在,會把它識別成車。
這些都已經是我們的經驗所內化的近乎反射的能力,唯一需要注意的,或許只是類的粗細層級。譬如你識別出照明物是燈,但燈也可能是白熾燈、LED燈等等。后者繼承自前者,但又具有自身的特性,這時候就需要你結合自身的業務場景進行合理區分。
如果燈是商品,那么識別到白熾燈這一層級是有必要的。如果燈只是作為場景中的輔助道具,譬如“你回到家,打開燈”;在這個場景中,燈只是為了照亮屋子的輔助道具,就沒有必要區分是白熾燈還是LED燈。
如果你把后者識別到白熾燈的級別,那么后端就不得不存儲多余的一列以區分它與其他燈的區別,從而造成了信息冗余和資源浪費。
因此在識別類的過程中,要記住兩點:
- 確定類之間的繼承關系;
- 圍繞業務場景確定使用哪個類,兩者為前后順序。
識別完類之后,就涉及類的定義了。
類的定義通過定義類屬性表現出來,運用最典型的例子就是游戲中的人物屬性。
(圖一)
(圖二)
- 圖一是射擊類游戲的人物屬性面板,該人物屬性包括角色類型、生命值、防御力和戰斗力;
- 圖二是RPG類游戲的人物屬性面板,該人物屬性包括角色名稱、等級、生命、內力、基礎屬性、詳細屬性和戰斗力。
同樣是對于人物的類定義,可是兩者的屬性定義卻截然不同:在射擊類游戲中作為原子單位的防御力;在RPG中就要分為物防和法防,并且后者還多出了內力、物攻、法攻等其他屬性。
如果你已經弄懂了類的繼承,可能會說,它們各自在簡單類——人物的基礎上發展出了新的類,圖一是槍械師類,圖二是弓箭手類。
當然有道理,可是值得思考的是:為什么圖一沒有發展出槍械親和力、開槍速度這樣的屬性呢?為什么僅僅有一個戰斗力屬性呢?
一個重要的原因在于:屬性本身也是有粗細的。
粗屬性可以分解為細屬性,細屬性也可以分解為粗屬性。屬性的粗細與否,跟產品的核心路徑有關。譬如上面的射擊類游戲,玩法本身不依靠屬性加成、削弱,所以識別到戰斗力屬性即可;而RPG游戲,則更依靠屬性間的配比,所以識別更細致一點。
但這并不意味著在進行屬性識別時,一開始就要從粗的來。MECE原則告訴我們,要從不同角度窮盡可能性。如果一上面就識別粗的層面,很有可能漏掉很多細節。
因此,最好的方式,是一開始將所有細的屬性全部識別出來,再結合產品邏輯進行整合。這樣做雖然更累,但也會使你對類本身進行更深入的思考。
上面我們談到MECE法則,該法則的第一要點就是從不同角度。意思是,我們在進行頭腦風暴時,依靠窮舉法,最后總結歸納;但一味地窮舉并不能很好包含所有可能性。
有時候往往只是一個方向上的多重反復。因此在進行窮舉之前,必須要先想好一共有哪些角度可以進行思考。
類也是一樣,我們必須思考定義類的屬性,本身都有哪些類別,其依靠何種方式而對定義類有所貢獻。
總體而言,類和屬性都可以有兩種分法:
- 類:實體類、抽象類;
- 屬性:指涉自我、與其他元素交互。
所謂實體類和抽象類,差別在于它們在現實世界有無對照物。
譬如水,水本身在概念世界中是一個抽象化的概念,但它在現實中有具體的實指——一種可以喝的、看得見、摸得著的存在。因此,水是實體類。
而如知識,本身是看不見摸不著的,它沒有實物的依存;只能通過概念世界產生,并且只能在概念世界運行。因此知識是抽象類。
區分實體類和抽象類的重要意義在于:確定屬性窮舉的基本維度。
實體類的基本維度是時間和空間。
水,從時間角度思考,可以確定其流速;從空間角度思考,可以確定其體積。
抽象類的基本維度是聚合。
知識本身是虛無縹緲的,但它有類型,可以分為語文知識、數學知識、物理知識;抽象類不是識別出來的,而是聚合出來的。
它是你遇到實類之后,根據業務需要,抽象出來的統籌概念。就像知識一樣,如果你的產品中有一個模塊,需要放語文、數學等各科內容,那么這時候你就需要抽象化出知識的概念作為內容的統稱。
不妨這樣理解,抽象類是一群實體類的最大公約數,它建立在先識別并定義好實體類之上。
接下來看屬性。
所謂指涉自我,其實就是事物本身蘊含的,不需要借助其他元素呈現出來的狀態。
桌子的屬性,可以是面積、新舊程度、占地空間、材質,這些都是它本身自帶的。
但是諸如品牌,是桌子與生產商交互的結果;諸如承重力,是它與放置其上的事物交互的結果。沒有其他元素的參與,桌子本身無法實現屬性的生成。因此,像品牌、承重力這些,則屬于與其他元素交互。
實際上,現實中的絕大部分事物,指涉自身的屬性很少,絕大部分的屬性都是在和其他元素交互中產生的。
拿人來說,身高、體重、姓名、年齡是指涉自身的屬性,但社會關系、工作狀態這些,卻都要借助其他元素生成。
交互屬性是屬性中最難把握的一塊,因為它沒有固定的痕跡,所生成的屬性取決于交互的對象。就像氧氣一樣,遇到氫氣,可以變成水;在吸熱反應下,可以變成臭氧。
因此,涉及交互屬性時,著重點是要根據業務需求,找到所交互的對象。
還是拿商品舉例子,如果桌子是一件商品,那么它的交互對象只需要限定在買賣雙方:從賣家的角度考慮,需要為桌子指定價格,指明庫存量;從買家的角度講,需要知道桌子的品牌、大小、承重力。
當然,買家角度的屬性還包括了指涉自身的屬性,但從更廣延的角度考慮,我們是可以用關系鏈的視角去看待以上的問題。
另外,也許你已看出了,指涉自身的屬性一般都屬于實體類的視角:時間和空間。而交互屬性則有點抽象類的意味。
實際上,這兩類四種視角,本身既有重疊,又有不同。關鍵是要結合業務,確定類別,再依據自身與交互確定方向。
類圖本身當然還有討論的空間,以上也只是一家之言。限于筆力和經驗,本篇文章到此就告一段落了。
希望有經驗的伙伴能分享自己的經驗,對文章中的謬誤之處也請不吝批評。
感謝閱讀。
#專欄作家#
善寶橘,微信公眾號:善寶橘,人人都是產品經理專欄作家。一個崇尚終身學習的互聯網斜杠青年,擅長學界理論與業界實踐結合,專注新媒體、游戲領域的運營策劃。當然,偶爾會寫點互聯網時事評論。
本文原創發布于人人都是產品經理。未經許可,禁止轉載。
題圖來自 Unsplash,基于CC0協議。
翻了翻作者的文章 ,只有這一篇寫UML的,而且寫的很好,好在獨到。也易理解,而不是bd上搜出來千篇一律的。
加油啊,再寫個用例圖的。
中間關于實體和概念之間的關系寫得很生動。和一篇很精彩的叫做《意識上傳中》的科幻小說中應用到的觀點非常一致。
所以,最后桌子的品牌這個屬性,是放在桌子這個類里面,還是另起一個品牌類?
奇怪,這么好的文章為什么沒人評論啊。
寫的很好,就是感覺作者偷懶了,沒寫完,缺少后面的 類與類之間關系的詳盡說明 和 具體如何畫類圖。。。
看到這篇文章想到了從前做開發的影子 QAQ