如何設計程序

本文摘譯自HtDP第三章旱函,原有語言DrRacket改寫為Python。本文還混有Composing Programs的內(nèi)容踪古。

設計程序當中很重要的一個環(huán)節(jié)是將問題轉(zhuǎn)化為程序。在這當中需要注意區(qū)分哪些對于描述問題至關重要拘泞,哪些無關緊要枕扫。此外,我們還應當確定目標程序的參數(shù)是什么诗鸭,輸出結(jié)果又是什么参滴,以及參數(shù)與輸出結(jié)果有什么樣的內(nèi)在聯(lián)系。我們還應該注意所選擇的編程語言以及相關庫是否對數(shù)據(jù)處理過程提供了基本的運算支持蝌箍。如果沒有暴心,那我們得自己編寫相關的輔助函數(shù)酷勺。最后,一旦程序完成甚亭,我們得檢驗一下程序是否按照預想的方案執(zhí)行計算過程击胜。

程序?qū)懞煤螅詈糜幸粋€簡短的說明暇唾,講述這個程序的功能辰斋,所需要的參數(shù),以及所產(chǎn)生的結(jié)果够挂。如能夠說明程序的正常運行狀態(tài)就再好不過了藕夫。最好的情況是,程序與求解問題的對應關系非常精確办悟。即如果求解問題狀態(tài)有小幅變動病蛉,程序也同樣能夠?qū)Υ俗鞒鲂》{(diào)整。

我們之所以作出上述要求是因為程序不止是滿足客戶要求能夠運行即可铡恕。我們要考慮到程序后期維護的需要:如果團隊人員發(fā)生變動探熔,新員工必須盡快讀懂程序。此外柬甥,提高程序的可讀性其垄,也會方便客戶隨時改動。

本書針對上述情況提出了一套系統(tǒng)地設計程序的流程臂外。

設計函數(shù)

信息與數(shù)據(jù)

信息是對這個世界的描述漏健。例如橘霎,三張電腦桌,價格分別為599元瓦盛,1299元外潜,2899元。
數(shù)據(jù)是對信息中與問題相關部分的抽象嘱吗。例如碧库,要求出三張桌子的平均價格,那么這三張桌子的品牌弄匕,材質(zhì)就無關緊要沽瞭,從而三張桌子可抽象為一個數(shù)組tables = [599, 1299, 2899]驹溃。

從某種意義上講,程序?qū)嶋H上是對信息處理流程的描述亡哄。程序?qū)⒄鎸嵤澜绲男畔⑥D(zhuǎn)化為數(shù)據(jù)布疙,經(jīng)過計算處理后蚊惯,得出新的數(shù)據(jù),然后將其轉(zhuǎn)化為信息并輸出灵临。其信息的來源范圍實際上是這個真實世界的一部分截型,稱作程序的定義域(Domain)

例如一個智能手機操作系統(tǒng)需要捕捉手指的點擊儒溉,將觸摸屏幕的電學信號轉(zhuǎn)化為屏幕坐標宦焦。正在運行的app接收到坐標后,根據(jù)預先編好的程序顿涣,發(fā)出指令要求屏幕上的圖片翻轉(zhuǎn)一次波闹。操作系統(tǒng)按照指令,控制屏幕的像素點的電學信號园骆,不斷的刷新屏幕,生成圖片翻轉(zhuǎn)動畫锌唾。

軟件工程界使用MVC(Model-View-Controller)模型來組織上述過程的代碼锄码。三個字母分別指代:數(shù)據(jù)處理過程、數(shù)據(jù)->信號過程晌涕、信號->數(shù)據(jù)過程滋捶。

MVC

撰寫函數(shù)說明

當明白了信息與數(shù)據(jù)的相互轉(zhuǎn)化過程后,就可以根據(jù)如下流程設計函數(shù):

  1. 使用注釋語句解釋一下如何使用數(shù)據(jù)描述信息余黎。例如重窟,

    'We use sequence to represent the price of tables'
    
  2. 寫出函數(shù)簽名(Function Signature),目標陳述(Purpose Statement)惧财,函數(shù)存根(Function Header, 也叫stub)

    函數(shù)簽名(Function Signature)描述了函數(shù)所需參數(shù)和產(chǎn)生的結(jié)果巡扇。例如扭仁,一個將整型數(shù)組轉(zhuǎn)化為整型數(shù)字的函數(shù)的簽名為

    'Integer[] -> Integer'
    

    目標陳述(Purpose Statement)描述了函數(shù)的作用:這個函數(shù)計算了什么。例如厅翔,一個計算三張桌子平均值的函數(shù)的目標陳述為

    'Calculate the average price of tables'
    

    函數(shù)存根(Function Header, 也叫stub)將函數(shù)的參數(shù)替換為具體的合法數(shù)據(jù)乖坠,并提供了輸出結(jié)果的具體示例

    '100 = average_price([int, int, int])' # average_price為函數(shù)名
    
  3. 使用樣例來證明以上三項。

    """
    >>> average_price([50, 100, 150])
    100
    >>> average_price([80, 160, 240, 320])
    200
    """
    
  4. 編寫函數(shù)代碼
    也就是完成對信號->數(shù)據(jù)過程刀闷、數(shù)據(jù)處理過程熊泵、數(shù)據(jù)->信號過程的描述。

  5. 測試函數(shù)

    Python中可以使用run_docstring_examples函數(shù)來完成這個過程甸昏。

      def average_price(prices):
        """This function is to calculate the average price of tables.
            
        We use sequence to represent the price of tables.
            
        Integer[] -> Integer
            
        100 = average_price([int, int, int])
            
        >>> average_price([50, 100, 150])
        100
        >>> average_price([80, 160, 240, 320])
        200
        """
        total = 0
        count = len(prices)
        for price in prices:
            total += price  
        average = total / count
        return average


    from doctest import run_docstring_examples
    run_docstring_examples(average_price, globals(), True)

函數(shù)average_price()在聲明時使用三個引號提供了一份簡單的說明顽分。在解釋器中執(zhí)行help()函數(shù)皆可獲得這段說明(按Q退出)。同時施蜜,這份說明也指出了特定值下的輸出值卒蘸。利用run_docstring_examples()函數(shù)可以自動完成檢驗,并輸出檢驗結(jié)果翻默。如下,

    Trying:
        average_price([50, 100, 150])
    Expecting:
        100
    ok
    
    Trying:
        average_price([80, 160, 240, 320])
    Expecting:
        200
    ok

其他須知

計算機程序都是在解決實際問題悬秉,因此編程人員應當對程序所應用的相關學科有一定的了解,例如數(shù)學冰蘑、音樂和泌、生物、土木工程等等祠肥。

此外武氓,還要對所使用的函數(shù)庫的API有所了解。例如仇箱,要用Python處理IP相關問題县恕,應當對ipaddress函數(shù)庫有所了解。

從函數(shù)到程序

復雜的程序不可能只有一個函數(shù)剂桥。大多程序都需要不少輔助函數(shù)忠烛,有些還需要定義很多常量。因此一定要使用好輔助函數(shù)和全局常量权逗,來系統(tǒng)的設計好每一個函數(shù)美尸。記得給函數(shù)和常變量起一個有意義的名字

如果有必要斟薇,應該把預先定義的全局常量在函數(shù)說明里公示出來师坎,以提醒程序維護人員這些常量的存在。

通常堪滨,隨著程序編寫的深入胯陋,你會發(fā)現(xiàn)需要不斷添加新的輔助函數(shù)和常量。我們建議你在編寫程序的過程同時也維護一張“目標清單”,把需要添加的新的輔助函數(shù)和常量列進清單遏乔。一旦完成义矛,把它劃去。只要清單上還有項目盟萨,就繼續(xù)工作症革。如果你發(fā)現(xiàn)清單里的項目全部完成了,那編程的工作也就結(jié)束了鸯旁。

程序測試

Python還可以使用assert聲明執(zhí)行成規(guī)模的自動化的函數(shù)測試。

# define a function to test
def fib(x):
    if x==0:
        return  0
    elif x==1:
        return  1
    else:
        return fib(x-1)+fib(x-2)
    
# define a test function       
def fib_test():
    assert fib(2) == 1, 'The 2nd Fibonacci number should be 1'
    assert fib(3) == 1, 'The 3rd Fibonacci number should be 1'   
    assert fib(50) == 7778742049, 'Error at the 50th Fibonacci number'
  
# execute test      
fib_test(2)
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末量蕊,一起剝皮案震驚了整個濱河市铺罢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌残炮,老刑警劉巖韭赘,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異势就,居然都是意外死亡泉瞻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門苞冯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袖牙,“玉大人,你說我怎么就攤上這事舅锄”薮铮” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵皇忿,是天一觀的道長畴蹭。 經(jīng)常有香客問我,道長鳍烁,這世上最難降的妖魔是什么叨襟? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮幔荒,結(jié)果婚禮上糊闽,老公的妹妹穿的比我還像新娘。我一直安慰自己爹梁,他們只是感情好墓怀,可當我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卫键,像睡著了一般傀履。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天钓账,我揣著相機與錄音碴犬,去河邊找鬼。 笑死梆暮,一個胖子當著我的面吹牛服协,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啦粹,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼偿荷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了唠椭?” 一聲冷哼從身側(cè)響起跳纳,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贪嫂,沒想到半個月后寺庄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡力崇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年斗塘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亮靴。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡馍盟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茧吊,到底是詐尸還是另有隱情朽合,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布饱狂,位于F島的核電站曹步,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏休讳。R本人自食惡果不足惜讲婚,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俊柔。 院中可真熱鬧筹麸,春花似錦、人聲如沸雏婶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽留晚。三九已至酵紫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奖地。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工橄唬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人参歹。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓仰楚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親犬庇。 傳聞我的和親對象是個殘疾皇子僧界,可洞房花燭夜當晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容