iT邦幫忙

8

掌握學習程式的本質與方法(二):整理思考脈絡

  • 分享至 

  • xImage
  •  

內容大綱

一、這篇想傳達的
二、開場問題
三、軟體開發的學習難題
四、該怎麼解決?理解並梳理思考脈絡
五、理解思考脈絡的本質,注意學習的陷阱
六、結論

HackMD 好讀連結
HackMD 系列目錄

一、這篇想傳達的

第一篇針對了「被動學習」和「主動學習」,傳達了看不到終點的學習焦慮和煩惱,主要來自於自己的學習認知和狀態。

接下來希望透過這篇,傳達學習程式技術的方向問題,為何主要源自於思考脈絡的雜亂,導致學了東,忘了西,學了一堆,等到需要拼在一起綜合運用的時候,腦袋一片空白。

除此之外,第二篇內容會延伸第一篇提到的內容:如何混用專案式學習和實驗式學習。

二、開場問題

以下幾位正面臨學習煩惱的人,描述了他們的學習方式和煩惱,先將他們的描述放進腦海當中,看完本文之後,思考看看,除了建議對方直接躺平,你會怎麼點出對方的問題?

A君:工作需要接觸 Angular 框架
我是某公司的 Junior 前端工程師,接下來需要接手幾個 Angular 的專案,在前兩個月,我很努力的把官方文件的內容都一個一個看完並且跟著做,第三個月開始,我準備接手一個 Angular 專案,裡面的程式碼都看過,但是每次需要調整某個頁面的功能、新增某個頁面的時候,卻不知道從何下手,我是不是要回去複習 Angular 的官方文件?

B君:從 .NET 6 框架轉換到 Spring Boot 2.7 框架
我是公司的後端工程師,在公司已經待了一年,由於公司的專案,主要使用的後端框架除了 C#.NET 6,還有 Java Spring Boot 2.7,因此主管希望我去接觸和學習,但我沒有 Java 的基礎,而且 Spring 又有 Spring Boot、Spring WebFlux、Spring Data、Spring Security 這麼多要學,我到底該從何學習?

C君:準備踏入前端工程師
我每天花了很多時間觀看網路上的 HTML & CSS 教學,把所有的 HTML 標籤和 CSS 語法記下來,但我總是容易搞混不同的標籤和語法,<head> 跟 <body> 差在哪、<link> 跟 <script> 差別在哪?CSS 的 vertical-align 和 justify-content 差別在哪?

D君:工作需要接觸 Linux
我是某個初階後端工程師,因為許多的專案都是架設在 Linux 環境,因為聽大家說鳥哥的書超級讚,結果買來之後看了一個月,發現要記的指令和常用資料夾路徑超多,越是學到後面,前面學過的指令和觀念越是沒有印象,我需要從頭回去複習前面的內容嗎?

三、軟體開發的學習難題

從上述四位的描述當中,你能否想像他們所學的東西,在腦中是什麼樣子?思考路徑不僅混亂,而且觀念抽象沒有連結

為什麼?多數有方向和混亂的問題,因為在學習時,聚焦在學習的內容忽略或甚至輕忽學習的思考脈絡

假設一個學了變數、條件判斷、輸入和輸出語法,但沒有方向完成 Console 版猜數字遊戲(1~100 猜一個整數)的人做類比,他們腦中的思考脈絡大概長這個樣子:

image

這樣的思考脈絡究竟有哪些問題?

(一) 每個脈絡之間的路徑沒有主次和順序之分 (迷路)

大腦的思考路徑,不知道主要先想哪些,其次想哪些
最直接的結果:不知道從何下手,腦袋一片空白。

對應到第一張思考脈絡圖:
每條思考路徑的粗細、顏色、深淺都一樣,隨著學的東西越來越多,思考路徑也容易越來越跳躍。

(二) 每個脈絡之間的路徑是分散且無法連結的 (混亂易忘)

程式開發這個領域,許多的觀念、語法,對大腦來說都是相當的「抽象」而且「沒感覺」。如果反覆死記硬背,記到後來不只難以回想,又容易遺忘。

對應到第一張思考脈絡圖:
每條思考路徑之間分散且沒有連貫,隨著學的東西越來越多,思考路徑也容易變得越來越難發現。

四、該怎麼解決?理解並梳理思考脈絡

(一) 以剛才的猜數字遊戲為例,學習時該怎麼整理思考脈絡?

如果要使用 C# 完成一個 Console 的猜數字遊戲,第一層要想的事情有哪些?

- **首先,怎麼從 1~ 100 的整數,產生並記錄正確答案**
- **接著,玩家怎麼輸入答案,並記錄在程式**
- **再來,如何比對玩家的答案與正確答案一樣**
- **最後,怎麼輸出比對的結果,告知玩家答對還是答錯**

