快速編程的捷徑——計算機達人成長之路(40)

9PASCAL語言(三)木氏程序分析模型

一個小小的課程設計,其實就是一個驗金石,誰愛好編程、誰擅長編程一目瞭然。動手能力強的同學,課程設計常常做的又快又好,而且能幫助很多其他的同學。而動手能力差一些但是學習慾望仍然很強的同學,雖然在編程過程中會遇到各種困難,但總會想方設法的解決,甚至請出編程達人同學手把手的教。無論過程如何,他們必定親手輸入其課程設計的每一行代碼。但是總還有另外一些同學似乎對動手編程毫無興趣,或者天生懼怕,每每課程設計,總是拷貝抄襲、請人代勞或者在別人上交的軟盤上寫下自己的名字。

木鴻飛曾經認爲,所有的學生都能學好程序設計,懷着這樣的想法,他教授了幾批學生。但在這過程中發現,有人對程序天生友好,稍一點撥就醍醐灌頂,思如泉涌,甚至舉一反三。他們從聽聞項目名稱開始,大腦就高速運轉,如此這般,如此這般,思路清清楚楚,一目瞭然。待到輸入代碼時,更是十指齊飛,工作效率與普通人不可同日而語。

但還有人卻似乎對程序天生遲鈍,無論怎麼教,怎麼學,就是不知道怎麼做。就如同牙膏般,擠一點出一點,更有甚者擠了半天也不出一點。即使這次完成了,下次稍有變化,又茫茫然不知所終,真是急煞人也。對此木鴻飛常常無奈的嘆氣,如果說他們笨吧,但做起其他事情來一個比一個聰明。如果說他們懶吧——是有一點——佈置的程序設計常常不能完成,但問題是這些同學獨立設計程序的能力很差,絞盡腦汁也不知道如何下手,只能空坐在電腦前發呆,即便編碼也會錯誤連連。老師不能總守着,也沒有其他同學可以諮詢,久而久之“遠編程而近遊戲”就成爲了習慣。

究竟是什麼原因造成了這個現象,這在教育界沒有定論,但木鴻飛在不斷的摸索與實踐中,卻略有心得。

成功開發軟件的內在要素,無外乎分析、語法、系統、設計和工具。先說工具,很多課程設計本身很簡單,並不需要複雜的三方控件或特殊專業知識,而集成開發環境的操作方法也並不複雜,新建、編譯、運行等等按鈕簡簡單單明明白白,所以工具不是原因。

再看設計,是否因爲編程技巧不高而導致無從下手。不可否認部分同學由於很少動手,編程技巧急待提高,但技巧不足常常是代碼行冗長和錯誤連連的罪魁禍首,還不足以導致編程時頭腦一片空白、毫無頭緒。

同理,一般課程設計很少使用操作系統的特性,同時大家對語法的掌握程度毋庸置疑。所以種種跡象表明,造成程序生疏的直接原因就是分析,即學習者嚴重缺乏系統分析、數據建模等方面的能力。

本處糾正一個觀點,部分人認爲系統分析是系統分析師的工作,是項目組長的責任,項目組普通成員或者小項目無需系統分析。這是不正確的,在設計任何一個程序之前都需要分析,大系統有大系統的分析,小程序有小程序的分析。即便設計從1連續加到100這樣的簡單程序,也必須先分析後編程,只是過程過於簡單,在頭腦中一閃而過,剎那間完成,感覺不到罷了。

當缺乏分析能力,無法正確進行分析和建模時,不同的人常常有不同的表現。有的人喜歡“知之爲知之,不知爲不知”,每每談論程序,他們都沉默是金,三緘其口,實在躲不過,就會蹦出三個字:“不知道。”

(某計算機課堂上)

木老師:同學們,你們都用過TT打字練習程序嗎?

衆同學(稀稀拉拉):用過。

木老師:想不想自己設計TT程序?

衆同學(異口同聲):想。

木老師:本次課程設計就是設計TT軟件。

衆同學(摩拳擦掌):好!

木老師:那麼現在請大家先思索幾分鐘,TT程序應該如何設計,也就是平時我常教的,應該如何建模?(教室裏平靜了三分鐘),不知名的同學甲,你來回答。

不知名的同學甲:(起來,然後沉默)

