從 Google 書籤看標籤與資料夾的設計觀 ─ 設計篇

如果我是某大軟體公司的主管,要應徵軟體結構性的設計人員 (偏對技術性,而非需求分析),一般的職稱是稱之為 系統設計師 (SD, System Designer),或者號稱為架構師 (Architect)、資深技術人員等。 若他們在履歷表上寫著擅長或懂 "O-O (Object Oriented)" 或 "UML"、結構設計 等,那麼,我不會考他們什麼 UML 語法還是 設計樣式 (Design Pattern) 等等。 那只是 "背書" 而已,一點意義都沒有。 要背書的話,不如直接給個電腦上網,然後要應徵人員展現如何透過 Google 查詢找到如何實做設計樣式的方法還比較實在。

我會提供的考題,必然是針對應徵人員 "自我思考推理" 的能力驗證,答案的正確性完全不重要,重要的是你為什麼是這樣表達設計的,能否自圓其說。 具有獨立思考能力的設計師,這才是人才!

所以,我會提供一個如這樣的考題:

Google 書籤 (bookmark)是利用 標籤 (Tag)來作分類的。 一個書籤可以被 "標記" 為一到多個標籤,相對來說,一個標籤可以有一到多個書籤。 另外,標籤是不會含有子標籤 (Sub-Tag) 的。

如果我要改良 Google 書籤的設計,希望能再加上 "資料夾 (folder)" 的管理觀念,也就是說書籤必然會 "放" 在某一個資料夾目錄內 (也只能是唯一),而某一個資料夾可以擁有一到多個書籤,同時資料夾也能再包含子資料夾 (Sub-folder)。

同樣類似的應用,可以延伸至部落格 (Blog)的本文 (Content)與標籤、目錄 (category)的結構設計。

請你利用 UML 類別圖,來表達出關於 書籤、標籤與資料夾的結構關係,並簡單說明你的設計想法。

上述的考題是一個 "需求陳述",應該算是蠻普遍的一般應用常識了。 不過若還是不懂上述的敘述,那麼也可以再佐以範例,來解釋什麼是 書籤、標籤與資料夾的概念。

老實說,我是以為,這類的結構設計應該算是很基礎的了,事實上,答案也比想像得意外簡單。 但是,我也問過好幾個號稱對所謂 設計樣式 很熟悉的資深技術人員,最直接給我的答案就是說: 這不就是 "複合結構 (composite structure)" 樣式的應用嗎? 不管你說什麼,反正先把設計圖畫出來再說吧。 結果呢,也真的如我所料,表達不出所以然,真的就只是在背書而已。 最大的盲點,就是把 標籤 (Tag) 與 資料夾 (folder) 給關聯在一起,而其實這兩個是一點關係都沒有的;甚至有些還執著在因為 標籤與書籤 的多對多關係,所以又拉出了一個所謂的 "關聯類別 (Association Class)",卻又說不所以然,越弄越複雜。 因為既然是表達想法,所以類別圖自然是表達 概念 (concept)與概念之間 的關係,而至於那個多對多的關聯類別,是在更細節性的規格設計實做階段再來討論即可,太早論及,反而模糊了要突顯的概念。

表達這類結構性的設計圖,要先找出核心的類別是什麼。 在本例中, "書籤 (bookmark)" 即為本文主體,是最根本的核心類別。 再來當能分別出 標籤 與 資料夾 並沒有關連,而是各自與 書籤 建立關係,那麼,這個設計的表達就可以說對了一大半以上了。 參考的 UML 類別設計如下圖:

圖 . Google 書籤的類別設計圖
(點擊圖片鏈接看原圖)圖 . Google 書籤的類別設計圖

這張設計圖該如何解讀呢?

先觀察紅色區塊,也就是 書籤 與 標籤 的關係。 從 書籤 的角度來看,它可以被多個 標籤 標記,所以在多重性 (multiplicity)的表達,會是 1..* (一到多)。 再來從 標籤 的角度來看,一個標籤可以有一到多個 書籤,所以也是表達成 1..* 的多重性。圖上在 書籤與標籤 兩端是只使用 * 的符號來表達成 多對多 的關係也沒問題,大概知道意思就可以了。

再來就是觀察藍色區塊這邊,這就是典型的 "複合結構 (composite structure)" 樣式了,它可以呈現出 階層性 (hierarchy) 的樹狀結構關係。 把 書籤與資料夾 的共同特性抽象 (abstract)出來,成為 "Bookmark Entry" 這個抽象類別。 至於有哪些共同的特性呢? 諸如 add(), remove(), getName() 等這樣的行為都可定義在這個抽象類別內。 而資料夾 (folder)則是 "聚合 (aggregiate)" 了 書籤與資料夾,在 UML 符號是以 空心菱形 來表示。 從 書籤 的角度來看與 資料夾的關係,它必然被包含 (也就是聚合關係)在某一個 資料夾 內,所以在 資料夾 類別這邊的 多重性 是表達為 1;而一個 資料夾 可以有 一到多 個書籤與子資料夾,所以在 "Bookmark Entry" 類別這邊,多重性是表達為 1..* 。

說實在的,即使不會複合結構的表達也沒關係,若能明確地抓出 書籤與資料夾 的關係 (去掉 Bookmark Entry 這個類別),這就夠了,在這個考題當中,反而要突顯的不會是資料夾的樹狀結構,再次強調,是 書籤、標籤與資料夾 的結構關係。 知道你要表達的焦點何在,這才是關鍵。