當我把第一層的思考脈絡整理之後,最後會是下圖的樣子。第一層思考路徑,就像這顆樹一樣,一開始從中間的樹幹,從下到上,依序往兩側的樹枝思考

一旦主次和順序整理出來之後,每次回想猜數字遊戲的時候,都能很快的從這四個問題切入。

image

回到剛剛猜數字遊戲的例子,第一層脈絡整理出了,猜數字遊戲要依序解決的問題情境。接著依序思考,每個問題情境需要用到哪些程式觀念和語法?

- **首先,怎麼從 1~ 100 產生並記錄正確答案**
    - 亂數:使用 Random 產生亂數
    - int 型態:產生完的整數亂數,使用整數(int)型態的變數存放
- **接著,玩家怎麼輸入答案,並記錄在程式**
    - 輸入的函數 Console.ReadLine()
    - 輸入的資料使用字串型態的變數存放 (string)
- **再來,如何比對玩家的答案與正確答案一樣**
    - 條件判斷: if {} else {}、三元運算子
    - 比較運算: if (userAnswer == inputAnswer)
    - 型態轉換:字串跟整數比較前需要將字串轉成整數型態 int.Parse() 或 Convert.ToInt32()
- **最後,怎麼輸出比對的結果,告知玩家答對還是答錯**
    - 輸出函數:使用 Console.WriteLine()

當我把第二層的思考脈絡整理之後,最後會是下圖的樣子。
image

學完整理出完整的脈絡後,原本抽象而且沒感覺的語法,和第一層的問題情境有了連結,有助於語法觀念的記憶和聯想。

接著就可以依照自己的需要,深入學習和實驗每個語法觀念。例如:我想要瞭解更多亂樹的用法,可以新增一隻實驗用的程式專案,去瞭解和實驗每個亂數的函數。因為有了脈絡之後再看語法觀念,跟你一開始直接看語法觀念的感覺會完全不一樣。

備註:因為這篇要把思考脈絡的「路徑」強調出來,所以使用樹來做比喻,你也可以使用心智圖來整理。
image

image

(二) 從 C# 轉換為 JavaScript

繼續延伸猜數字遊戲的例子:

如果今天改從 C# 換到在瀏覽器的 Console,使用弱型別的 JavaScript 實現,你會發現哪些差別?第二層的程式語法和觀念細節。
1. **亂數產生的函數**:Math.random()。 【語法差異】
2. **int 型態**:使用 let 宣告,而且不需要型態。 【語法差異+語言特性】
3. **輸入函數**:如果是瀏覽器的 prompt() 當作輸入函數。 【語法差異】
4. **型態轉換**:parseInt()。 【語法差異】
5. **比較運算**:除了嚴格相等 (===),即使型態不同,弱型別的語言也會自動轉換。 【語言特性】 
6. **輸出函數**:console.log()

(三) 從 Console 轉換為網頁

在轉換相似的思考脈絡當中,你也整理了當中的語法差異和語言特性差異。同樣的還可以練習看看:

如果要從 Console 改成網頁表單的形式,原本的脈絡會怎麼變化?這邊以**第一層脈絡**的「輸入答案」和「比對答案」,使用原生 JavaScript 為例:

- ~~輸入函數~~ **表單**:欄位的說明 (label) 、輸入的欄位 (input)送出按鈕(Button))
- **事件(event)**:表單送出事件(submit) 或按鈕事件 (click)
- **取得 input 的內容**:submit 事件的 event.target\['xxx'].value 或使用 document.querySelector('yyy').value 從 DOM 下手

當你學習時,從整理的脈絡發現,對於表單、DOM、事件的觀念不太熟悉時,你就可以抽一些時間,深入學習這幾個部分的整體觀念。

(四) 從 Console 版猜數字遊戲加入功能變化

除了用來轉換到不同的語言或工具,還可以加入變化,如果覺得抽象,可以自己嘗試照著上面的原則,「主要先想那些,哪些是次要接著想的,觀念和問題該怎麼連結。」將思考脈絡條列並畫出來:

在 Console 的猜數字遊戲,加上「可以重複猜測直到答對」、「最多猜測十次」、「最大最小的範圍提示」、「再玩一輪」等功能。

- **可以重複猜測直到答對**:
在第一層脈絡上,多了一條分支「可以重複猜測直到答對」,往下延伸一條第二層分支: while 迴圈,重複的條件為「使用者答案 不等於 正確答案」 (userAnswer != correctAnswer)。
- **最多猜測十次**:
    - 第一層「計算並判斷作答次數」,底下延伸一條「算術運算」。
    - 接著回到第一層,想到剛才的「可以重複猜測直到答對」,重複的條件改為「『使用者答案 不等於 正確答案』,而且『猜測的次數 小於等於 5 (初始值從1開始)』」(userAnswer != correctAnswer && guessTime <= 5)。
