3.2 讓程式設計平穩起步——思維、設計、表達——《逆襲大學》連載
返回到【全文目錄】
目錄
3.2 讓程式設計平穩起步——思維、設計、表達
踩離合、掛檔、踩油門、擡離合,拿捏得當,汽車這臺鐵傢伙才能緩緩起步。老司機只要坐上駕駛位,想都不想,就順順當當起步了。而對新手而言,常被這幾個步驟搞得焦頭爛額,熄火、倒溜、猛衝出去,所有的不當操作組合起來,老手看到的是相當熱鬧的場面。
這和程式設計新手遇到的場面有些類似。這也告訴我們,一些基本的環節熟悉以後,不論要解決什麼問題,按那些套路走下來,也便有了眉目。汽車起步的幾個要領,需要在一次次的練習中實踐,久而會養成習慣;而程式設計起步時需要的基本動作也不是有誰天生就會,只要在程式設計初期有意品味,日久也會內化於心。初學開車的會手忙腳亂,我十幾年前學車用的是輛破吉普車,一起學習的幾個女孩沒少掉眼淚;初學程式設計的,一時找不到要點,氣惱、著急的也有不少,甚至有人急忙給自己貼個“學不了程式設計”的標籤。這個標籤貼上了,是安心一陣子了,但也可能路就被堵死了,麻煩在後面。
汽車起步其實真不難,踩離合、掛檔、踩油門、擡離合。在程式設計新手的各種慌亂中,也有幾個基本動作,做到了,起步不需要忙亂。
機械化的思維
還記得那年春晚“張惠妹”大媽問,將大象放到冰箱需要幾個步驟?需要三步:開啟冰箱門,把大象放進去,把冰箱門帶上。能給出這種回答的人,都能編得了程式。這個回答中體現的就是一種機械化,就是要將解決問題的步驟詳細地一一列出來,可以自己去實施,也可以指導別人去實施。給計算機程式設計序,就是通過指令列出解決問題的步驟,讓計算機實施這些步驟就行了。能機械化的,就能自動化,只要分清楚一步一步做什麼,寫成程式由計算機自動執行就行了。
燒水泡茶需要做四項工作,即洗好水壺,洗好茶杯,準備茶葉,燒開水泡茶。列出這四項來,是讓燒水泡茶工作能夠機械化的前提。在此基礎上,可能的做法可以是:(1)洗好水壺,灌上涼水,放在火上,等待水開;水開後,再洗茶杯,準備茶葉,沖水泡茶;(2)先洗好水壺,洗好茶杯,放好茶葉,一切就緒,再放水燒水,水開後再衝水飲茶;(3)洗淨開水壺,灌水燒水;燒水過程中,洗茶杯,放茶葉,水開後泡茶喝。這就是三種燒水泡茶的程式。
現實生活中的程式,就是事情進行的先後次序的安排。可以看出,在不同的程式的指導下,做事還是有些區別的。在為計算機程式設計序時,也需要分離出計算機要完成的操作,然後將這些操作的順序安排妥當。
初學程式設計的大學生,不適應這樣的思維。我們總是習慣於自己親自做一些事情,作為一個有高度智慧的人,做完一步順理成章地接著做下一步,而各步之間的銜接卻常常意識不到。在我們日常的行事中,已經逐漸地適應了在整體上看一件事情的方式,而不是將一件完整的事情分解開來去描述。比如,當你要離家上大學獨立生活時,媽媽可能也只一句“要注意勤洗衣服”,而不再嘮叨:“放好水,加入洗衣粉,泡上半小時,……”
然而,對於想學程式設計的人來說,現在能做且有必要做的事情,可以將想要完成的任何事情都分解成一些更具體的細節,並樂於這樣描述,從而將機械化思維養成習慣。這樣的事情很多:一次班級活動、國慶長假的旅行、高等數學要複習了,等等,都可以試著列一列步驟。我們面對的,是運算能力強大,但就是不會自己做出安排的計算機,我們要學習的,就是學會為它安排第一步開啟冰箱,第二步……
這樣的一種思維習慣目標在於讓計算機能明白“求解問題”。這樣的思維習慣,將使你習慣站在一個更巨集觀的角度看問題,學會將整個的問題分解開來,具體到一個個可行的步驟。這種思維將是我們在清清楚楚地做任何事情的時候都需要的,是從事計算機行業工作的需要,也是一種普適的思維。清晰的程式設計思路可以得來,有序的人生其實也是一樣。
有層次地設計
看別人的程式相對容易,一到自己寫程式,直接卡殼,程式設計不順的同學說:“沒思路。”
沒思路就是列不出前面的機械化思維的步驟,這是需要在程式設計的實踐中逐步提高的能力。對於一個新手而言,看問題就是一個整體,天狗吃天,找不到下口的地方,怎麼都看不出這一步、下一步。其實,面對複雜的問題,我們需要有一種方法,幫助找出這些步驟。
我們要做的是有層次地思考。從問題的總體,細分一些,再具體一些,最後得到的是讓計算機可以直接執行的步驟。這種有層次地思考,叫做“自頂向下,逐步求精”。
案例3–1 舉一個例子。學校舉辦校園歌手大獎賽,敲計算器算分太慢了,把加號按成減號之類自擺烏龍的情況屢有發生。(其實,這樣的做法也算是一個程式,只不過計算的工作由計算器完成,而計算的過程是由人控制著的。)現在就有人要請你設計一個程式,計算歌手成績。打分規則是:七位評委各給出一個分數,去掉一個最高分,去掉一個最低分,餘下五個分數的平均值作為選手的最後得分。
這個事情讓人做,看見七個數字,戳計算器算就得了。而要交給計算機做,就得列步驟。我們的注意力放到了七個數字上來,而沒有管評委是男是女,是俊是醜,高矮胖瘦,運用的是抽象的方法,在此我們只關心分數這樣一個最核心的要素,而將其他與問題實質無關的因素剔除掉了。現在要求解的問題就是,利用七個輸入資料,最後得到一個輸出資料。用七個輸入資料計算得到這一個輸出資料,這就是解決這個問題所涉及的資訊的因果關係。這樣,為一個歌手打分的過程中要做的事情,包括了以下的工作:(1)輸入七個數;(2)求出除了最大值和最小值以外的其他五個數的平均值;(3)輸出平均值。這個平均值就是歌手的得分。這樣的分解結果可以表示如下,作為初學者程式設計沒有思路時就需要這樣列出:
(1)輸入七個數:a1,a2,a3,a4,a5,a6,a7
(2)求出除了最大值和最小值以外的其他五個數的平均值:V
(3)輸出平均值:V
這是在“自頂向下”分析中最“頂”層的一個分解,是對問題“總體”的解決方法。下面我們逐步深入到細節中考慮。其中“(2)求出除了最大值和最小值以外的其他五個數的平均值”是最核心的工作,還沒有具體到可以直接解決的程度,需要繼續分解下去。其中的一種思路是,先求出最大值和最小值,將七個數累加起來之後,再將最大和最小值減去,也便得到了所需要的平均值。也就是說,將(2)分解為下面的4個步驟:
(2.1)求出最大值amax
(2.2)求出最小值amin
(2.3)求出七個數的和:S=a1+a2+a3+a4+a5+a6+a7
(2.4)V=(S–amax–amin)/5
體會一下,這樣的“機械化”的節奏是否更鮮明一些了?一個“整體”的問題,被我們清楚地分成了幾個步驟。這樣的過程可以繼續下去。例如,對於(2.1),我們可以繼續得到第三級的分解:
(2.1.1)設amax=a1,即暫時認為第一個數就是最大的
(2.1.2)對於a2到a7中的每一個數ai//在程式設計時,這裡需要一個迴圈解決
(2.1.3)如果amax<ai,amax=ai//如果amax比ai小,ai應該就是當前最大的
對一個已經有一些程式設計體驗的人,求最大值、最小值及求和的問題,可能是能夠直接去實現了,將不需要做第三級的分解,這也體現了在學習程式設計過程中循序漸進的必要性。而如果對求最大值等功能還不能直接解決的同學,不妨多寫一級,將分解繼續進行下去。
逐步求精的方法,是人類解決複雜問題時採用的基本方法,是為了集中精力解決重要問題而儘量推遲對問題的細節的考慮。在人類的認知規律中,注意力只能集中7±2個知識塊。逐步求精方法要遵循的法則,就要求當一個巨集觀的描述進一步求精時,如果涉及的細節太多,最好將其限制在7個以內,更多的細節可以在下一級再進行處理。
自頂向下的策略,先巨集觀再微觀,把一個時期內必須解決的問題排出一個先後順序來,用逐步求精的方法,確保每個問題都能被解決,而且安排在合適的時候解決。用這樣一種有層次的設計,層層遞進,最終得到能夠直接用程式設計語言編寫的程式。
想一想,我們做任何工作,例如對大學生活做一個巨集觀的規劃、制定一天的學習計劃、組織一次班級活動、完成一個工程專案開發、策劃一項商業活動,無論複雜還是簡單,有意或無意地,都可以踐行“自頂向下,逐步求精”的偉大思想。用心體會,這將成為無論學習程式設計還是處理其他事務中的有效的思維習慣。
學會利用工具表述問題
程式設計序的最終目標是寫出能夠正確完成任務的程式來。其實,比寫出語句更關鍵的能力,是會用程式設計的思維思考。由問題到程式碼,中間的跨度比較大,企圖在大腦中完成所有的過渡,至少對於初學者而言顯得不切實際。機械化的思維,分層次的設計,都是為此做的過渡。事實上,在軟體工程發展歷程的實踐中,產生了很多實用的表達工具,能夠幫助人們完成這個過渡。
圖3–1是案例3–1中在進行求解歌手大獎賽成績的問題分析時,畫出的程式流程圖。流程圖是表示演算法的一種圖形工具。隨著箭頭的方向,是否能發現這樣的表達更形象,更自然?有了這樣的流程圖,可以很容易地寫出對應的程式來。一張圖頂一千字,在軟體工程中,有很多圖形工具可供使用。這些工具可以幫助我們整理思維,也成了在產業中分工合作、相互交流的介質。
在傳統的工程學科,如機械工程、土木工程等領域,設計和施工中都需要用到圖紙。軟體工程中的很多環節也需要有圖形工具表現設計結果,並形成了諸多標準。由於軟體和程式的不可見的性質,這些圖形工具更加必要。系統需求分析中要用到的系統流程圖;在軟體結構設計中,有軟體結構圖;做資料需求分析時,有資料流圖(DF圖);設計資料庫的邏輯結構時,要用到實體—聯絡圖(E-R圖)。在採用面向物件的程式設計方法時,常用到圖形化的統一建模語言UML,在其中共涉及到了五類共十種圖,包括用例圖、類圖、物件圖、狀態圖、活動圖等。
這些設計工具的使用,體現的是重要的設計方法,也將是大學學習中逐步要接觸到的內容。對於程式設計的初學者而言,直接能夠使用到的是描述演算法的程式流程圖,而盒圖(N-S圖)中不涉及線條的轉移而更具有結構化的特點,也經常應用。應用中學會使用各種各樣的設計工具,是對程式設計初學者的基本要求。
流程圖這樣的工具,老師會在課堂中講,大多數的程式設計的教材、參考書中也會涉及,本書中不再深入。但在我的教學實踐中發現,即使知道了這些工具,同學們卻很少在實踐中主動應用,僅限於佈置作業後畫一畫。他們太在意最終的成果——程式了,以至於一旦拿到任務,滿腦子也就是程式。在這樣一種狀況下,不重視畫流程圖之類的基本功的訓練,就一直學不會有效利用工具。等到遇到複雜問題需要解決,只靠大腦不能夠完成構思時,也才想起流程圖的好處,卻用不得法,於是轉而繼續擱置。如此迴圈,越學越糊塗,乃至信心也在喪失。設計工具在實踐中被大量地用於支援設計流程,幫助開發人員整理和表達思路,描述演算法,指導實現,起著非凡的作用。業內有不少的高階技術人員在設計的層面上工作,他們也在大量用此類的工具進行表達,而不是直接在程式碼層面上工作。作為程式設計的初學者,更是需要在在實踐中主動使用這些工具,學會用設計工具思考和表達的方法,體會到這樣做的好處。
返回到【全文目錄】