iT邦幫忙

DAY 8
6

網站系統規劃實務系列 第 8

網站系統規劃 - 換個角度想想,談將想法描述成情境的練習

本篇文章作為第二週的第一篇,
這週我們將進入流程與資料關係的分析,並著重在資料分析的部份。

--------系列簡介--------

網站系統可說是現在最多學子與新人想要入門的一個領域,
這個原本屬於新興的領域,這幾年來也累積許多年的知識與 pattern ,
在有限的環境(stateless)與有限的伺服器端、瀏覽器資源下,
成為許多人進入程式的一塊入門鐵板(?)。

這個系列希望能夠就網站系統設計幾個門檻著手,
這是設定給初心者作為學習,給同好們作為回顧,

重新認識有關網站系統的每個環節。
今天我們的主題是談將想法化為情境的練習,作為資料處理的前哨站,
這個主題其實相當單純,簡言之就是化繁為簡。

那什麼是將想法化為情境呢?

我們常常都會想到一些點子,但是實作時卻會卡住,
這理由就在於我們並沒有將想法化為一個個使用情境(use-case)的能力。

這個作法並不限於寫程式,而是廣泛的包含於所有類型的計畫裡面。


讓我們舉個生活化的例子,
「國慶日時要到xxx餐廳去吃一頓大餐。」

這個想法,其中包含許多情境,
像是:

1.因為當天是國定假日,需要事先進行預約這個餐廳的動作
2.決定要邀請哪些人一同參加,確定他們當天是否已經有安排行程
3.瞭解當天該餐廳的交通路線

而這些情境裡面,又有可能因為回應的不同,而產生出更多的情境,
像是預約餐廳時,可能會發現餐廳已經沒有位置,而導致有新的分歧路線。


同樣的,底下讓我們舉個程式化的例子,
已知小明分數為 60分,小華分數為 90分,小乖分數為99分,請問其中誰最高分?

您可能一看就會告訴我 99 分的小乖最高,但您可能會忽略,
您在心理默默的將 60、90、99 進行比較的過程。

因為這些比較已經太自然,自然到我們不會去注意。

就像是人類抬起膝蓋,到底區要牽動多少神經與肌肉,
其實是很複雜的事情,但是因為那是自然的事情,我們並不會去探究。

而且我們一般的情況可以碰到事情再進行反應就好,
但系統您至少需要設計一個意外情況時的機制,才能夠撐到我們發現並妥善處理。


透過寫程式來進行系統的開發,每一個可能情境都需要被定義、被執行,
假設我們用前面比分數的例子,以 JavaScript 來執行的話,

var users = [
	{
		name:"小明",
		score:60
	},
	{
		name:"小華",
		score:90
	},
	{
		name:"小乖",
		score:99
	},
];

如何比較出最高的過程就無法倚賴人腦的直覺反應,
而必須要透過嚴謹到像是笨蛋的定義。

這個比較三者分數在程式裡面的情境可以有很多種作法,這裡提供一個例子:

1.設定第一個人的分數為目前最高值(current_index)
2.跟第二個人的分數比較看看,如果第二個比較高,就設定第二個為最高直。
3.以此類推,直到最後一個人都比完。

之後我再看目前最高值是哪一個,就知道誰是最高分了。

像是底下這樣的程式碼

var users = [
	{
		name:"小明",
		score:60
	},
	{
		name:"小華",
		score:90
	},
	{
		name:"小乖",
		score:99
	},
];

var current_index = 0;
for(var i =1 ; i <users.length;++i){
	if(users[i].score > users[current_index].score){
		current_index = i;
	}
}
alert("最高分為:" + users[current_index].name + ",分數為 "
 + users[current_index].score );

線上範例 http://jsfiddle.net/2Qc72/

筆者要強調的並不是比大小的程式,
而是您如何將腦袋沒有知覺的計算化成流程。

如果單看這隻程式,您可能會覺得這很像數學,
但是其實這不是數學,這是「流程」。

進行一個事情時所需要的一些步驟。


這樣就結束了嗎?

不,除了流程以外,我們還必須加上「前提」,才能夠提出所有情境。

我們剛剛那個問題的題目是
「已知小明分數為 60分,小華分數為 90分,小乖分數為99分,請問其中誰最高分?」

您可以從這中間讀到的前提是:
1.只有三個人
2.三個人的分數沒有重複

假設我今天程式處理的可能會是動態的每天不同的考生的成績,
最高分成績有可能不會重複嗎?

很有可能有一個以上的人考滿分對吧?

所以這時候我們從已知問題中推論時就要仔細審查,
我們的程式是否有假設任何前提,這些前提是否符合我們的需求。

如果我今天設定這隻程式是要接收一個學生班級的考試成績,
我們剛剛寫得程式就不能用了,

因為當最高分同分時,我們只會挑先被比較的那一個;
而這樣其他也是最高分的人就會心生不滿。(跟原本假設衝突)


假設我們今天修改一下題目:
A 考 85 分 , B 考 90 分, C 考 100 滿分,D 也考 100 滿分。

請問您,最高分的是?

您應該會回我 C 與 D ,因為他們兩個都考滿分。

請注意,這時候您除了剛提到的分數判斷以外,
您也分析出最高分有兩人同分的細節,並且決定了最高分要兩人並列的方式。

再次強調,這些我們以為是理所當然的事情,
在系統面上並不理所當然,每個細節都需要在情境面被考慮進去。

於是我們接下來稍微修正剛剛那個應用程式,來看出這中間的差異:
我們將最高分設定成可多個。(以陣列方式存放。)

var users = [{name:"A",score:85},{name:"B",score:90},
             {name:"C",score:100},{name:"D",score:100}];

var current_index = [0]; //設定目前最高分為第一個學生
for(var i = 1 ; i <users.length;++i){
    if(users[i].score > users[current_index[0]].score){
        current_index = [ i ]; // 清空目前最高分並重新設定
    }else if(users[i].score == users[current_index[0]].score){
        current_index.push(i); //分數與目前最高分時暫時並列最高分
    }
}

if(current_index.length == 1){//只有一位最高分的狀況
    alert("最高分為:" + users[current_index].name + ",分數為 "
     + users[current_index].score );
}else{
    
    var result = "最高分有 " ;
    for(var i = 0 ; i < current_index.length; ++i ){
        result += users[current_index[i]].name ;
        if ( i != current_index.length -1 ){
            result += " ,";
        }
    }
    result += " 共計 "+ current_index.length +" 位,分數為 "
        + users[current_index[0]].score;
    alert(result);
}​

線上範例 http://jsfiddle.net/PT9bB/

您可能會發現,不只計算方式變了連呈現結果也變了,因此多一個迴圈來打印資料與呈現,
原本就我們思考中非常單純的一個變兩個,換到程式裡面,可能就不見得這麼單純了。

當然方法有很多種,也有另一種作法是先取得最高分數,
再重新搜尋一次所有學生看誰的分數跟最高分一樣,將其挑出來顯示。

一種需求能夠有非常多種實作是常態,這裡只是作為一例。


就筆者的經驗裡面,分析需求跟辯論是非常像的,

您必須從各種需求中可能的假設,

挑出可能的弱點加以分析,並判斷這些弱點的嚴重性,
如果並不嚴重的問題,則可以暫時掠過不計。

舉個例子,像剛剛的例子,如果我們假設人數無上限,
結果人數太多多到系統無法在系統時間內運行完怎麼辦?

這個問題很顯然的在正常的班級裡面不太可能發生,即使以有數十萬張考卷的考試而言,
分析最高分這件事情這對系統而言是非常輕鬆的,所以這種問題就不是需要考慮的問題。

另外要盡量考慮到不同情境裡面的可能性,
很多入門初學者看到這樣循序的分析方式就會急著說我不懂數學,

但這其實不是數學,這是流程。

我們其實就像是工廠生產線的設計者,我們排定一個又一個的劇本,讓程式去運作,
所以具有將思緒化為生產線程序的練習,就是非常重要的,

所以我們今天將會一直頻繁作這個練習。


筆者就讀大學時,常常在與同儕討論程式習題時,
發現有人會無法讀懂題目,也是因為缺乏將文字情境化的能力。

就以筆者大學時的練習題目作為例子:

停車場一個小時收費五十塊,未滿一個小時以一小時計,
超過三小時的話,超過的時間部份以五折計價,
假設為停車 n 分鐘,請問您如何透過程式計算此停車費?

這裡我們先作個實驗:假設我告訴您有人停車 80 分鐘的話,
您可以多快告訴我他該收多少費用?

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

我相信您應該可以馬上告訴我,該收的費用是 100 塊,
因為我們常常在停車場,這樣的算術應該不陌生。

接下來我們要來拆解需求囉以利撰寫程式,

停車場一個小時收費五十塊,未滿一個小時以一小時計,
超過三小時的話,超過的時間部份以五折計價,
假設為停車 n 分鐘,請問您如何透過程式計算此停車費?

首先我們先釐清已知:
* n 的單位是分鐘
* 一小時有六十分鐘

再來我們要解決一些問題點,這些問題可能我們人腦可以馬上反應,
但是我們可能只會算結果,不見得寫得出算式喔,馬上練習看看?

1.如何由分鐘判斷是幾小時?
2.如何判斷未滿一小時?
3.如何算出超過三小時的部份
4.如何計價(前三小時以 $50 計,超過得部份以 $50 打五折計算)

筆者相信大家都很聰明,所以直接寫答案

1.如何由分鐘判斷是幾小時?

將 n 除以 60 分鐘,得到去小數的商數就是確實經過的小時

如 140 / 60 = 2.333333 ,2 就是確實經過的小時數。

2.如何判斷未滿一小時?

不是直接看就知道嗎?(XD,如果您真的這麼想的話,無法分析好程式邏輯的喔。)


將 n 除以 60 分鐘取餘數,若餘數不是 0 就表示有未滿一小時的部份。

如 140 % 60 = 20 (% 是 mod ,取餘數的運算子) ,我們就知道 20 未滿一小時。

如 120 % 60 = 0 , 120 是剛好兩小時,沒有未滿一小實的部份。

  1. 判斷 n 是不是超過 180 就知道了 XD

  2. 先計算總共有多少小時(含未滿一小時計價的部份),
    如果超過 3 ,就以 50*3 + (時數-3) * 50 * 0.5 ,反之 50 * 時數 。

所以這個題目,其實可以簡單換算為以下的 JavaScript 算式:

var n = 190 ;

var hours = 0; 
if( n % 60 == 0 ){ 
	hours = n / 60;
}else{
	hours = parseInt(n / 60,10) +1; 
}

var price = 0;
if ( hours > 3 ){
	price = 50 *3 + (hours-3) * 50  * 0.5; //(0.5 = 五折)
}else{
	price = 50 * hours;
}

alert("時間為 " + n + " ,價格為 " + price);

線上範例: http://jsfiddle.net/xYtBA/


@ 我怎麼有一種在讀國小數學的感覺?您真的確定我們需要重新學習這麼基本的東西嗎?

這些是寫程式的實作者需要重新鍛鍊的細節,
筆者在求學過程中,也是轉過好幾個彎才弄懂這些邏輯該怎麼寫,

即使只是很簡單的未滿一個小時該怎麼判斷這件事情。

筆者總認為用人腦想是一回事,但是人腦會騙人,
我們常常會忽略掉那些大腦幫我們處理掉的許多細節運算。

筆者並不是說這樣的練習多作幾次,能夠幫助於您理解系統。

這只是個例子讓您意識到我們平常在大腦裡面有意識進行的運算方式,
跟純粹邏輯性的流程還是有一段距離的。


@ 不相信嗎? XD 那我們接下來舉更多例子。

現在很多人對於一個 blog 系統的想法,很有可能是:
註冊、登入、發文、登出,這些基本的操作與功能。

如果您沒有去細想的話,這裡面跟現實的差別在於:

1.所謂的註冊,您需要考慮到使用者不斷註冊帳號或是無法取回帳號的問題,
所以需要作 email 認證。

2.登入的時候如果登入失敗,要有錯誤畫面,
如果短時間內重複登入失敗,要考慮是否要暫時不允許該 ip 進行登入。

3.發文能允許哪些文章格式,使用者希望有漂亮、豐富格式的內文,
所以我們可能需要有圖文編輯器幫助他們使用,

但是圖文編輯器如果能置入 JavaScript 的話,又有安全性風險,需要為此做處理。
如果採用 markdown / wiki 等格式的話,又會需要教育使用者使用方式。

4.發文可能會需要有圖片,所以我們可能需要作相簿系統,或者整合現有相簿系統,
並且將其整合到發文系統裡。

5.文章需要有清單頁才能瀏覽,但是您一開始,
可能會以為只需要有個畫面把文章顯示出來就好。

6.當文章量多到一個程度以後,可能會需要 tag 或 category 來協助您分類。

以上六點,再深入進去還可以再舉出超過一百個以上的情境分歧與細節,
請絕對不要小看每個問題背後的問題。

對人腦而言,因為一方面大腦自己運轉過程產生的錯覺,
另一方面是思緒的不周全,容易導致您無法在一開始考慮到所有的細節。

而將腦袋裡面概念轉化為情境的同時,
也就是在將開發的細節給拓樸成系統規劃的過程。


@ 等等,我是個初學者,我怎麼可能一開始就明白這些細節?

所以我們必須將我們所知的部份化為情境,
一旦當我們開始將情境著墨到紙上或是系統圖形時,

我們就可以針對每一個情境去發展子情境。

如果時間有限,先針對核心情境進行設計,
之後再請人以假想的使用者測試的方式來測試這個系統,也可以找到很多細節。

另外絕對切忌使用「參考 xxx 網站」的方式作為情境,如果要參考別人的網站,
應該是一樣一樣將每個從該網站觀察到的情境寫下,這樣才叫參考,
而不是碰到什麼問題才去該網站看人家怎麼解決。

理由是因為很有可能有情境上的衝突,另一方面是可能根本舉不出合理的情境。

@ 最後再來一個很小很小的情境的練習吧 :)

假設我們今天要來作一個留言板,那這個情境,我們可以怎麼分析?

# 留言板的情境 v 1.0

* 要可以瀏覽
* 可以留言

# 留言板的情境 v 1.1?

* 要可以瀏覽
** 是單則瀏覽呢,還是多則瀏覽?

* 可以留言
** 留言要含有哪些項目呢? (可能會有標題、內容、作者、email、website)這些資料將需要被儲存

* 是否允許回應呢?

您會發現這裡都是問號,這些問號就代表前提(需求)。

在這裡需要決定一些前提,因為不決定這些前提就無法前進。
(很多專案是失敗於錯誤、發過程不斷變更的前提)

@ 以下是我們決定好的 留言板情境 v1.1

* 要可以瀏覽
** 多則同時呈現在同一個畫面上
** 每則需要呈現標題、作者、內容

* 可以留言
** 需要填寫 標題、內容、作者並儲存。

* 為求簡單與開發順利,不允許回應。

# 留言板的情境 v 1.2?

* 要可以瀏覽
** 多則同時呈現在同一個畫面上
** 每則需要呈現標題、作者、內容
** 有多則以上的時候,呈現的順序應該依照什麼順序?
(目前的資料只能依照 標題、內容、作者排序)

* 可以留言
** 需要填寫 標題、內容、作者並儲存。

* 為求簡單與開發順利,不允許回應。

@ 這是決定後的留言板情境 v1.2

# 留言板的情境 v 1.2

* 要可以瀏覽
** 多則同時呈現在同一個畫面上
** 每則需要呈現標題、作者、內容
** 有多則以上的時候,依照發表時間排序,後發表的先顯示(desc)

* 可以留言
** 需要填寫 標題、內容、作者,並紀錄以上資料及發表時間

* 為求簡單與開發順利,不允許回應。

# 留言板的情境 v 1.3?

* 要可以瀏覽
** 多則同時呈現在同一個畫面上
** 每則需要呈現標題、作者、內容
** 有多則以上的時候,依照發表時間排序,後發表的先顯示(desc)

* 可以留言
** 需要填寫 標題、內容、作者,並紀錄以上資料及發表時間
** 如果不小心打錯字怎麼辦?
** 如果使用者沒有輸入內容,還是要送出嗎?

* 為求簡單與開發順利,不允許回應。


接下來的分析就不繼續寫下去了,
如果為了撰寫技術文章,可能為了專案簡單,
我們很有可能會選擇打錯字就打錯字,不讓使用者修改。

但現實是往往我們不會選擇專案簡單的作法,而是選擇繼續發展下去,
做出簡易的會員系統,好讓使用者可以自行編輯修改文章等,
所以根據不同的選擇就會有不同的結果,系統複雜度也會有很大不同。

一個系統開始起來時,會有許多「必須」的假設,
像是多則資料時的排序依據、希望填寫、呈現的資料,這些是設計者需要事先想好的。

後來則多少會隨著需求本身以及我們對這些需求的選擇,而產生不同的發展。


今天其實這樣討論是為了對比明顯,
所以我們將許多不同層次的情境分析混為一談。

事實上如何將想法列舉為情境,有分成許多層次,

像是從最原本提出的點子、需求或者是臨摹別人網站到情境,
這是屬於最 end_user 端的 use case 撰寫,也就是需求訪談。

將 use case 寫成系統架構與系統流程,就是系統分析。

另外負責去將系統分析中各個子系統實作出來,這就是系統開發。

需求訪談 > 系統分析 > 系統開發,
這三個環節在進行不同層次的情境分析,越底層的要考慮的就越細。


這也是許多專案中常常產生爭議的地方。

筆者在第二週進行資料面的第一天先將這個議題提出,

是因為後續的資料設計、系統功能分析,都將基於這些情境進行設計,
如果開發者無法瞭解開發時需要的情境,則任何系統都將脆弱不堪。

筆者自己因為有過三年多的專案外包經驗,曾經體驗過這其中許多不同角色的矛盾與細節,
在這裡面的不同環節都需要彼此合作與協助;

專案進行到中期時,適當地取捨需求就開始是必須的,
所有可能需求都想要在一開始就一次滿足的專案往往面臨失敗。

在撰寫之後的技術文章時,因為我們也不可能考慮到所有情境,
筆者也會在過程中將許多筆者開發時假設的情境反覆強調並撰寫出來,與本篇作為呼應。

最簡單的地方,往往就是最容易造成問題的地方。

明天開始,我們就要開始談論網站需求,
如何透過關聯式資料庫來達到協作目的。

那就明天見囉。;)


上一篇
網站系統規劃 - 網站狀態介紹
下一篇
網站系統規劃 - 資料管理初探(以 Excel 為例)
系列文
網站系統規劃實務27
0
timloo
iT邦研究生 2 級 ‧ 2012-10-02 00:31:50

所有的字是發多少時間打上的?

不知作者一分鐘打多少字?太驚人的字數了。

一篇抵10篇的量。

年輕人的思考速度真驚人。

和作者比起來,在需求分析上簡直太粗糙了,多大的熱情才能容忍USER的善變。??!!

tony1223 iT邦新手 2 級 ‧ 2012-10-02 00:56:22 檢舉

這篇差不多七點半或八點開始寫得吧,三個半小時左右。

0
ted99tw
iT邦高手 1 級 ‧ 2012-10-02 06:44:26

不推會遭天打雷霹呀......
讚讚讚

0
withsr
iT邦研究生 4 級 ‧ 2012-10-02 14:51:54

這個概念跟我當初寫講義訓練一樣
口語化與生活化來達到教學的目標
強推

0
Kathy Lai
iT邦新手 5 級 ‧ 2016-12-08 14:36:43

這篇真的很棒,很仔細,說的精要。

我要留言

立即登入留言