再來,又如何知道上述的設計圖是正確的呢? 那當然就需要驗證了。 不一定非得要寫成程式碼後才能知道設計得正不正確,那太耗時費工了;我強烈建議使用 物件圖 (object diagram),利用實際的案例,對應所設計的類別,很快就能對比出結構設計的正確性與否了。 物件圖的表達在此就略過不談了,讀者若有興趣,可以利用 UML 工具(如 EA)來練習看看,然後也可以把 Model 檔寄給我,多少我還能協助 Review 驗證的。

※ 延伸參考:
 o 從 Google 書籤看標籤與資料夾的設計觀 ─ 觀念篇

文章導覽

   

共有 12 則迴響

  1. 克明老師,我是8/16 「UML 團隊開發流程與管理課程」的學員,這篇文章可以讓我轉載到我自己的Blog嗎? 供自己留存的學習筆記使用。

  2. “盡量也不要被特殊性的集合類別綁住”,非常同意此一意見.

    檢視系統的結構設計過程中,若發現在實作環節上會需要經常引用到系統綁定性較高的類別,通常我會在實作設計上,為其類別再包裝一層,隱藏綁定性.

    這麼做,無非是為日後諸多的不可預測性買個保險,另外也是事先做一bound動作,避免PGs實作上各自引用來源不明類別,徒增日後維護困擾.

    • yes. ^^

      這一類的實做設計議題,係為相依性(dependency)的分析範疇,一般 PG Leader (可能為技術長)會建立讓 PG 共同遵循的實做規範。

      另,附帶說明及提醒一下,本文中,複合結構並非是重點,重心是擺在以 “Bookmark” 為核心,再由其去觀察與其它類別的關係;類別萃取的設計階段,要能釐清設計的焦點為何,這才有可能很明確地聚焦的。 🙂

  3. Hello ivan:
    如何實做關聯性,那就跑到了實做面的開發議題了。 是否採用 Array or Hashtable 等,在那個階段則會有其規範共識的。

    另,提供個參考。 利用系統提供的 Collection 機制實現,盡量也不要被特殊性的集合類別綁住,採用如 .NET 的 iDictionary interface 會比較理想。 🙂

  4. 很棒的圖示演示,不過前面的階層性結構需求描述和改進還真是饒舌又不易懂,花了點時間在對映Bookmark是啥?Tag又是指啥?為何又有Folder的需求?還好站在那邊被問的不是我,因為少了一張需求分析的圖對階層性結構
    ,我八成聽不懂題目(謎很大~~~),然後被消費一番.

    個人一點小小感想,既然將Folder管理方式加入需求,那麼標籤功能也許是可以拿掉,很好很強大,但….少了那麼一點使用直覺,使用者可能會很昏吧…..多對多的關係真的是好複雜啊~一不小心可能還會誤刪書籤.

    另外,個人想法,Google 書籤的類別設計圖似乎也允許書籤內可放置Folder,圖面看來是這樣,這….我只是剛好看到..,只是不曉得除了規定PG”U 不准這樣用之外”,是不是有什麼好方法避免PG誤入歧途.

    • 所以,看來還要加上圖解,才能比較瞭解問題的描述了。 ^^ (其實可看觀念篇)

      另,我在「觀念篇」有說明到,TAG 與 Folder 的觀念是互補,一為實,一為虛,是可以達成很好的書籤管理機制。

      最後,結構圖是沒有允許書籤可以包含資料夾的。

      anyway, 結構圖一般經過程式碼驗證,就可以知道 PG 的理解。

      • 底下的想法也許是我誤解或觀念不清楚,說錯請多海涵與指導.

        對於結構圖面上來說,Bookmark與Folder同樣extend自Bookmark entry,且Bookmark entry又aggregiate Folder,因此Bookmark應是也繼承了此一特性,能包含Bookmarks,也能包含Folders,畢竟都是同樣繼承自Bookmark entry.

        若PG在未閱讀需求分析文件情況下,就結構圖面上來看,會否誤解以上的情況?

        • 應該說,Bookmark 是 Bookmark Entry 的 “特殊化”,它只繼承了 Bookmark Entry 的屬性與行為,但可沒有繼承它的關聯性關係的。

          這算是很基本的複合結構圖了,其實在許多 Design Pattern 書籍均有範例可以查知的。 ^^

          對於 PG,老實說,需要中高等以上程度的,才有可能勉強瞭解如何實現。

          另,當重視結構面設計時,此時需求分析的文件反而是被用來驗證結構設計的正確性與可完成性等,算是只作為參考而已的。

          • 感謝你的耐心回覆,這張結構圖的描述的確是沒錯.

            是我搞錯了aggregiate line的方向性問題,這的確是正確的表示法,且Bookmark也不會繼承此一Folder與Bookmark entry關聯性,這個關聯性應只有Folder類別具有.

            原本想打開EA畫出我的想法放上來,不過一拉出aggregiate line就知道我搞錯方向性了.

            這樣一來PG應是不會搞錯其關聯性的,圖正確,實作八九不會跑掉.

            若是我實做此一關聯性,我應會在Folder內宣告一空的Bookmark entry Array(動態空間陣列型別),利用多型特性,讓此一Array可儲放指向Folder或Bookmark物件的參考或指標.

            更進階一點,應是可利用Hash類別,來當做此一Array空間,可提供額外的搜尋能力.

發佈回覆給「ivan」的留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *