我曾經聽過一個老師對一個做的不錯的程式員的一句評論:“某某某做程式确實很快,但就是都不能用”。事實上,直到今日,我們中很多人仍然在寫這樣的程式。不能用的程式一般都有幾個特征,比如當程式出現問題時,總是不知道該怎麼處理,甚至是在正常情況下都會出現問題,但歸根結底就是壓根就沒有認真從使用者的角度來考慮使用者到底怎麼來使用。如果使用者輸入了程式接受的輸入,那麼必然該給出正确的結果,可悲劇的是,就是有那麼多的意外,因為客戶行為總是在很多程式員意料之外,是以,當使用者執行了某個程式員認為是非正常的操作的話,運作結果可能是使用者無法得到任何問題的解釋,然後使用者下定一個結論就是:“這是一個什麼破軟體,真沒用!”。
舉個例子,民生網銀就是一個巨大的悲劇,我上網銀想要做一個操作,就是查詢我的信用卡本期該還多少錢,但是我始終找不到那個菜單,原因在于:1 菜單字型太小,找起來真費勁;2 前幾項看起來像是查詢賬戶的,但點選後,悲劇的結果是提示“該卡為非儲蓄卡”,我就納悶那你為什麼不提示我信用卡該做那個操作呢。于是我就找了客服問她如何查詢,并向她抱怨網銀字型太小,無用菜單太多,于是客服MM告訴我可以自己設定菜單的現實。可是,我哪知道該顯示/隐藏那些一級菜單呢?最後我費了很多力氣總算找到菜單,然後點選查詢後,竟然要讓我輸入日期,我就尋思,為什麼不直接顯示最近一期的呢?這麼麻煩我幹麼呢?最後越想越氣,因為:1 這個操作過程非常不爽;2 做網銀軟體的這幫人真是壞了我們程式員的名聲,怎麼搞出這麼難用的軟體呢?要是逼這幫程式員天天用民生網銀軟體,估計也讓他們折壽不少; 3 民生銀行好歹算不錯的公司了,怎麼會上這麼難用的軟體呢?于是,我就很自然的、“邪惡”的聯想到“特色”的社會主義。後來,我覺得我做為一個社會主義合法公民,我該“為中國的軟體事業做點貢獻”,給民生銀行提點建議,于是我就想注冊民生論壇發表一下意見。不幸的是,悲劇又來了,需要填寫的注冊資訊真多啊,但更悲劇的是,在我填寫完所有詳細資訊後,IE 9 下無法注冊,總提示驗證碼不對。還好,我是程式員,我機器上有3個浏覽器,于是,換了Chrome,注冊了,但修改文章不成功;淡定,我還有Firefox,結果出現了亂碼。于是,我再次發揮程式員的職業素質,清理了Cookie,用注冊好的賬戶,換回Chrome來發文章,告訴民生網銀有哪些易用性問題。經過一個小時痛苦折騰,算是OK了。要不是為了出心裡的這口氣,我才不會半夜1點鐘忙到2點鐘給民生銀行反應問題呢(需要說明一下,客戶MM态度很好,另外,半夜還要伺候我這樣的人,還真難為她了。在她給我道歉時,我就回複她,這不是你的問題,然後轉到論壇抱怨來了)。在我印象中,我活到現在半夜發抱怨的文章僅有2次,一次是在電影院看了“要拍給下一代人看的”田壯壯導演親自執導的《狼災記》電影,另一次就是使用了民生網銀。你也可以看到,程式員不替使用者考慮最終會給使用者帶來多大的麻煩,也可想而知,如果這事發生在作為程式員的你身上或者你所在公司身上,會給你帶來多大的信譽損失。
這類的悲劇也曾出現在我們團隊身上,比如,我們的SaaS應用商店開放平台的應用讓使用者試用了應用之後,使用者覺得不錯後要繼續使用,當使用者購買以後卻發現怎麼也無法激活應用了。這對使用者和我們來說,絕對是一個巨大的打擊,先不說使用者有多麼惱火,就問你,你怎麼給使用者解釋出現的問題呢。你總不能告訴使用者,我們的程式員忽略了一個情況,“當應用過期時,應用不能激活了,因為要防止使用者重複使用試用的應用”。這個問題讓我思索了很久,因為我不能單純的去怪罪我的程式員,因為畢竟在設計許可證授權這個子產品時,由于我忙于别的任務,我沒有去努力把好關,沒有讓他嚴格走我們的“概念設計->功能規範->設計規範->實作->QA”标準軟體産品生産路線,但更重要的是,我沒有把他們培養的和我一樣,無論做什麼東西,都必須以“使用者場景驅動”來設計産品。是以,他們很容易忽視軟體在非正常操作下的處理,以及一些很細節的問題。最後這件事情是在我用1個小時的時間給他解決好問題後,客戶才最終釋懷并表示了解和謝意。
我這篇文章想以2個例子來解釋程式需要注意的細節和非正常操作下的軟體處理。關于“使用者場景驅動”設計,我在本文不做詳述,大家可以檢視《Framework Design GuideLine》這本書。
第一個執行個體:我們給一個客戶提供尤埃開放服務平台(UIOSP) OEM版的激活工具。這個工具在正常運作下的界面如下:

(1)運作初始界面。
(2)輸入序列号後,正在激活。
(3)激活成功,顯示一些資訊。
在這個小程式裡面,需要考慮一下的小細節:
(1)界面不能被Resize,因為一旦Resize,将會變得非常醜陋;
(2)背景圖檔不能随着分辨率的變更而出現一些空白或者遮擋,這也非常的醜陋;
(3)可以支援“ESC”或者“Enter”按鈕,進而避免使用者使用滑鼠操作;
(4)支援使用“Alt + <Key>”的組合鍵,這樣友善使用者使用鍵盤操作;
(5)當使用者點選“激活”按鈕時,要将所有的按鈕變成Disabled,避免使用者重複點選;
(6)激活過程要避免界面假死,就是當此時點選界面,界面能及時重新整理;
(7)激活是要顯示激活程序,提示使用者,現在正在操作;
(8)界面的字型,要讓使用者能看清楚;
(9)異常處理:A)如果網絡不暢通,用提示使用者檢查網絡;B)如果許可證輸入為空,提示使用者輸入;C)如果許可證無效,提示使用者輸入正确許可證;D)如果許可證已經超過使用限制,提示使用者購買更多授權;E)如果激活成功,但不是使用管理者使用者,則許可證在Win7下可能無法正确儲存,那麼必須提示使用者設定權限或者使用管理者身份。
(10)如果使用者點選取消或者關閉,要提示使用者是否确定取消。
您或許還需要考慮國際化與本地化支援,此外還需要考慮是否遵循Section 508規範來支援更廣泛的易用性規範,以及其它問題。不過,一個真正合格的軟體需要考慮的細節确實非常的多,我也沒有完全做到正确。下面,我用一個示例來介紹一下關于異常處理的執行個體。
第二個執行個體:許可證輔助工具,這是一個控制台程式,支援對SaaS應用商店開放平台應用許可證的操作。目前它提供了“-help”、“-alterlic”、“-alterconstraint”、“-listconstraint”、“-showmac”、“-listlicattr”和“-showlic”指令,分别用于擷取幫助資訊、變更許可屬性、變更許可限制、列出可用的許可限制、檢視本地Mac、列出許可證屬性和檢視一個許可證的資訊。預設的是,讓你将一個許可證拖拽到這個程式,自動顯示該許可證的資訊。這個程式采用了“管道-過濾器”體系結構來設計,我僅以“-alterlic”指令來展示如何進行異常情況處理。
1 namespace UIShell.OSGi.LicenseUtility
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 CmdLinePipeLine pipeLine = new CmdLinePipeLine();
// Pipeline-Filter Architecture。
8 var showLicense = new ShowLicenseDetailsFilter();
9 pipeLine.RegisterFilter(new AlterLicenseAttributesFilter());
10 pipeLine.RegisterFilter(new AlterConstraintFilter());
11 pipeLine.RegisterFilter(new ListConstraintsFilter());
12 pipeLine.RegisterFilter(new ShowMacFilter());
13 pipeLine.RegisterFilter(new ListLicenseAttributesFilter());
14 pipeLine.RegisterFilter(showLicense);
15 if (args.Length == 1 &&
16 File.Exists(args[0]) /*&&
17 Path.GetExtension(args[0]).ToLower().Equals(".lic")*/)
18 {
19 try
20 {
21 showLicense.ShowLicenseDetails(args[0], string.Empty);
22 }
23 catch (Exception ex) // There is details exception in ex.Message. Thus, just show it directly.
24 {
25 System.Console.WriteLine(ex.Message);
26 }
27 System.Console.WriteLine();
28 System.Console.Write("Press any key to exit.");
29 System.Console.Read();
30 }
31 else
32 {
33 pipeLine.Handle(args);
34 }
35 }
36 }
37 }
該指令的格式為“-alterlic <File or Directory> [-deep true/false] [-lictype fx/bundle] <attribute>=<value>”。
使用者輸入異常可能為:
(1)File or Directory沒有指定;
(2)File or Directory不存在,必須告訴使用者輸入正确的檔案/檔案夾;
(3)File不可讀取,必須告訴使用者更改權限;
(4)File格式不正确,必須告訴使用者程式無法處理;
(5)如果是Directory,則是周遊所有的License File,那麼,如果其中一個LicenseFile處理失敗,則不能影響其它LicenseFile,但必須記錄失敗的License;
(6)如果使用者輸入的屬性設定“<attribute>=<value>”是一個“aaa”格式的字元串,則必須提示使用者,并且忽略掉;
(7)如果使用者輸入的屬性設定“<attribute>=<value>”中attribute不存在,則必須提示使用者,并且抛出異常,終止變更;
(8)如果使用者輸入的屬性設定“<attribute>=<value>”中value與目标類型不比對,則必須提示使用者,并且抛出異常,終止更新;
(9)對許可證變更之前必須備份,以做復原操作。
(10)其它細節或者異常處理。
在這裡面,我們需要考慮的細節問題和異常處理問題比較多,我無法一一細述,僅供參考,希望能給大家一些思考。關于異常,我想強調一下,異常處理就是你需要提前考慮使用者的非正常操作,并對使用者的這類操作給出錯誤提示,并告訴使用者如何去糾正。不過,我想,你也應該發現了,做一個在正常情況下能夠工作的軟體和一個在任何情況下都能工作很好的軟體是有非常大的差別的,後則需要我們付出更多的努力和更專業的技能。
本文轉自道法自然部落格園部落格,原文連結:http://www.cnblogs.com/baihmpgy/archive/2011/09/27/2192437.html,如需轉載請自行聯系原作者