木老師:不要緊張,你會如何設計TT程序,想到什麼就說什麼。

不知名的同學甲(仍然沉默,然後很輕聲):不知道。

木老師:設計TT程序,首選什麼數據結構。

不知名的同學甲:不知道。

木老師:TT程序會涉及了那些操作,比如計算時間之類的,想想還有什麼?

不知名的同學甲:不知道。

木老師:假設TT程序已經編好了,用戶會怎麼使用。

不知名的同學甲:不知道。

木老師:你貴姓。

不知名的同學甲:不知道。

木老師:不是吧,貌似你剛剛最興奮,不要緊,勇敢的講出你心中的想法,錯了也沒關係。

不知名的同學甲:我睡着了,被他們吵醒了,不知道是什麼事情,跟着叫喚的。

……

還有另一些人卻正好相反,面對程序設計,無論是否首次接觸,他們貌似總有自己的見解,建模方案和設計手段層出不窮,思如泉涌、口若懸河甚至手舞足蹈,彷彿胸有成竹熟悉無比。但一旦要真正編程時,嘴巴不靈了,手腳不便了,思路枯竭了,就像換了一個人似的。

(大學宿舍中)

帥哥張:今天編譯原理老師佈置了課程設計,做一個詞法編譯器LEX,你們有思路嗎?

教授(面帶愁容):毫無頭緒。

柳輕侯:這個真的很難,我還要考慮一下。

木鴻飛:我也是略懂,正在深入體會中。

于謙(滿不在乎):誰編好後記得給我掛名,我請他吃KFC

牛人生(洋洋得意):詞法編譯器,很容易啊!其實它就是把輸入的一段文字區分爲不同的單詞而已。

木鴻飛:是啊,但是到底如何區分呢?

牛人生:很容易啊,它分爲兩個部分,一個部分記載所有的單詞,當然是以正則表達式的方式記載的。另一個部分則分析文字,以有線自動機的方式將文字分解爲一個個的單詞,……

木鴻飛:嗯,講的不錯,要不我們合作開發吧。

牛人生:嚴重同意!你負責編程序,我負責提供思路和設計方法。

木鴻飛:還是一起編程吧,一個人寫程序速度太慢。

牛人生:思路很重要,想好了思路,事半功倍。如果沒有思路,程序是編不下去的。

木鴻飛:這樣不好吧,要不,你設計第一部分,我設計第二部分。

牛人生:別咯!你編程序,有什麼不懂的地方來問我就行了,我有的是辦法。

……

其實,系統分析人人都會,之所以度不同而已。度太淺就是誇誇其談,無法形成可行的方案。度太深則缺乏全局觀念,容易陷入一個個細節當中無法自拔。那麼如何才能掌握這個度呢?就請欣賞下面的實例,希望大家能有所感悟。

實例:分析TT打字練習程序

分析1:沙發。

分析2:好東西,可以圍觀。

分析3:太好了,我要學習。

分析4:不知道。

評論:此處忽略以上毫無營養的分析。

分析5:在上面顯示一行文字,在下面等待輸入,錯誤的就以紅色標記,最後顯示分數。

評論:這是典型的需求,程序設計前的必修課,外行和誇誇其談者常止步於此。

分析6:用一數組存儲顯示出來的用以提示用戶輸入的文字,稱之爲提示數組。用另一個數組存儲用戶實際輸入的文字,稱之爲打字數組。如果兩數組對應位置的元素相同則說明用戶輸入正確,反之就是輸入錯誤,正確的總數除以數組長度就是正確率。

評論:此乃建模,系統分析關鍵之所在。正所謂外行看熱鬧,內行看門道,對於計算機軟件設計而言,門道就是模型,就是掩藏在繽紛複雜的表象下的數據結構和算法。只有真正提出了數據結構和算法,纔可能實現程序,纔不會坐在電腦前毫無頭緒,否則就是誇誇其談。分析5是必須的,但僅有分析5是不夠的,因爲分析5中沒有可供實施的具體方案,所以分析6實現了由外行到內行的飛躍。

分析7:提示數組中的元素,可以用隨機數的方式生成。具體生成算法容以後詳細考慮。

評論:列舉程序可能需要的算法,並點明實現該算法的關鍵,無需馬上指出具體實現。