- **最大最小的範圍提示**:
第一層先想到「比對答案」,接著想到「條件判斷」,原本的程式邏輯只有「答對(\==)」、「答錯(!=)」,加上提示範圍的程式邏輯變成「答對(\==)」、「比答案小(<=)」、「比答案大(>=)」。
- **再玩一輪**:
第一層脈絡,多了一條分支「再玩一輪」,底下延伸兩條第二層分支,包含 「do...while 迴圈」和「輸入函數」。

image
猜數字遊戲2

(五) 總結整理脈絡的重點

對應第一篇提到的專案式學習和實驗式學習,在專案式練習,關注三個部分:

  1. 釐清與拆解涵蓋的問題情境:思考路徑的切入點
  2. 整理問題情境的主次層級:思考的層級順序
  3. 將相對具體的問題情境,連結到陌生且抽象的觀念:思考的連貫性。

當你透過實驗式學習,深入瞭解某一個路徑的觀念時,用相同的原則,將某個路徑從原先的脈絡拉出來思考,整理成另一個抽象語法或觀念的思考脈絡

(六) 總結思考脈絡的好處

往後在回想的時候,不管你從問題情境的角度切入往下延伸,或者從抽象語法觀念的角度切入往前回想,思考脈絡對你來說整體又容易掌握

  1. 容易找到思考的切入點
    描述問題的時候,其他人比較容易理解並找到問題的癥結點。
  2. 有助於記憶和回想抽象的語法觀念
    快速的從第一層問題脈絡的連結當中,找到和理解每個抽象的觀念和細節。
  3. 轉換學習時,幫助掌握共通點與差異點
    換到不同的語言、工具或技術時,可以當作轉換的方向,專注在脈絡當中的差異點、較弱的觀念。

(七) 整理思考脈絡的盲點

  1. 語法或觀念細節要怎麼辦?
    整理思考脈絡的重點在,整理思考的路徑,所以流程或語法觀念的細節,比較建議整理成文章、程式檔的形式。不在第二篇的討論範圍。

  2. 最多延伸到幾層?每一個層級要固定放什麼?
    沒有標準答案,只要思考時,路徑能自然的連貫起來。

(八) 沒經驗或缺乏基礎的人,整理思考脈絡會遇到的狀況

  1. 想不到一開始的切入點
    問題情境實現的功能切入並拆解。
    如果認為發現實在有難度,我會直接建議找專案導向的書或課程 + Google 學習。

  2. 鑽牛角尖,或者過於發散。
    通常是想的「太細」,或者「不夠具體直接」,可以試著拉高層級,整理歸納較為細節的脈絡。

  3. 某個思考路徑,超出自身的認知,卡住無法往下延伸。
    思考跟目前的學習重點有關,如果連結性較小,選擇性的暫時擱置

以上三點拿開場問題的B君學習 Spring Boot 為例,沒整理過的思考脈絡可能長這個樣子:
1. Java 的 JDK 與 JRE
2. IDE 或編輯器
3. Maven 或 Gradle 的使用
4. 怎麼啟動 Spring Boot 的 API 測試
5. 怎麼定義 GET, POST, PUT, PATCH, DELETE 的 API
6. API 的請求參數和回應參數怎麼定義和存取。
7. 連線資料庫的設定。
8. 資料表與欄位的 Class 定義。
9. SQL 操作在 Hibernate 的架構下該怎麼實作。
10. 實作基本的會員相關功能
...

經過整理後的思考脈絡:
1. 開發前的準備:開發環境、開發工具
    - Java 的 JDK 與 JRE
    - 開發用的 IDE 或編輯器
2. 怎麼建立和啟動一個專案
    - 怎麼使用 Maven 或 Gradle 安裝套件
    - 使用什麼指令啟動 API 測試。
3. 以前寫過的會員系統,在 Spring Boot 是怎麼實作的
    - 如何定義 WebAPI
        - 怎麼定義 GET, POST, PUT, PATCH, DELETE 的 API
        - API 的請求參數和回應參數怎麼定義和存取。
    - 相依服務的設定和使用
        - 定義為可被注入的相依服務類別 (建立 Bean)
        - 注入其他的相依服務類別 (注入 Bean)
    -  搭配關連式資料庫
        - 連線資料庫的前置設定。
        - 資料表與欄位的 Class 定義。 (Model)
        - SQL 基本 CRUD 操作在 Hibernate 的架構下該怎麼實作。 (Repository)
        - 怎麼實作關聯查詢 (Join)
        - 怎麼使用資料庫的交易 (Transaction)
    - 註冊的商業邏輯
        - 判斷帳號是否重複註冊
        - 判斷密碼的強度
        - 判斷密碼與確認密碼是否一樣
        - 密碼的加鹽
    - 登入的商業邏輯
    ...
    - 登出的商業邏輯
    ...
    - 忘記密碼的商業邏輯
    ...

