1. 程式人生 > >自上而下設計,由下而上實現

自上而下設計,由下而上實現

本文只提供給新手程式設計師閱讀。

多年前的一個 IBM 的老鳥曾經教過我一個 5 分鐘上手的思維習慣,當我聽到以後,醍醐灌頂,驚人天人,一改日常的編碼風格。到現在,它還持續保持在我的日常的編碼習慣當中。

我不知道應該怎麼稱呼這種思維習慣的名字,top-down,自頂而下,或者分治?不管怎麼樣,它的核心是非常清晰的:編碼的時候只思考同一個思維層次的邏輯,在這層完成之後再思考下一層

它基於這麼一個事實:我們每個人智力是有限的,同一個時間只能思考有限內容的東西,我們都不是天才。由於這個事實的存在,所以程式 bug 就會存在(廢話)。因此,思考問題的時候(編碼)不要跨抽象層級思考,在我們有限的智力裡面現保證這個層級的邏輯正確,再思考下一個。什麼叫跨抽象層級思考,什麼叫同一個抽象層級的思考。我們通過一個例子來看看,假設現在我要編寫程式打車去上班。

首先穿衣服,然後洗臉刷牙上廁所,然後下樓打車。

這句話就算是一個三歲的人都能說出來。上面的描述是在同一個思維層次,把“打車上班”這個事情分成了幾個符合順序和操作邏輯的模組和動作,我的大腦能夠承載這些邏輯,這一套邏輯下來就能夠把這件事情完成。於是我把它寫下來:

def goWorkByCar () 
    dressUp() 
    wash() 
    goDownstairs() 
    goByCar() }

這個抽象層次的東西已經完成了,我看這個函式就知道這個操作的順序和邏輯是什麼,甚至還不用註釋。我們有四個函式都是沒有完成的,它們的具體實現就是下一個抽象層次的東西。我們現在下到下一層,看看 dressUp

。現在我的注意力已經不在打車上班這件事情上了,這一層的邏輯已經完成了。我的注意力在怎麼穿衣服這件事情上:

從櫃子裡把衣服拿出來,先穿上半身,再穿下半身。

符合正常的操作,不錯:

def dressUp ()
    clothes = takeClothesFromWardrobe()
    dress(clothes.up)
    dress(clothes.down)

我們看看洗漱怎麼做:

上廁所,刷牙,洗臉

def wash () 
    urine()
    brushTeeth()
    washFace()

下樓呢?

我要先出門,然後鎖門,然後坐電梯。

def goDownstairs () 
    openDoorAndOut()
    lockTheDoor()
    takeTheLift()

打車呢?

用手機打車,然後坐車走人

def goByCar () 
    car = callACarByPhone()
    takeTheCar(car)

...然後再用這種方式實現像 brushTeethwashFace 具體的實現,想想它們需要什麼操作。

你會發現我們不停地在填函式,函式裡面又不停地出現新的函式需要我們去完成。每個函式體裡面的操作都和這個函式所要完成的目的相關,在一個函式裡面,我們只關心這個函式需要完成的目標所需要操作。例如“打車上班”這個任務所依託的 goWorkByCar,我們在這裡並不關心怎麼刷牙,因為它是下一層的東西,我們只關注完成“打車上班”這個目標需要哪幾步。如果我們刷牙、開門這些操作都放在這個函式裡面,那麼一開始就會陷入無限的細節當中而失去了主要目的的關注,而且大腦也無法承載如此複雜多端的細節,處理不好就很容易出現 bug

而這種思維方式可以讓我們不停地把一個大的任務在同一個層級做分解,保證這一層的步驟和邏輯正確以後,然後再下一層分解,最後其實是一個樹狀的結構,樹的葉子結點才是具體的程式碼演算法實現。在編碼的時候,我只用我有限的腦力關注當前層級的任務,不關注上一層也不關注下一層的細節。

這樣的程式碼寫出來不僅 bug 少,邏輯清晰而且還很輕鬆,因為你每一層思考的東西其實都很簡單,不知不覺就把程式碼寫完了。為什麼很多人覺得程式設計很難,因為你接到一個“打車上班”的任務以後就開始腦子裡面就填滿了刷牙打車穿衣服這種不成邏輯和順序的任務,並且都把它寫到一個函式裡面去。

接到任務以後你可以像上面一樣用人類語言描述一下如果你要解決這個任務,你需要什麼步驟。這些步驟才是這一層任務的關注點。例如跟女朋友看電影:你要先看看有什麼好電影,然後再約女朋友,再買票。

(UPDATE:有朋友說這裡第一步應該先找女朋友,同意!!必須同意!全身同意!每個細胞都同意!)

當你寫一行程式碼的時候可以經常看看你的函式名,你這行程式碼和你的函式名所代表任務的是不是同一個邏輯層次的東西,不是的話,把它分出去。

相關推薦

自上而下設計實現

本文只提供給新手程式設計師閱讀。 多年前的一個 IBM 的老鳥曾經教過我一個 5 分鐘上手的思維習慣,當我聽到以後,醍醐灌頂,驚人天人,一改日常的編碼風格。到現在,它還持續保持在我的日常的編碼習慣當中。 我不知道應該怎麼稱呼這種思維習慣的名字,top-down,自頂而下,或者分治?不管怎麼樣,它的核心是非

先外後裏盒子布局

padding 布局 prop 收益率 pos sel 3.2 src bubuko 分兩部分布局,頭部tab、列表內容。 html <!-- 頭部 --> <view class='tab'> <view class