程序具備某項功能,則必定會有相應的算法支持,有的算法比較簡單,可以一帶而過,有的算法則比較複雜,需要仔細思考。比如掃雷遊戲必定有埋雷算法,連連看遊戲必須有匹配算法。算法常常不止一個,比如俄羅斯方塊遊戲中,至少有方塊移動算法、方塊旋轉算法和方塊消除算法等多個。

分析7有三個優點:其一、列舉了必要的算法;其二、點明瞭實現該算法的核心,本處爲隨機數;其三、拿得起放得下,抓主線略細節,並不在此深究算法,本處只需記錄下程序所需要的每一個算法並假定已經實現,待所有主線思索清晰後再回過頭來逐個突破。

分析8:生成算法有幾種,比如隨機生成025,寫入數組時爲a+隨機數。也可以爲所有可能出現的字符建立一個索引,隨機生成0~最大字符數-1,寫入數組值爲該索引對應的字符。

評論:算法的具體設計,對分析7中列舉出的所有算法一一設計,當然針對同一個功能也可以提供若干個算法,然後從中選取最適合的一種。

分析9:程序接收鍵盤輸入,存入打字數組對應位置中,並在屏幕上回顯字符。同時判斷是否輸入正確,倘若錯誤則在相應的位置輸出紅色的驚歎號。

評論:以上是對程序中行爲的分析,行爲一般是需求的細化,常常不止一個。比如在俄羅斯方塊中,至少包含定時結束方塊下落,接收並處理鍵盤關於左移、右移、旋轉和加速下移的指令等多個行爲。

行爲在某種意義上是需求內容之一,故外行或者誇誇其談者也會有本分析流出,但他們無法詳盡每一個行爲,並且無法提交針對該行爲的可行性設計方案。

分析10:分析9中多次提及“對應的位置”,具體來講包括當前要輸入的是顯示數組中的第幾個元素,字符存入的打字數組中第幾個元素,輸入字符回顯到屏幕的具體位置,驚歎號顯示的具體位置等四個內容。理論上需要四個數據才能存儲以上四個位置,但實際上這四個位置之間存在特殊的聯繫,它們與起始處的相對位置是相同的,所以可以定義一個整型l爲當前字符的位置,假設顯示數組爲a,打字數組爲b,首字符橫座標爲x,那麼對應的數組元素分別爲a[l]b[l],而在屏幕回顯和驚歎號的橫座標就是x+l

評價:對分析9中的行爲進行再建模,這裏體現了一種迭代的思想,在大範圍建模後(兩個數組)又在小範圍建模(對應位置)。

能不能從複雜的表象中發現程序的本質,是成爲真正的程序員的關鍵。默不作聲者可能爲表象所迷惑,而誇誇其談者則只注重眼前,他們均未能更進一步,或者說他們心有餘而力不足,不知道如何透過現象看本質。以本處爲例,需要對比顯示的字符與輸入的字符是否一致,但顯示的字符到底是何方神聖?誇誇其談者只覺得該字符就在屏幕上,所以不會去思考。而默不作聲者雖然隱約的感覺事情不是想象中的那麼簡單,但由於編程太少,無從下手。他們並不知道本處的核心就是確定這個字符在內存中的存儲位置。倘若能夠思考至此,那麼神馬迷霧都是浮雲。

至此,對TT打字練習程序的系統分析大體完成了,此後就可以條理清晰地進入詳細設計和編碼階段。

分析方法多種多樣,本處借用打字練習程序,介紹獨創的“木氏程序分析模型”,如下圖所示:

木氏程序分析模型

木氏程序分析模型由建模(modeling)、算法(algorithm)和行爲(action)三個對象組成,簡稱MAA模型,此三對象之間相互關聯,每個對象又可細分成分析(analysis)和設計(design)兩種內容。

