?? ??
馬上就要回北京,兩個月的假期就這樣轉瞬即逝了,一邊修養生息,一邊學習新東西,因為要兼顧修養,因此沒有很固定的時間很有計劃的學習,本來可以就很多學習內容做些總結,也可以做一些學習筆記。但始終也沒有時間來做這些,因為就某一專題具體論述,都要經過細推敲,于是把一些要點總結一下。
假期主要閱讀了下面這些書,由于每本書都很有難度,所以每本都只讀了一半,而且發現看一本書時忽然需要另一本書的概念支持,所以又看看別的書:
1
、
Refactoring
重構,
Martin Fowler
2
、
Design
設計模式。
GoF
3
、
UML
與模式應用
Apply UML and Patterns
,
Craig Larman
4
、
Pro Spring
(在書店看了前兩章)
下面這本看了三遍,而且很多主題經過了反復的研究并進行了實驗
5
、
Spring
從入門到精通,郭峰
下面這本看了兩章,但是做了實驗
6
、精通
SOA
:基于服務總線的
Struts+EJB+Web Service
整合應用開發,梁愛虎
?
1
、面向對象關鍵詞
1.1
領域模型(Domain Model)
領域模型
是對①領域內的概念類或②現實世界中的對象的可視化表示。
[MO95
,
Fowler96]
?
1.1.1
領域模型是個多義詞
在
UP
(更廣泛而言,在
OOA
中)領域模型指的是上面的概念,也就是說它是現實世界中對象的概念透視圖,而非軟件透視圖
(Larman
《
Apply UML and Patterns
》
)
。
對于上面概念的詳細解釋如下,它是對于某個領域(比如醫藥、保險、生產制造等)中的概念類(也就是平常所說的那些抽象概念,如思想、事物或對象。比如銷售、訂貨、指令、商品(在銷售領域叫商品,在生產制造領域就叫產品,在流通領域叫貨品,它們都是抽象概念,這點與蘋果等實際的事物是有區別的)等,它們不是現實世界的東西,而是人們創造的非實物的想出來的東西。)或現實世界中的對象(比如汽車、蘋果)的可視化表示(通常就是用圖形進行表示)。也就是領域模型的概念由兩要素組成:表示的是什么(①領域內的概念類或②現實世界中的對象)和怎么表示(可視化表示)。我們需要注意領域模型的討論語義來討論它。比如在進行
OOA
時,只需要和領域專家(更廣泛的講,接受你調查的需求提供者都應該算作領域專家)進行溝通從純業務的角度來考慮該模型,而不應該摻雜進軟件的思想。
在這個階段,我們創造的是現實世界或領域內的模型,領域之外或現實世界之外的就不要涉及。
?
領域模型的另一個語義則是跟軟件有關了。它指的是
軟件對象的領域層
,在表示層或
UI
層之下的
軟件對象層
是由領域對象組成的——領域對象是表示問題領域空間事物的軟件對象,并且與“業務邏輯”或“領域邏輯”方法相關。例如,軟件類
Board
具有
getSquare
方法。
(Larman
《
Apply UML and Patterns
》
)
。
為避免誤會,在這本書里,
Larman
把該語義下的領域模型稱為領域層(
Domain Layer
)。對象具有屬性和方法,這一點在現實世界或領域內和在軟件語義中是相同的。
?
1.1.2
幾個概念的區別
1.1.2
.1
、領域模型與數據模型
?? Larman《
Apply UML and Patterns》:
領域模型不是數據模型
(通過對數據模型的定義來表示存儲于某處的持久性數據),所以在領域模型中,并不會排除需求中沒有明確要求記錄其相關信息的類(這是對關系數據庫進行數據建模的標準,但與領域建模無關),也不會排除沒有屬性的概念類。例如沒有屬性的概念類是合法的,或者在領域內充當純行為角色而不是信息角色的概念類也是有效的。
從直觀感覺來說,數據模型是指包含數據和數據關系的模型,而領域模型是可以不包含數據的模型。從作用上來講,它們也是完全不同的,領域模型是用來表述領域的概念或現實中的事物的,這些事物或概念不一定要持久化,而數據模型描述的都是需要持久化的數據。
從第二點區別來講的話,就出現兩種開始設計軟件的方法:面向對象和面向數據。長久以來,我們(指的是筆者和筆者所在的團隊以及周圍的團隊)都是采用面向數據的方法開始,也就是先從畫
E-R
圖、設計數據庫結構開始,然后再設計類層次結構,其實這也是沒有辦法的,在學校就是這么學的,也沒有人講過怎么從面向對象開始。而且由于數據庫不是面向對象的,而我們做信息系統的很重要一點是要將數據保存到數據庫。
Apply UML and Patterns
這本書真是堪稱經典,
Larman
將相關概念講的十分通透,而且全書采用兩個例子來傳授敏捷
UP
的實踐過程,并且旁征博引,讓我受益匪淺。這個假期很多知識和思考都來自
Larman
這部著作。
?
1.1.2
.2
、領域模型與設計模型
在這里我們討論的領域模型都是第一個語義下的領域模型,因此它與設計模型的最大區別是一個是面向領域的,一個是軟件的。而領域模型的第二個概念,則主要強調了軟件的領域對象層,這與設計模型也是不完全相同的。對于后一種區別似乎不是很清晰,它們的區別應該著眼于討論范圍的不同。設計模型應該是個更宏觀的概念,而領域層是特指在多層體系結構中的一層(然而在我們現在接觸的很多項目自然就被設計成多層結構的,因此大多數情況下可能體會不到其區別)。
設計模型可以從領域模型(第一個語義)推倒出來,你可以在
Spring
的
Sample
中看到給出的例子含有
model
文件夾,里面包含了重要的領域模型(第二個語義,可以看作是設計模型的一部分)。因為并不是所有的類都是領域層,還有其他的類從其他設計模型轉化而來。
?
1.1.2
.3
、領域模型與領域規則(業務規則)
領域規則
[Ross97
,
GK00]
指出領域或業務是如何運作的。領域規則通常被稱作業務規則,然而兩者是前者包含后者,后者是前者的子集的關系。在領域建模階段,我們會通過捕捉領域規則來捕獲凌駕于特定應用之上的長期規則或政策,例如稅法。(
Larman
《
Apply UML and Patterns
》
)
某些領域模型描述了領域規則,很多領域模型中還有領域規則。
在分層結構中,領域層和業務規則層往往是對應的,比如在
Brown
分層模型、
Marinescu
分層模型中的領域層跟
Core J2EE
分層模型、
DNA
分層模型中的業務層(業務規則層)是對應的。在叫法上斤斤計較是沒有意義的,在這里提一下主要是想明確一下各種概念的區別和聯系。
?
1.1.2
.4
、領域模型(領域層)與
MVC
中的
Model
在《設計模式》中,對
MVC
有如下描述:在
Smalltalk-80
中,類的模型
/
視圖
/
控制器(
Model/View/Controller
)三元組(
MVC
)被用來構建用戶界面。……模型
Model
是應用對象,視圖
View
是它在屏幕上的表示,控制器
Controller
定義用戶界面對用戶輸入的響應方式。在《
J2EE
核心模式》中又詳細地講解了
Model I
和
Model II
,很多書中也都將
MVC
稱為表現層模式。那么這里面的
Model
是不是就是領域模型(領域層)呢?看上去好像就是這么回事。等有時間我再好好研究一下
MVC
,就可以解答這個問題了。
?
1.1.2
.5
、領域模型(層)與常見
Object
VO
(
Value Object
或
View Object
)
這兩個
VO
是怎么回事我沒仔細研究過,最早見到
VO
好像是在
Core J2EE Patterns
里,我的理解是
VO
就是個啞對象,
Struts
中的
Form Bean
就是
VO
,它不是
Model
,不過在《
Spring
從入門到精通》(郭鋒著)將
VO
當成領域模型,在
SpringFramework
的例子里,相似的代碼放在
domain
目錄下,所以我覺得
VO
可能就是個用來傳遞數據的,而不是像在《
Spring
從入門精通》中那樣,當成
domain
。兩套程序都含有
service
目錄,但作用卻不同,在《
Spring
從入門到精通》中它是用來封裝業務邏輯的,而在
springframework
里
jpetstore
中,
service
是來封裝遠程服務的,而在
domain
目錄下的
logic
目錄里的文件是來封裝領域規則的。從前面論述的結果來看,我覺得還是
springframework
例子里的結構比較合理(大師級的作品,經過全世界無數大師的驗證,而且
Rod Johnson
也是敏捷愛好者,不會犯這種錯誤的)。關于
VO
的具體作用,我還是回去重新看看
Core J2EE Patterns
再下結論吧。
還有以前我和很多初學者很疑惑的問題,什么
TO
,
PO
都是干什么的?后來也是看了
Core J2EE Patterns
才知道,
TO
是傳輸對象,主要是用來在
DAO
層和
BLO
層傳遞數據的,而
PO
是持久化對象,主要是用來與數據庫表進行一一映射的。這都屬于設計模式,但是往往被人濫用,不加分別的在同一語境下討論
DM
(
Domain Model
),
VO
,
TO
,
POJO
,
JDO
,造成了初學者的混淆。我覺得
VO
和
PO
分別被包含在了表現層框架和持久層框架中了,表現層框架中那些
FormBean
就應該是
VO
,而
Hibernate
中所謂的那些
POJO
,就是
PO
了,而在各個層次中傳遞數據的對象都可以稱為
TO
了(更廣泛的來講)。
1.2
用例
???
用例是圖形,不是文本。(
P46
)
用例是文本文檔,而非圖形;用例建模主要是編寫文本的活動,而非制圖。(
P47
)
用例就是需求,主要是說明系統如何工作的功能性或行為性需求。(
P48
)
用例是一種優秀的方法,使領域專家或需求提供者自己編寫(或參與編寫)用例成為可能,并使這項工作難度降低。用例的另一個價值是強調了用戶的目標和觀點。(
P48
)
我們經常發現,用例建模新手(或具有嚴重
A
型行為的分析員)過于關心那些次要的問題,比如用例圖、用例關系、用例包等,而不是致力于簡單的編寫文本情節的實際工作中。
(
P48
)
??????????????????
????????
——
Larman
《
UML
和模式應用(原書第
3
版)》(機工)
第一次看到
Larman
的這些話,我仿佛找到了一個出口,因為以前進行系統分析時,總覺得用例圖往往只是個擺設,因為它所能涵蓋的內容太少了,操作契約、條件分支(在
UP
中叫擴展,那時候不知道有什么主成功場景的說法,然后自己想當然的像畫業務流程圖一樣分出好多枝杈,其實每個有必要說明的“枝杈”都應該在有必要的情況下畫一個用例圖),雖然原來知道有用例文本一說(那時統而言之叫做用例說明),但常常以為那只是起補充作用的次要部分。然而看了
Larman
的講解后,才知道那些才是關鍵。正如上面引述的最后一段話所言,那的確是這兩類人最容易犯的錯誤,我就是,過于關注用例圖而非實用的文本信息。(不過這也不能怪我,因為當時學習面向對象時,用例
=
用例圖),還記得那時在一個需求提供者面前用
Visio
畫用例圖記錄她的需求的場面,她顯然是看不懂,而在我看來當時那些不過是糊弄外行的畫兒而已,實際作用甚微。其實書看到這我還是有很多疑問的,比如用例到底怎么寫,包含哪些要素,何時寫和寫到何種詳細程度(因為
UP
中典型的初始、細化、構造、移交階段對于用例的詳細程度是不同的,其實在敏捷
UP
中,只有一個原則——夠用就好
~
)。
下面也是從該書中摘錄出來的一些內容,以備他考。
1.2.1
用例三要素
Larman
在書中并沒有給出這樣的說法,但我覺得它們組成了用例的核心部分,它們分別是參與者、場景和用例。
參與者
就是具有行為的事物,可以是人,計算機系統或組織。
場景
就是參與者和系統之間一系列特定的活動和交互。
用例
就是一組相關的成功(主成功場景和其它擴展(替換場景))和失敗場景的集合。
1.2.2
用例參與者
?????
參與者是任何具有行為的事物,
在所討論系統(
System under Discussion
,
SuD
)調用其它系統服務時,還包括其自身。
?????
參與者三種類型:主要參與者,協助參與者,幕后參與者。
????
?
主要參與者
:具有用戶目標,并通過使用
SuD
的服務完成。例如收銀員。
?????
協助參與者
:為
SuD
提供服務(例如信息服務)。自動付費授權服務即是一類。
?????
幕后參與者
:在用例行為中具有影響或利益,但不是主要或協助參與者。如政府稅收機構。
1.2.3
三種常用形式
????
它們被應用在不同的
UP
階段。
????
在初始階段,
UP
中提出給出大多數用例的簡單描述,指的就是這種形式,叫做摘要。它只記錄主成功場景。而非正式用例也出現在這一階段,區別在于它是不同場景的組合描述。
????
在初始階段提到的對
10%
需求編寫詳細用例就是指的詳述用例,它包含所有必要細節。
1.2.4
[
詳述用例
[
模板
用例的不同部分
|
注釋
|
用例名稱
|
以動詞開始
|
范圍
|
要設計的系統
|
級別
|
“用戶目標”或“子功能”
|
主要參與者
|
調用系統,使之交付服務
|
涉眾及其關注點
|
關注該用例的人,及其需求
|
前置條件
|
值得告知讀者的,開始前必須為真的條件
|
成功保證
|
值得告知讀者的,成功完成必須滿足的條件
|
主成功場景
|
典型的、無條件的、理想方式的主成功場景
|
擴展
|
成功或失敗的替代場景
|
特殊需求
|
相關的非功能性需求
|
技術和數據變元表
|
不同的
I/O
方法和數據格式
|
發生頻率
|
影響對實現的調查、測試和時間安排
|
雜項
|
例如未決問題
|
???
??
這張列表里為我解除對用例最大疑惑的就是主成功場景和擴展(替換場景)的出現。它解決了我過去對于在用例中出現條件分支時手足無措的棘手問題。另外前置條件和成功保證(后置條件)也是相當有用的。我覺得成功保證不是一個好的術語,它的基本意思其實是如果系統成功運轉了,會產生什么樣的結果——如果看到這些結果同時出現,則保證成功了(估計成功保證這一術語就是這么來的)。
?
Larman
這本書傳遞的一個重要思想就是在必要的時候做必要的事,而且有有效果有價值,反映用戶目標和價值。與現在整個軟件業講求實用的主流是一致的,正如敏捷宣言所說的那樣,簡單、有效才是最正確的。這種獲益的感覺在讀
Rod Johnson
的三部連續的巨著時也產生過,那是第一次聽到循證這個詞時,讓我感到了一種特別的歸屬感。我就是一個講究實用的人,而且喜歡速效的人——后來看
Martin Fowler
的書和文章,發現他大抵也是這么一個人。
Larman
的這本書目前剛看到第
12
章:從需求到設計——迭代進化。其中“以迭代方式做正確的事,正確的做事”讓我想起來當初學管理學時所講的經典言論——做正確的事比正確的做事更加重要。這本書一個
40
章,而且有太多東西需要思考和實踐,因此看完此書估計還得有一陣子了。
1.3
類關系
繼承(
Inheritance
):
記得好像是在
Rod Johnson
的書里將繼承分為兩類,一種是接口繼承,一種是實現繼承。我愿意從它們的兩個關鍵詞來理解它們,接口繼承使用
Implement
。實現繼承使用
Extends
,他們正好表現其含義,一個是實現接口,一個是擴展父類。比較提倡使用接口繼承——因為提倡面向接口編程——這個應該是業界的共識。
關聯(
Association
):
指的是類(更精確地說,是這些類的實例)之間的關系,表示有意義和值得關注的連接。在
UML
中,關聯被定義為“兩個或多個類元之間的語義聯系,涉及這些類元實例之間的連接。”關聯有點像關系數據庫中的“聯系”。
1.4
依賴與依賴注入
跑去書店看了看孫衛琴寫的《
Java
面向對象編程》,才終于理解了“依賴”這一術語的含義(可能以前也看過,不過沒有留意)。依賴指的是類(更準確說應該是對象)之間的調用關系,在
A
類中創建了
B
類的實例
b
,然后調用了
b
的方法,就叫
A
依賴
B
。
????
明白了什么是依賴,才知道了什么是依賴注入。所謂注入,指的是使用
XML
將被依賴的類注入到需要依賴的類。比如
Spring
中,在
A
類中聲明一個
B
的實例,產生
setter
,然后在
xml
文件里一配置,就完成注入了。
?
1.5
實例與對象
不記得哪本書上寫的了,最近剛看到的,很明確的給出了實例和對象的關系——對象是類的實例。(在很多書里經常一會對象一會實例的,而且還是在相同語境下,把我徹底搞懵了。)
?
明天接著寫下一部分:重構和設計模式