設計師學編程?從五個思維訓練開始

設計師學編程?

WHY?

因為,這是連接現在和未來的語言。如果你想創造任何數字化的作品,只有掌握一些編程語言,才能體會到真正的創作自由。

Art & Code - 專欄 將持續更新這方面的教程,幫助設計師們進入新的創作領域。

畢竟,這是一門語言

編程語言雖說跟自然語言類似,但有一些本質的區別,如果不理解這些區別,編程所獨有的一些們檻會始終把你擋在門外。這篇文章嘗試以 Python 為例,用比喻的方法來講解幾個關鍵概念。你並不需要懂得 Python 的語法,只需要用一種開放的心態看待編程,嘗試理解它的獨特之處。

一、變數 vs 替身

變數是學習編程語言時第一道標誌性的認知門檻。因為在日程使用的語言中,所有句子中的詞語都是既定的,你說了 「Great minds think alike」,這個句子不會變成 「Great mouse think alike」。但是在編程語言中,某些詞語會「變化」。這種會變化的詞語,叫做「變數」。

例如

想要寫個程序,顯示一周七天不同的早餐菜單

我們需要有一個東西來代表「今天是周幾」。可能性有 7 種,但是當下只有 1 種,比如今天是周五。那麼需要一個「替身」,來限定它的「變身」範圍是周一至周日,然後讓它根據條件變變變……

這是對編程思維的第一個訓練:

抽象

將某種類型、某個範圍內變化的「實例」,抽象為一個「代號」。

變數的陷阱

  • 變數命名

    這幾乎是一個終極問題…… 因為命名同時承載了佔位符、運算對象、功能解釋、類型暗示、作用域暗示 等等的使命,於是短了燒腦,長了燒眼……

  • 理解成本

    雖然程序是自己寫的,變數是自己命名的,但是每一次回看程序時,都存在「翻譯」變數名的隱性步驟,這個步驟消耗了很多認知資源,相當於腦子裡面得有很多對牽線木偶,運行前是一個,運行後是另一個……相信這是老手感受不到/回憶不起的一種狀態。尤其當程序長了以後,變數越來越多,記憶變數和管理變數都成問題,還容易犯看錯變數名的錯誤。

填坑:

  • 定義函數時,想想它的用途和變化範圍,寫好注釋
  • 避免用三個字母以內的命名,使用那些一個月後再看,仍然能快速理解的命名
  • 如果變數比較多,分一下組,或者動手畫出它們的關係,幫助理清思路

二、數組 vs 分格抽屜

替身雖好,但是有時候還是不好管理,執行命令起來效率有點兒低,因為同質性不夠高(雖然替身都是人,但可能年齡、愛好、性取向、左撇右撇、甜豆花派咸豆花派等等都不盡相同)、以及沒有按順序排列。

於是我們需要一個更「軍事化」的組織——數組。數組就像一個分格抽屜:

從外面看來,一個抽屜就是一個東西(裡面能裝很多東西);打開抽屜,裡面是按照順序放置的同一類東西,每一格都有位置編號(指針)。

這是對編程思維的第二個訓練:

壓縮

對同樣的東西,摺疊再摺疊,收納再收納。

抽屜的陷阱

  • 抽象

    因為抽象,容易見抽屜而不見格子。寫下數組太輕鬆 array[] ,但是一旦加入到運算中(尤其是循環),腦內演化就容易一團漿糊。

  • 抽屜裡面的抽屜

    多維數組又是編程學習中一道難以逾越的門檻。每增加一維,複雜性成本增加。需要先辨別是哪個抽屜,然後再定位到抽屜內的單元。

    小抽屜為大抽屜增加了多樣性,一個抽屜放馬卡龍,一個放銅鑼燒,一個放益力多……

    至於N維數組……

填坑:

  • 克服對數組的心理恐懼,多使用這麼簡潔高效的工具,嗯
  • 數組都是高濃縮佔位符,佔地小,內涵大,如果見到數組,可以自動腦補更大的空間給它
  • 對循環語句中的數組尤其警惕,試著畫一畫邏輯關係

三、判斷+循環 vs 防偽點鈔機

嗯?點鈔機?

我們來看看點鈔機的工作特點:根據設定的條件,重複同一步驟。這正是 「判斷+循環」的精髓。正是它,把我們從機械勞動中解放出來。

下面的代碼雖然只有幾行,但是綜合了變數、運算、循環判斷、數組等等。非常濃縮,非常坑……

for shapes in shape_list:n if shapes[1] == "circle":n canvas.draw_circle(shapes[0],Radius, 1, "Black",shapes[2])n else:n canvas.draw_polygon(shapes[0], 1, "Black",shapes[2])n

這是對編程思維的第三個訓練:

自動化

找出條件,識別共同步驟,循環處理,實現量變到質變。

自動化的陷阱

  • 抽象

    循環裡面如果有個函數調用,再來個二維數組,腦子馬上就漿糊了