建模就是確定程序的需求和實現框架。建模分析尋找程序的所有需求,報告針對用戶的外部需求和針對設計者的內部需求。比如上文中對TT程序的描述(分析5

建模設計則分析程序的內部實現,核心是找出適合程序的數據結構和算法,其中尤以數據結構爲最。因爲數據結構是算法的核心與基礎,正如經濟基礎決定上層建築一般,數據結構決定算法,算法根據數據結構的改變而改變。比如上文中使用數組存儲字符(分析6)。建模設計是程序由虛入實的關鍵。

算法分析階段需要列舉程序所涉及的所有算法,當然不能是簡單的羅列,更爲重要的是必須知曉實現該算法的核心思想。比如上文中標明生成字符串的核心思想是隨機(分析7),又比如遊戲中尋路徑算法的核心是深度或廣度優先搜索等等。如若不能標明核心思想,則算法必然是無的放矢、誇誇其談,甚至根本不能實現。

算法設計則將上述的思想落到實處,提出徹底可行的流程。對於簡單的算法可以在列舉後同時設計流程,而對於複雜的算法,只要確定其可行性,爲避免思路受阻、分析中斷,可以暫且略過,待到主線分析完畢後再回頭設計。

行爲分析是更微觀的建模分析,它可以是來自外設的行爲,也可以是來自系統對象的行爲。隨着分析的深入,行爲也會更加細緻。

行爲設計是以可行的方式設計行爲,可以在總體模型的基礎上對行爲進行細節性再建模,以使原有模型更加完善。

當然,實際情況瞬息萬變,複雜萬分,在具體設計時模型內容會有稍許增加。比如設計某項大型項目,前期還會有復更雜的步驟,比如設計拓撲結構,劃分對象模塊等。因此在應用本模型時要注意以下幾點:

第一,分析時必須遵守從主線到細節的原則。只有建立了主體模型,纔可以思索算法,然後再是具體設計。千萬別在神馬都是浮雲的時候就仔細設計具體實現。沒有主線只有支流只會使你的思維更加混亂,到達無從下手的最高境界。

第二,操作時必須牢記當前步驟的工作範圍,設計到大體的模型和算法即可,切不可繼續細化到每一行代碼。需知諸如設定幾個變量,使用什麼循環之類的東東是下一步的工作計劃,若是提前出現除了帶來擾亂思維、增加工作量等惡性後果之外,不會附加任何好處。

第三,整個分析過程不會一蹴而就,也會有一個反覆迭代的過程。比如在分析過程中可以對原有模型進行修改完善。又比如從行爲分析到行爲設計本身就是一個再建模過程,在分析該行爲時很可能形成一個新的模型。有時一個大項目會劃分爲很多小項目,這些小項目又會繼續細化爲更小的項目。在面向對象方法設計時,會將系統劃分爲若干對象。這些小項目或小對象均有可能是一個新的模型。

最後,必須聲明的事,任何事情都有一個熟能生巧的過程,系統分析也不例外。大家是不是看了上面的分析實例忽然覺得熱血沸騰,發覺原來程序分析是如此簡單如此清晰的一件事情,產生一種天下程序盡在我手上的錯覺,以爲自己一下子就轉職爲編程高手。殊不知好事多磨,只有多做系統分析方面的練習,纔可以真正的掌握以上方法的精髓,纔可以笑傲程序。否則,你無法透過現象看到本質嗎,無法快速並且正確的建模。

不經一番寒徹骨,哪得梅花撲鼻香。不經過一番刻苦的練習,即使背熟了模型,也是紙上談兵,仍然無法直擊本質,無法活用數據結構。恐怕一邊搖頭一邊高唱“借我借我一雙慧眼吧,讓我把這程序看得清清楚楚明明白白真真切切”就是真實的寫照。

倘若有心練習,有大量的實例可供選擇。遠的不說,就拿大家喜愛的遊戲程序來說,從俄羅斯方塊、貪吃蛇、掃雷,到連連看、祖瑪,植物大戰殭屍等等都可以成爲練習的素材。甚至可以留意生活中一切可能接觸到的應用程序,反向思索其系統分析,比如與朋友們一道卡拉OK時,就可研究點歌程序;使用了一個背單詞軟件,也可以分析其設計模型。不用擔心練習太多,時間無多,分析畢竟是分析,不涉及編碼,免去了很多煩人的細節,不會佔用太多時間,所以×××。當然很有必要從中選取一二完全設計,如此以來即可驗證系統分析正確性,又可練習編碼等必要能力,還可以得到上臺面的成果,實在是學習編程、樹立名氣、誘惑MM的必備良藥。

上一篇   目錄  下一篇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章