2013年8月23日 星期五

The U-D-C-L feedback loop


應用 How To Solve It方法寫程式時,並不期望將四個步驟實施一次即能解決問題;通常這四個步驟需重複實施,構成一個U-D-C-L迴授圈(feedback loop)

U--D--C--LU--D--C--LU ... U--D--C--L
1---------2---------3-... n--------done!               

每一U-D-C-L迴授圈一輪(one iteration)。在每次實施L步驟時,手邊得到程式必須是一個可執行可驗證是否完成的 working software。L步驟執行就是迴授:你想確認問題是否已經解決?如L步驟回顧的程式仍不能滿足做完(done)的條件,則找出待解決的議題,並進入下一輪 -- 仍以U步驟為首,因為前一次L可能讓你對問題有了新的理解。

你可能要問:為什麼不一次做完?原因很多,例如程式具相當規模,你想先完成關鍵架構,再完成其他部份;問題夠複雜,你決定先加以分解成數個子問題,逐步個別解決與整合,直到整個問題被解決為止;程式中使用到一個關鍵的技術,你仍不知道會花多少間才能完成,故你想先以一個簡單的作法實現;等等。

對已熟悉C語言但初學C++者而言,這個作法可讓他先以已知的C language features先將問題大致解決,暫不去理會C++特有的 language features,然後在回顧中,列出必要的C++ language features 學習議題,並在稍後的U-D-C-L迴授圈加以完成。從學習的角度來說,這讓學習者在學習相關C++ language features時有特定的目標。


舉個例子。初學者第一次撰寫C++ class時的建構元(constructor)時,經常會被引導去讀完不同建構元的定義方式與規則,如default constructor、copy constructor、data member 初值化等。這些規則可以輕易的塞滿教科書的一整章!你可以查看常見的C++教科書,輕易的印證這個觀察。


我並不是說C++教科書不應該把建構元相關的規則、例子集中在同一章,因為這樣作有它的好處,例如便於查閱。但身為學習者,你必須瞭解這樣的編排並非要你從 第一頁讀到最後一頁;在適度的引導下,你應該可以選擇性的閱讀必要的內容--以完成當下這一個工作為範圍--漸漸的學完大部分的C++ language features。

How To Solve It的目的之一是提供這樣的一個導引。下一篇文章,我將用一個例子來說明。

© Y C Cheng, 2013. All rights reserved.

Introducing "How to solve it: OOP"

寫軟體應該是一件有趣的活動,因為許多人自願的開發了許多軟體供眾人使用。寫軟體也可賺錢,許多人以此維生。世上有這麼多軟體、有這麼多人寫軟體, 也必然代表寫軟體這件事並不是相當困難。至少,寫軟體應不至於困難到僅僅有只有少數人知道如何做。但對一個初次學習寫軟體的人,不管他是科班的學生(如大 學裡的資訊、電機、電子、數學相關科系的學生)或是一般人仕(不要弄錯,很多傑出的軟體開發者為非本科畢業生),他需要一個簡單而且易學的方法,以支持他 學習寫軟體相關的技能。

個人多年來教授程式設計、軟體開發等相關課程,經常遇到學習者即便在撰寫簡單的程式時,仍遭遇極大的障礙。傳統上的障礙來自於程式語言本身的語法、語意挑戰,我們將這個現象稱為符號障礙(symbolic barrier),如正確的撰寫一個迴圈、主程式與函數、參數的傳遞、區域變數與全域變數的使用等。如同學習一個外國語言,學習者需要為這些基本規則加以掌握,才能寫出使用該外國語言者看得懂得文章[1]。目前市面上已有許多優異的教科書或參考書,足以有效的解決symbolic barrier的問題。

除了符號障礙以外,寫軟體面臨的問題仍有:工作習慣養成、如何從程式到軟體、個人到團隊等問題。在學校養成良好工作習慣,有助於學習者日後發展。唯有解決這些問題,學習者才能在寫軟體的工作上漸漸的步入坦途,而能將其心力專注在解決實際問題上。

寫這個部落格的動機在於提出一個簡單、有效、且學習者可養成工作習慣的方法,以有效克服這些障礙。我將以數學家George Pólya著稱於世的How To Solve It解題方法中所揭櫫的四個步驟為基礎,提出一套簡單、易學、易養成習慣的方法,使學習者在極短的時間內即可開始寫出有意義的程式,不再只為學習克服程式語言的符號障礙而寫一些無用的程式。

How To Solve It的四個步驟為瞭解問題(understanding the problem)、規劃解法(devising a plan)、依規劃解題 (carrying out the plan)與回顧(looking back)。數學問題分成problem to prove 與 problem to solve兩大類;借用How To Solve It於寫軟體,則典型的問題為problem to solve:建造一個程式以解決問題。套用到寫程式,這四個步驟為 :
  1. 瞭解問題(U):程式的需求為何?具體而言,程式的輸入資料為何?程式的輸出為何?限制為何?
  2. 規劃解法(D):列出解決該問題所需做的所有程式待辦工作
  3. 依規劃解題(C):一次挑出一個待辦工作,加以完成並驗證。
  4. 回顧(L):並檢視程式,提出待改善之處,列入待辦工作中。
往後,我將分別以U, D, C, 與 L表示這四個步驟。這四個步驟如何實施將在後續文章中討論。由於這個部落格的目的是提供有程式經驗的學習者進一步學習,我想先指出我用的一個學習策略: 進行C步驟『依規劃解題時,如需使用一個特定的程式construct時,我將不會假定學習者已經學過所有的相關的語言規則並能使用最好得寫法來完成程式。取而代之的,我將使用just-enough與just-in-time的學習策略,專注在解題上,即做出working software

舉例而言,後文中物件導向版的向量(vector)的例子裡,先只定義一個夠用的建構元(constructor),讓學習者能定義向量物件後,即開始 解決向量計算的問題,而避免進入所有形式的建構元的詳細介紹。在另一方面,這個策略下寫出來的程式可能不夠好甚至不正確。此時,How to solve it的L步驟『回顧』中,學習者將有機會檢視現況,並提出下一階段可進行的改善作法。

How to solve it 適用於所有語言的學習。這個部落格的短文中採用的例子裡,我將假設你已經寫過C程式,並準備學習C++語言。

[1] 這裡以『寫』取代一般的『聽、說、讀、寫』,以彰顯『寫』對語法、語意上的要求,高於聽、說、讀的要求。

© Y C Cheng, 2013. All rights reserved.