填坑:

  • 用 viz mode 這類的可視化工具幫助理解,訓練循環摺疊思維…… 推薦偶像Bret Victor的一篇文章:LEARNABLE PROGRAM — Designing a programming system for understanding programs ,中文版 易學編程:一個幫助理解程序的編程系統的設計

四、函數 vs 百寶袋

每個函數,都是哆啦A夢百寶袋裡面的一件寶物!

寶物的特點是什麼?實現大雄的一個願望。至於怎麼實現的,大雄並不用擔心。當然,想實現多個願望,最好不要指望於一件寶物,那樣往往會出 bug……

說回最開始一周早餐菜單的例子。要 print 不同的菜單,我們需要先判斷今天是周幾,這件事可以寫到一個函數 whatIsTheDay() 中。以後一旦要做這件事,就 call 一下這個函數,外包這項任務給它,自己就翹著二郎腿等著它給出結果。一個程序中有多個函數,也就成了一個百寶袋。

函數的強大之處還在於,可以通過參數實現定製化需求。比如我們在函數 whatIsTheDay(year, month, date) 加入三個參數 year 、month 和 date ,告訴函數:「我想知道 某年、某月、某日 是周幾 」

以上是對編程思維的第四個訓練:

模塊化

分產承包,責任到戶;結果導向,過程自理。**

模塊化的陷阱

  • 貴圈太亂

    函數的調用關係複雜,你調我,它調你,你調你自己……

  • 參數傳遞和返回結果

    參數傳遞引入了新變數(認知內存中又要處理多一套對應關係 >_<),容易跟全局變數、函數內的局部變數混淆。而返回結果又是一個隱式的變數,不可見但影響重大。

  • 交叉並行路徑

    如果只有一個明確起點,調用關係也單純的程序就很好辦。但事實往往是有多個起點入口,調用關係也複雜,偏偏程序是線性寫下來的,不能按照從頭到尾的順序去讀。於是到底程序從哪裡開始,zeng 地躥到了哪裡,很讓人頭疼……

  • 自定義函數和原生函數

    因為原生函數不是自己親生的,所以經常覺得陌生,尤其搞不清楚原生函數之間的關係。

填坑:

  • 明確函數功能,勤加註釋
  • 牢記函數的輸入(函數參數)和輸出(返回值)
  • 多進行局部調試,print 函數返回值
  • 函數之間的調用關係,通過可視化幫助理解

五、類 vs 招聘職位

每一個類都包含屬性(變數和值)和行為(函數)。它跟招聘職位的描述是不是有些類似?

JD(招聘職位描述):

WXG01-微信高級交互設計師(廣州)nn工作職責:nn- 參與微信相關產品從概念到原型的設計過程,輸出相關設計文檔;n- 對產品持續進行設計優化,提升用戶體驗;n- 協調和推動可用性測試及用戶研究,以驗證現有和將來的功能設計;n- 負責設計前瞻性的相關研究。nn工作要求:nn- 工業設計、心理學、計算機、視覺傳達相關背景,本科及以上學歷;n- 3年以上工作經驗,主導過1000萬+用戶的移動互聯網產品的設計,具備多領域設計工作相關經驗,如產品設計、硬體設計、視覺設計等;n- 對互聯網交互設計有深刻理解,具備完整的理論和技術體系;n- 優秀的產品意識,良好的全局觀、前瞻性和判斷力;n- 同理心強烈,擅長換位及獨立思考,卓越的情景還原能力;n- 優秀的溝通、組織和項目管理能力;n- 性格樂觀向上,興趣愛好廣泛。n

類:

class Character:n def __init__(self, name, initial_health): # __int__ 初始化對象n self.name = name # self 是新的對象的引用n self.health = initial_health # name 和 health 是self對象中的域(field)n self.inventory = []nn def __str__(self):n s = "Name: " + self.namen s += " Health: " + str(self.health)n s += " Inventory: " + str(self.inventory)n return snn def grab(self, item): # methond defines the behaviors of objectsn self.inventory.append(item)nn def get_health(self): # method 所有方法的第一個參數都是selfn return self.healthn

  • 工作要求其實就相當於類的「屬性」,作為這類人,本身需要具備什麼樣的條件和素質;
  • 工作職責相當於類的「行為」,這類人要幹什麼事情。

類和函數的區別在於,類只能操作某個類型的對象,而不能通過其他方法直接被調用。面向對象編程的強大之處,對於一個類,理解其介面和已實現的方法,就可以使用了。

這是對編程思維的第五個訓練:

面向對象

打包成型,封裝上架。

面向對象的陷阱

  • 哪些對象、函數需要組織成類,類如何在一開始就做好規劃
  • 類和子類的繼承關係太複雜
  • 類如何管理

關於類、實例、方法等問題,後面再深入討論。

今天先到這~ 可能有很多不恰當的類別,請各位程序猿輕拍~

推薦閱讀:

getter 和 setter 方法有什麼意義?
我們為什麼需要React?
學習編程的好方法——控制台遊戲
git:一個本地分支可以對應多個遠程分支么?
High Flexibility Remote Development

TAG:编程 | 设计师 | 教程 |