最近和大家一起討論了一些內容管理方面的功能和設計,有些思考,和大家分享一下。
在討論內容管理的功能需求時,我們常常會考慮某個功能各種各樣的情況,功能性、易用性、複雜的處理情境、異常的處理情境,這些無疑都是非常非常有價值的,一個系統做到最好的境界,從客戶角度來看,也就是這些功能了。
同時,我們也討論了很多軟體設計方面的一些內容,考慮了很多靈活性、擴充性方面的內容,同時設計和功能也是緊密相連的,設計常常對功能的具體展現會有一定的影響。
那我們實際中遇到的困難是什麼呢?針對上面我們討論的兩個方面,主要是兩個問題:
1)功能太多了,有時候是越想越多,如何選取合適的功能集合成為討論的焦點;
2)還有就是設計的靈活性和擴充性的把握,感覺好的設計,往往需要更多實現的時間,然後項目時間似乎又不允許。
在說明這兩個問題之前,我想有必要稍微說明一下軟體品質的一些分類。
最近看一本書(Scrum and XP from the Trenches),對軟體的品質,劃分為內部品質(internal quality)和外部品質(external quality),外部品質指的是從客戶角度可以看到的品質,比如軟體的功能,易用性、效能等等;內部品質則是是從程式員角度來看的品質,比如代碼的健壯性、可擴充性、可維護性等等。外部品質好的軟體,內部品質不一定好;但是內部品質不好的軟體,外部品質一般很難好。很難想像,一個設計很糟糕,代碼品質很糟糕的系統,功能、效能和易用性可以很好。內部品質就好比是外部品質的基石,代碼的可維護性和擴充性,直接影響了系統的功能的改進和提升。
外部品質和內部品質比較容易對於到功能和設計兩個問題上。
那麼回過頭來看我們遇到的兩個問題,首先是功能的取捨問題。
我們Agile的團隊討論,大家對於某個User Story,討論起來越談就越起勁,想出了好多好多的功能點,隨之也帶來了很多麻煩,比如說要實現的範圍好像太大了,似乎一下子工作量變得很大,隨著而來也有很多壓力,然後接著我們有時候也會不由自主的按照項目時間點,尋找一些“捷徑”,然後可能就逐步丟掉了或者少做了一些好的功能點,甚至會轉向實現一些大家雖然覺得不怎麼好但是滿足項目時間點的功能,這時大家都不免感到有些失落。
那我們可以怎麼處理呢,可以稍微分析一下我們整理出來的功能點,我們會發現,情況也許不是我們想像的那麼糟糕。我自己覺得有四個原則可以協助我們去抉擇:
1)功能優先順序
2)80/20法則
3)完整性
4)可持久性
1)優先順序
首先是我們可以按照優先順序來選擇功能點,這個是顯而易見的。重要的功能先做,次要的功能可以先放一放。特別是最基本的功能,比如客戶一定要的功能,沒有這個功能客戶就玩不轉了;比如內容管理,如果內容建立、修改和刪除,這些功能如果都沒有,那麼系統都無法正常運轉了,肯定是不行的了。
2)80/20法則
80/20法則,就是先選擇哪些客戶日常使用最需要用到的功能,比如說內容處理的基本流程,有一些內容同步的異常情況,實現起來是很複雜的,但是實際中遇到的可能性相對較少。又比如內容建立流程的易用性,這個使用者使用頻率是非常高的,那麼怎麼最佳化內容建立的使用者體驗,這個功能點優先順序也就是很高的,然而它的代價可能不會特別高。
3)完整性
要特別注意是功能點的完整性,比如說內容異常流程的處理,假設因為項目時間,先不實現了,那麼也不是說完全不處理異常了,還是要做到有一定完整性,即使是簡單的實現也是需要的(比如說記錄日誌以供人工查詢),但是這個簡單實現是代價最小的,而且是以後可以很快去替代的。
4)可持久性
功能點的實現選擇,要考慮的還有可持久性的問題,就是功能點是可以不斷去疊加來完善的,而不是說不斷的推翻後重新實現一把,這個是差別很大的。比如說內容建立功能,現在對於異常的處理我們暫時不實現,這個是沒有問題的;但是如果下次要實現異常處理的時候,就要把現在內容建立的流程的功能描述推翻重來,這個可持久性就有問題了,因為這個意味著以前的功能全部都會被推翻,很可能是以前的實現都白費了,這就是功能點設計的的不可持久性了。功能點設計一定要有持久性,如果是這樣子,系統的功能就能夠越做越強。
所以我們可以把每一個的User Story的各個功能點想的更加完善,這個是很好的,剩下的只是如何取捨的了,所謂取捨,只是階段性的捨棄和選擇罷了。所以在討論過程中,不要因為功能的增強,範圍的擴大而讓我們感到害怕和困惑,把他們記錄下來,就是很好的逐步改進系統的武器,我們只要運用上面的一些原則,就能夠讓我們做的更好。
下來再談談設計的問題。
在Head First Object-Oriented Design的書中,定義Good Design就是Flexible Design。而The Art of Agile Software Development一書中,定義Good Design為“A good software design minimizes the time required to create, modify and maintain the software while achieving acceptable runtime performance.”就是軟體的可維護性。所以Agile Design強調的功能,基本上都是從如何不斷改進軟體的可維護性和可擴充性而努力的,只有軟體具備了良好的可維護性和可擴充性,那麼軟體能夠很好的不斷疊加功能,軟體才具有旺盛的生命力。
我們實際中面向的問題呢?其實還是很簡單,就是好的設計和項目時間的衝突,好的設計是需要時間考慮的,也是需要時間來實現的(雖然不是絕對,有時候好的設計會節省更多的工作量)。
對於第一個問題,於項目時間的衝突,這個可以回到前面開始談的內部品質和外部品質的問題,前面對於功能(外部品質)的問題,我們已經談了取捨的方法,那麼,內部品質(設計),是不是也可以取捨呢?在“Scrum and XP from the Trenches”書裡面,作者自己是這麼認為的:
Internal quality, however, is not up for discussion. It is the team’s responsibility to maintain the system’s quality under all circumstances and this is simply not negotiable. Ever.
在這上面我是持一樣的觀點的。
然而我們的問題依然存在。和項目時間的衝突如何平衡呢?我想可以考慮兩個原則:
1) 足夠好(First Right)
2) 分階段實現/可持久性
1)足夠好(First Right & Good Enough)
所謂First Right & Good Enough是讓我們看看我們所作的設計是不是足夠清晰的架構我們的系統,而不是太過的複雜導致項目時間不足,往往好的設計並不是要花更多的時間實現的,通常只有Over Design才讓我們感到力不從心。所以我們發現設計導致實現的時間過長的時候,我們需要看看,是不是我們想的太複雜了?
另外一方面,我們不提倡Over Design,避免Needless Complexity,但是還是要Good Enough & First Right,就是在看的到的需求範圍內,我們的設計要好,好的設計和不好的設計,差別往往是在維護代碼和增加功能的時候才能夠看到,稍微花一些時間完成一些精妙的設計,不僅是技術,更是藝術美感的體現,這個只有在未來才能夠體會到。
要注意的是Refactoring和First Right並沒有衝突,只有每次都是Right的比Wrong的更多,逐步的將Wrong的地方進行Refactor,系統才能夠越做越好。否則系統的品質就始終處於初級階段了。
2)分階段實現/可持久性
好的設計往往是Flexible的,是可以分階段實現的,很多設計的基本原則,比如面向介面編程,就是支撐“分階段實現”的一個很好的原則。當我們定義的介面層次很清晰的時候,介面的具體實現,是可以根據項目的時間點,進行控制的。項目時間比較緊的時候,可以做一些快速的實現,然後在下一階段再Refactoring,如果對象之間是介面依賴而不是類依賴的話,下一階段的Refactoring也對系統已有功能影響也就非常的小,這個也是IOC核心價值所在了。
舉個例子,比如說話單檔案格式的靈活設計,假設話單有好幾種格式,那麼它的設計可以有幾個階段:
第一個階段是能夠在類這個層級易於維護,先通過Template的設計模式定義一個話單父類後,不同的話單格式的子類實現父類的模板方法,如formatCDR(格式話話單記錄)即可,這種情況下,外部函數寫話單的時候,只需要執行個體化相應對象後,調用父類的介面就可以寫出相應的話單。而有新話單格式的時候,只要產生一個新的子類並實現相應方法就可以了,可以看到這種設計是一個Good Enough的設計。
第二個階段是把類的可維護性提升到配置的可維護性,比如說通過一種XML的方式來配置話單格式,使得系統的可維護性達到運行時而不是編譯時間。這個時候,還是在原來的基礎上,產生一個新的子類,這個子類在formatCDR的時候是從XML設定檔裡面讀取配置後產生格式化資料的罷了,系統還是支援很多種預設的CDR格式並且對於一些無法通過配置的CDR格式,還是可以通過子類繼承的方式來實現。
第三個階段是做一個很好的GUI來配置和管理話單XML設定檔了。
所以往往好的設計是可以逐步疊加並且完善的,象Spring的核心IOC就是為了設計模式而生的,很好的運用這些技術和理念,是可以讓我們的設計具有更好的生命力和持久性,同時也平衡項目中的一些時間點。
結語:無論如何,軟體的需求分析和設計,都是一種藝術,是要在我們不斷的開發過程中去積累和提高的,要做到最好,所有的付出,都是值得的。