如果你不像 B 君有足夠的經驗,延伸幾點學習上的建議:

  • 記錄下來當前常常卡住的部分,抽時間一起學習
    如果在學習 Spring Boot 的時候,發現 SQL、@Autowird 和 @Component 等等觀念和用法,常常讓你覺得卡東卡西,我會記錄下來,花點時間把卡住的觀念和語法整個學過一遍,另外開個實驗專案嘗試並觀察。

  • 準備一至兩個自己能從頭到尾完成,而且相對完整的作品,找個練功的第一份工作
    練習的過程中,或許你的作法並不是 Best Practice,Code 寫的不是很好,或者有些脈絡是自學不容易接觸到的,但至少你有了屬於自己的學習脈絡和紀錄。

    先挑一個要求沒這麼高的低階工作練功,進入職場之後,跟隨較資深的前輩做中學,將有毒的作法、設計調整過來,並且補足自學不容易掌握的思考脈絡。很多對程式碼好壞很敏銳的人,也是接手過別人的爛 Code,或者自己的爛 Code。如果是一位天份不錯的人,自認作品的 Level 比其他人高,那第一份工作就可以挑比較好的去挑戰,因人而異。

五、理解思考脈絡的本質,注意學習的陷阱

(一) 思考脈絡是給「自己」的大腦用的

看完了思考脈絡的說明和舉例,我需要特別強調,思考脈絡是給自己用的。換句話說:

  1. 主要必須靠自己思考和整理,別人的不一定適用自己。
  2. 可隨時不斷的調整。
  3. 每個人不會完全相同。

只有靠自己思考和整理的思考脈絡,印象才會最深刻,思考起來才會靈活

(二) 「速成筆記」或「技巧」的使用時機避免過早

因此我會建議在剛開始學習程式的時候,最好避免:

  1. 密技思維:剛開始學習,就直接使用網路或別人整理好的心智圖、學習路徑 (Road Map)、Cheat Sheet、XXX 個技巧學習。
  2. 思考重心流於整理筆記,偏離思考事情本身。

抄捷徑的密技和方法,適合在有一定思考脈絡的時候,補足不足的部分,但如果當作一開始主要學習的內容,反而是大腦整理思考脈絡的殺手。為什麼?

工作面臨的開發與除錯問題,很多都是綜合性的問題,沒有脈絡的密技和技巧,很容易會以東拼西湊的角度切入,遇到問題越補越大洞、方向越來越偏。

(三) 當作一種習慣養成,而非唯一的萬用工具

  1. 要練習多久?有什麼方法技巧快速練成?有哪些練習的題材?
    當作一種習慣養成,用在整理平常學習的專業、工作的每一件事情,之間的主次與關聯,時間因人而異。
  2. 是不是只要會整理思考脈絡,就能快速具備工程師的能力?
    當然不是,整理完思考脈絡,只是幫你整理掌握整體的結構和方向,你還是要下功夫去理解、練習學習的內容。

六、結論

專案式學習面對的問題情境、完成的功能,在學習的時候幫助蒐集、釐清、整理思考脈絡,混用實驗式學習,可以在有整體脈絡的支撐下,專心強化所學的理論。

看文本篇內容之後,我們來整理一下文章的思考脈絡:

整理思考脈絡

除了學習,工作要接手陌生的專案、文章或會議紀錄的大綱、找程式問題,有沒有習慣整理思考脈絡,做事的效率也會有明顯的差別。

最後以開場問題的 A 君來進行總結:

A 君可以從網站的角度切入第一層脈絡,Angular 前端框架主要處理的問題有哪一些(以下是簡單舉例):

- 開發的前置作業:開發環境的設定
- 管理網站底下的所有頁面位置:網站的路由
- 元件開發
    - 頁面 UI 元件
    - 共用 UI 元件
- API 串接的服務層
- 整個網站的資料共用:
    - 服務 (Service)
    - 狀態管理 (NgRx)
- 多語系
- 環境變數
- 建置與部署

隨著時間,不斷累積開發處理的問題和情境,加上框架本身的更新變化,A君對於 Angular 的思考脈絡也會跟著改變。不同的人,對於 Angular 的思考脈絡也不會一樣。

C、D君,兩位的思考脈絡,就留給讀者自己整理看看。

題外話:
曾經下班為了練習 Angular 13,透過完成 UI Libary 的過程,熟悉 Angular 13 大部分的 UI 元件的語法,有興趣可以參考看看,怎麼轉成新版的 Standalone & Control Flow 寫法:
https://ngx-youi.github.io/NGX-YOUI/

第二篇內容到這邊結束,謝謝大家耐心的閱讀。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
lctgood
iT邦新手 5 級 ‧ 2024-01-12 09:27:19

感謝分享

我要留言

立即登入留言