CentOS 安裝openOffice並在Linux實現office轉PDF

安裝openOffice 前提是系統已經安裝好java環境,網上很多需要解除安裝系統自帶java環境的,我覺得沒必要,直接使用也ok。 進入下載的openOffice所在目錄,執行(tar -zxvf Apache_OpenOffice_4.1.5_Linux

接口的多態使用; 接口應用實例:U盤、打印機可以使用共同的USB接口插入到電腦實現各自的功能。

插入 應用 es2017 使用 bsp 功能 jpg 實現 -1 接口的多態使用 接口應用實例:U盤、打印機可以使用共同的USB接口,插入到電腦上實現各自的功能。 接口的多態使用; 接口應用實例:U盤、打印機可以使用共同的USB接口,插入到電腦上實現各自的功能。

判斷滾動事件觸發事件(偽)

window 判斷 var ons log posit ans win style .chan-top{top: 416px;} <div class="ans-box chan-top" style="height: 312px; position: fixed;l

百度面試題之二叉樹層次遍歷(從)

1.二叉樹的層次遍歷 遞迴解法 class Node(object): def __init__(self, v, left=None, right=None): self.value = v self.left = l

【從學習Redis】資料結構篇(一):跳躍表(skiplist)

描述 跳躍表(skiplist)是對有序的連結串列增加上附加的前進連結,在列表中的查詢可以快速的跳過部分列表,因此取名跳躍表。跳躍表大概就長得如下圖所示 再舉個形象點的栗子,就像我們如果要去國外,如果徒步去當然會累死,於是我們先坐飛機,下飛機後乘坐汽車,然後再走一段路最

動畫之從彈出

從上到下 <span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/

vue10行代碼實現拉翻頁加載更多數據純手寫js實現拉刷新拉翻頁不引用任何第三方插件

each ray 如果 部分 list 插件 下拉 ast 頁面數據 vue10行代碼實現上拉翻頁加載更多數據,純手寫js實現下拉刷新上拉翻頁不引用任何第三方插件/庫 一提到移動端的下拉刷新上拉翻頁,你可能就會想到iScroll插件,沒錯iScroll是一個高性能,資源占用

HDFS設計思路HDFS使用查看集群狀態HDFSHDFS傳文件HDFS載文件yarn web管理界面信息查看運行一個mapreduce程序mapreduce的demo

b2c 數據系統 set 打包 value map mode format drive 26 集群使用初步 HDFS的設計思路 l 設計思想 分而治之:將大文件、大批量文件,分布式存放在大量服務器上,以便於采取分而治之的方式對海量數據進行運算分析; l 在大數據系

linux的檔案的拓展lseek實現

程式碼如下:  1 #include<stdio.h>   2 #include<unistd.h>   3 #include<sys/types.h>   4 #include<sys/stat.h>   5 #includ

windows mongodb 連線備份還原遠端伺服器的資料庫(在cmd命令視窗實現

1. Windows下遠端連線伺服器上的MongoDB資料庫 使用的是mongo命令,如果安裝mongodb時配置了環境變數,可以直接快捷鍵windows+R開啟cmd。 管理員身份cmd執行如下語句:      mongo -h ip:埠/資料庫名 -u user

設計模式(01) 單例模式(建立類模式)(兩種推薦的實現方法)

From Now On,Let us begin Design Patterns。 單例模式 定義 確保某一個類只有一個例項,而且自行例項化並向整個系統提供這個例項。 Ensure a classhas only one instance, an

物聯網浪潮之下前端工程師如何迎刃

步驟 angular 訪問 誤區 學習 傳輸 前景 本質 mcu 經歷了過去幾年的發展,Node.js、Angular.js、Vue.js 等前端主流技術框架填補了原有技術的空白與不足,日漸趨於成熟。然而信息時代的來臨,任何的技術不會趨於穩定而止於腳下,現如今物聯網、人工智

linux使用rzsz實現文件的傳和下載

輸入 ssh登錄 usr 終端 啟動 mode 裝包 ftw soft 新搞的雲服務器用SecureCRT不支持上傳和下載,沒有找到rz命令。記錄一下如何安裝rz/sz命令的方法。 一、工具說明 在SecureCRT這樣的ssh登錄軟件裏, 通過在L

iOS UILabel設置居對齊居中對齊對齊

fall pla prop text break case pat png com 在iOS中默認的UILabel中的文字在豎直方向上僅僅能居中對齊,博主參考國外站點。從UILabel繼承了一個新類,實現了居上對齊,居中對齊,居下對齊。詳細例如以下: [c

JQ 移動端返回頂部滑動時顯示返回按鈕滑動時隱藏返回按鈕

hid 獲取 scroll var 返回 向上 區域 手勢 默認 returnTop:function(){ //預定義返回頂部的html代碼,它的css樣式默認為不顯示 var gotoTop_html = ‘<div class

MQTT是IBM開發的一個即時通訊協議構建於TCP/IP協議是物聯網IoT的訂閱協議借助消息推送功能可以更好地實現遠程控制

集合 cap 消息處理 簡易 遠程控制 mes ogr 設計思想 成本 最近一直做物聯網方面的開發,以下內容關於使用MQTT過程中遇到問題的記錄以及需要掌握的機制原理,主要講解理論。 背景 MQTT是IBM開發的一個即時通訊協議。MQTT構建於TCP/IP協議上