Skip to content

Instantly share code, notes, and snippets.

@dboyliao
Forked from ccwang002/0_Background.md
Last active August 29, 2015 14:19
Show Gist options
  • Save dboyliao/9c13e56ecadd1c518c75 to your computer and use it in GitHub Desktop.
Save dboyliao/9c13e56ecadd1c518c75 to your computer and use it in GitHub Desktop.

[TOC]

Lab Guide for Coding Beginners

亮亮(@ccwang002)| Mar, 2015 | CC 3.0 BY license

如果內容有誤,你可以用任何管道發訊息轟炸我,或用底下的 gist comment 留言。

學習方式

每個檔案都會是一個主題,主題底下會列出一些資源。資源的最後會有一個學習目標,方便讓你評估自己學到什麼程度。學習目標會給一個明確的任務,我盡量讓它能跟(宅宅的)日常生活結合。通常只要完成前一、二個目標就行了,這也不是功課所以不一定要給我看。如果你不介意給我看,我會分享我主觀的建議,但大部份的任務是沒有絕對的正確答案。只要能解決問題都是好方法。

這些資源不用全看,任務不用全做,大家自己斟酌要花多少時間在不同的主題上。

挑你喜歡的東西盡量鑽,沒有 fu 的就隨便看看會了就好

我會盡量按照難易度排列,中英文的資源都放。

簡介

以下的內容,目標讓大家了解當今軟體開發流程及基本技能。但軟體開發需要一些背景知識,才能與開發者正常交流。這些背景知識包括:

  • 一個很多人用的工具長什麼樣
  • 如何把自己的程式與別人分享
  • 多人共同開發
  • 其他人都怎麼樣寫程式

這些內容在學校課程的訓練中會比較少,尤其是電機背景的話在寫程式又更為隨性,但這對一個長期的軟體專案是必需的。希望大家能在這個專題中養成這些習慣。

這些課題需要熟練到什麼程度,見人見智,深入下去每一個都夠花幾個月的時間鑽研,但以一個實驗室專題、或要完成的軟體專案來說都不實際。所以個人覺得,最低標準就是在遇到該課題不懂的地方時,「能知道怎麼下關鍵字查」且「查完的結果能看得懂」。

Q: 為什麼不帶大家手把手教學?

簡單地說沒空。認真地說,大家的學習速度跟底子都不一樣,同步學只是浪費各位的時間。

我大概沒有辦法一個一個項目帶大家練習,底下的很多連結只是提供一個學習的窗口,真正要學下去,都是要花一定時間的。所以也不要抱著「只要讀完這些文章就會了○○○」這樣的想法。

白話的來說,這些背景知識就像遊戲的技能樹,基礎技能要先點好才能點進階技能。要把基礎技能點滿了再練等也可能,但不必要,也不是大家都喜歡練功的方式。

一開始可能碰到小問題就要查,或者要連續查很多個網頁被導向四、五次才能稍微解答自己的疑問。這個現象是非常正常的,如果大家能撐過初期這段比較挫折的時期,日後要自學軟體基本上就沒問題了。

熟練來自生活中的實踐

要很快地學好程式,我推薦練習把程式應用在生活中。例如用文字命令列來下載檔案;把自己筆電變成 linux 桌面系統,練習自己編譯軟體、解決各式安裝的狀況。讓自己的電腦成為一個自己能接受的軟體開發環境,並經常的使用它,就能降低對寫程式的陌生與不知所措感。

上面的方法可能稍難一些,負擔比較小的可以開始做「思考練習」。思考練習包含去想生活中的大小事該怎麼寫程式來控制。例如我該怎麼設計一個電梯系統?臉書怎麼呈現大家的動態?只要大概想一想就好了,想不出來也不會怎樣,也不用特別查資料。過一段時間對程式的 sense 也會提昇。

如果需要更硬派的學習方式,不妨把自己電腦安裝的軟體的源始碼都拿出來看一下,加入幾個自己平常用的軟體的專案來修改它,讓它更少問題更多功能(一般叫 contribute)。也可以把實驗室有用到的工具的源始碼拿出來看一下,例如 sratoolkit、cutadapt,看看自己能不能讀懂別人的程式碼。

給 Windows 使用者

TL;DR 建議大家想辦法裝個 Linux(或用 Mac)。如果不想取代掉自己的 Windows 環境話,可以安裝 VirtualBox 裝個虛擬的 Linux,或者在 Amazon 等 VPS 架一台虛擬主機。

Windows 因為對圖形介面(GUI)設計的很好,也不容易讓使用者用命令列模式(terminal, console)。雖然 Windows 上有像 command prompt、Powershell 之類的環境,但都很難用它來操控整個系統。而且它打從骨子就跟 Linux 不一樣,所以相關的指令不好在網上的教學文章中找到,而多數 Windows 的開發者也不喜歡用 terminal。

另一方面,大家對 Visual Studio 的印象都是要收錢的�註1,這是 Windows 上最完整最好用的開發環境,不想付費的情況下可能就會覺得「寫程式充滿障礙」,更何況 VS 也是圖形化的編輯器,也會不了解背後運作的方式。市面的開源軟體多半在 *nix 上開發,對 Windows 支援度差也加深這個障礙(「想要自己裝但都一堆限制又很容易失敗」)

註1:Visual Studio 自 2013 後有 Community 版本,免費但內容與 Professional 版本大致無異,所以未來要有 C/C++ 32/64bit Compiler 會更容易。但多數的開源軟體還沒跟進,所以很多還在用舊的 VS 版本(就要付費),這個現象還會持續一陣。學校都有買。

不用 terminal 的壞處是很難想像自己系統中的軟體為什麼能運作。感覺要寫個有 GUI 的程式都要很厲害,跟自己學過的寫程式都不一樣。但實質上是沒有太多區別的,只是要完成一個能安裝在系統中的視窗軟體,需要的步驟多很多,一般簡單的專案都不會到那個階段。

給 OSX 使用者

Mac OSX 使用者也有這樣的現象,但因為 OSX 在底層用的是跟 FreeBSD 很相似,而 FreeBSD 跟 Linux 相似,所以它的 terminal 環境是很完整的。現在軟體開發者很多人用 OSX,因此網路上 Linux、OSX 資源都很多,兩者的經驗常能自然地移植。

如何要在 OSX 上開發程式,可以參考附錄 0 的筆記,但內容很主觀,不是每個人都會像我這樣用。

目錄

寫一寫內容也變得蠻多的,所以把它切成了幾篇文章,請按照數字順序閱讀:

[TOC]

Linux First Try

這是第一個比較大的障礙,因為會在短時間接觸到非常多新的東西。後面的東西多少都與 Linux 相關,而 Linux 難的部份在開始使用 terminal 來操作「整台電腦」,對很習慣使用視窗介面的人會覺得很不直覺。好在近年幾個主流的 Linux Distribution 都有很好的圖形介面(正確稱 Desktop Environment),所以一開始能漸近地適應 terminal 操作。

在實驗室 server 上開發,「能在 terminal 裡做事情」是必須的。

Linux、Unix、BSD、*nix

Linux 和 Unix 是不同的,但對初學者來說他們的分別不容易查覺,兩者的終端指令很相似,也因此有了 *nix 的通稱。Linux 介紹書多半會把他們的歷史好好的說一遍註2,有興趣聽軟體發展故事的就多留意這部份。

不完整地主要分成:

  • Redhat, CentOS, Fedora
  • Debian, Ubuntu, Linux Mint
  • ArchLinux
  • openSUSE
  • FreeBSD, OpenBSD

這些 distributions(簡稱 distros)。其實 Linux、BSD (or Unix) 的系統非常多註3,但對初入 Linux 的使用者,應該要找比較熱門的 distro 使用,才好找資料。

上面條列的方式是有意義的,我把類似的 distro 放在同一排,只要學了其中一個,同排的其他都很好上手。其中前兩排是兩大家族反映兩種生態。我們實驗室的大 server 用的是 CentOS;但近年來我自己的電腦已經漸漸換到 Debian 上。

註2:Linux distros 源流 http://en.wikipedia.org/wiki/Linux_distribution

註3:Distro Watch 是一個介紹各種 Linux、BSD 系統的地方,可以來這邊看各個 distro 的介紹。

Distro 簡介

以下是我不負責任的主觀介紹。從介紹篇幅就知道我是個傾向 Debian 的人。

Redhat 是商用的版本,開源社群維護的對應版本是 CentOS。它以保守穩定著名,但相對來說新的東西在上面就要自己安裝,這對實驗室都用較新的工具來說是個減分的地方。他套件用 yum xxx 來操作。Fedora 上的東西會新一點但我們實驗室沒人用,所以不建議。

Debian 是另一個大家族的頭,雖然是頭但一直保持穩定開發,在說明文件、wiki上都有不錯的品質。本身有所謂的 stable、testing、unstable 並分別對應三個版本號碼與名稱。以 2015.03 為例,stable 是 Wheezy(7)、testing 是 Jessie(8)。unstable 永遠對應到 sid。如字面上的意思代表當中套件(軟體)的新舊程度。stable 上的工具也因此會比較舊不適合實驗室使用,但 testing 還蠻適合的,我個人很推。套件用 apt-get xxx 來操作。

Debian 家族中的 Ubuntu 非常火紅,網路上教學非常多,背後也有公司加持。基本上 Debian 的優點都會傳到 Ubuntu 上。Ubuntu 雖然套件包等等都從 Debian 移植,但他有自己的版本號碼,每半年發佈一個版本。

再來的有興趣自己看,但我要額外介紹一個 ArchLinux。這是一個很自幹的系統,一點都不適合新手與懶人。但他有一個寫得很仔細完整的wiki 站。想要學新的套件、不會設定的話,去問 google 的時候請優先看他們的 wiki。

查資料的時候,除了 StackOverflow 、Ubuntu 論壇之外,請多看品質優良的 Arch Linux 和 Debian 的 wiki。

寫了這麼多,沒有給一個明確的選擇,多數人還是很難決定。所以如果你是初學者,我會建議安裝 Ubuntu,在此時請選擇 14.10 Desktop 版本,因為他網路上的資源最豐富。

但我不是很喜歡 Ubuntu,所以等你有能力自己查詢 Linux 相關操作時,建議再看看別的 distro (例如我推薦的 Debian testing channel

桌面環境 GNOME、KDE、XFCE、LXDE

圖形化介面(GUI),除了使用者的應用程式外,還需要系統輔助、管理等核心套件。一系列的 GUI 套件就稱之為桌面環境。

Windows、OSX 在安裝系統時都會自動安裝, 即桌面環境只有一種選擇。但在 Linux 上,GUI 的安裝是選擇性的,系統能在只有單純的 terminal 介面便能完整使用(例如選擇安裝 Ubuntu Server 時),不少 server 為了效能、安全性的考量都不會裝桌面環境。

對 Linux 來說桌面環境是能之後再選擇安裝上去的,而且還有「不同口味」可以選擇,使用者也可以自由的移除它們(但很有可能會炸掉),常見就有 GNOME、KDE、XFCE、LXDE註4 幾種系統能使用。例如選擇安裝 Ubuntu Server 後,想要再加上 GNOME 列圖形化介面時,

sudo apt-get install ubuntu-gnome-desktop

這邊不會去細講這些實作方式的不同。簡單而言,GNOME 最流行。XFCE 使用的系統資源較少,在實驗室上的 server 常會裝這個。在 Ubuntu 上,預設是用 Unity,它是從 GNOME 沿伸出來的。

註4:LXDE 原作者是 PCMan 喔,也有相當多的台灣人在維護它。

第一次安裝時,就使用預設的模式吧。裝好之後要換到不同的桌面環境時,需要對套件管理系統(例 apt、yum)、調整系統設定有足夠了解。

相關資源

認真的說,我有點不知道 Linux 從很初學到完整學習的資源在哪裡。如果你們在學的過程中,有碰到更適合的請再告訴我(可以利用 gist 底端的 comment 區)

鳥哥的私房菜

在台灣學 Linux 大概都會先推薦鳥哥,這應該是最多人用的完整中文資源了。如果願意啃完他,對 Linux 絕對會有足夠的認識。我大學的時候也是看這本入門的。

不適合的地方是鳥哥介紹 Redhat 系的操作,很多設定在 Ubuntu 上不需要或者是用別的方式去管理。例如,在 CentOS 上可能都用文字檔來修改設定,但在 Ubuntu 上可以用 dpkg-reconfigure 指令來更動。他示範的 OS 為 CentOS 5.x,現在 CentOS 已經 7.x 版了,許多設定也過時了,新的工具不會介紹到。

例如現在安裝 Linux 時,在磁區分割上都有很好的預設值,初學者可以不用再學調整 swap 等設定。同時系統也都提供使用 LVM (Logical Volume Manager) 註5 管理磁區,這些磁區 (LV) 日後能動態調整。換句話說,第五章(含)的內容都與現在使用 Linux 的方式不同,如果只是順著鳥哥書的順序一章一章看下來,會沒辦法對照自己系統操作,因為近期的 Linux 安裝只要很順的下一步就能完成了。

註5:LVM 不懂沒關係,有興趣可以參考鳥哥十五章Arch Wiki 介紹

各章節重點整理

鳥哥的內容退一千步來說都對初學者很有幫助,但為了避免各位花費無謂的時間在「對照古早與現代操作 (google 到的資料)上」,整理個表格讓大家知道每個章節什麼地方需要看。

章節 章節名 重要的內容
0 計算機概論 沒聽過 CPU、RAM、MB GB 單位就從頭看; 不然就讀資料表示方式(3)、軟體程式運作(4)
5 首次登入與線上求助 man page 文字模式下指令的下達(2)、man page 與 info page(3)、nano(4)
6 Linux 的檔案權限與目錄配置
7 Linux 檔案與目錄管理 除檔案隱藏與特殊屬性(4)外都重要
8 Linux 磁碟與檔案系統管理 檔案系統的簡單操作(2)
9 檔案與檔案系統的壓縮與打包 壓縮檔案的用途與技術(1)、打包指令(3)
10* vim 程式編輯器 語系編碼轉換(4.3)
11 認識與學習 BASH 全。但可視情況忽略 2.4-2.8、6.4
12 正規表示法與文件格式化處理 前言(1)
13 學習 Shell Scripts 全(等用到再看)
22 軟體安裝:原始碼與 Tarball 全(了解流程、懂有這些關鍵字就好)
23 軟體安裝: RPM, SRPM 與 YUM 功能 Ubuntu 用的是 APT

*學 vim 有別的資源,詳見 2 Text Editing

正規表示(regex)很重要,但初學 Linux 時會覺得很複雜可以跳過。 2 Text Editing 會再接觸到一次 vim 的 regex、4 Python 也會學到 Python 的 regex,可以等到時候再回來學 sedegrep 等指令。

APT 的使用教學可以參考 Ubuntu 官網網路上大大的筆記

Introduction to Linux on edX course

Linux Foundation 所開辦的線上課程,有英文的影片和講義。還請到了 Linux Kernel 的作者 Linus Torvalds 來拍介紹片。這是真的從非常基礎開始講,我有稍微看過,但我怕難度不夠,需要再搭配其他的資源來使用。好處是初期的學習比讀鳥哥前幾章來的快非常多(鳥哥前幾章為計算機概論)。

Debian User Manual

英文的 Debian 系統使用者手冊,裡面包含了常見問題排解、各種硬體上的安裝指南、參考手冊。想要好好學習現代 Debian (Linux) 的使用方式的話,可以參考這些資源,它們還有再維護。

缺點是這手冊太長了,如果有碰到什麼特別想了深入了解的,建議可以看這個。

Chapter Highlights

Chp. No Chp. Name Highlights
1 GNU/Linux tutorials Everything except for 1.3 Midnight Commander
2 Debian package management Read 2.2 Basic package management operations
10 Data management Read 10.1 Sharing, copying, and archiving

學習目標

因為這邊指的 Linux 算是一個蠻廣的內容,一開始學的時候很容易迷失方向。所以我額外列了幾個很重要的觀念,你應該能在學習 Linux 的初期接觸到他們:

  • 了解 $PATH 與程式執行位置的關係

    為什麼打 ls 可以找到這隻名為 ls 的程式

  • 知道 stdin、stdout、stderr;pipeline 的使用

  • 知道環境變數是什麼,怎麼修改

  • 了解檔案、目錄、相對路徑;權限設定

  • 使用 <cmd> -h <cmd> --help man <cmd> 來查看指令的功能、可下的參數

    <cmd> = 任何在 linux 下的指令

如果你花了一個禮拜的時間,但上述的內容連聽都沒聽過(或沒什麼使用到),那很可能你學習 Linux 的方式跟我想得很不一樣,請先寫個信告訴我。上面這些觀念的學習也是漸近式的,過了一個禮拜只有聽過但不是很了解,這是很正常的現象。

  1. 自己從零開始安裝一次 Linux 系統(可以用 VM)。

  2. 定期使用它一個星期以上(即熟悉 cd ls 等基礎指令)

  3. 使用 ssh 連線到遠端的 Linux。(要打開 ssh 的 port)

    Bonus: 在 ssh 連線時不用打密碼。
    Bonus hint: 查 authorized_keys。會需要建立 ssh user identity keypair,這會在上傳 GitHub 時用到)

  4. 安裝一個叫 htop 的系統監控軟體。使用它來查看系統資料的使用狀況

    Bonus:

    • 調整欄位的排版
    • 開啟 Tree Veiw
    • 選擇顯示單一使用者運行的程序(太舊的 htop 可能沒這功能)
  5. 安裝一個叫 aria2 的續傳軟體,他可以多線程下載 HTTP(S)、FTP、甚至 BT。今天想要下載 Debian Jessie netinst 的映像檔,使用 2 個線程同時下載。

    Hint: 查 aria2c 的 man page。

  6. 學會查看系統硬碟的使用量;查看當前目錄內所有檔案的大小(絕對不是 ls -l

    Hint: dfdu

  7. scp 是個透過 ssh 傳送一或多個檔案的指令,試著用它把自己電腦的檔案(們)傳到 server 上。

    Bonus:

    • 在路徑中搭配特殊字元 *? 傳多個檔案
    • 有一個更精密的傳檔工具叫 rsync,試著改用它來傳檔。
  8. 使用 GUI 的遠端介面。這相關的技術有很多:VNC、RDP 最常見。 RDP 在 windows 連接上比較順暢;VNC 在畫面傳輸比較沒效率,這會對 server 造成不小的負擔,也很容易 lag。有一個新的通訊協定叫 NX,它對畫面壓縮使用即便網速很慢依然能使用圖形介紹。
    試著用實作 NX 協定的軟體 X2go 做遠端桌面連線到 server。

    Hint: 你需要在 server 與 client 端(通常是自己的電腦)都裝上 X2go 的軟體,並會使用到 SSH 的連線設定。

  9. 只用 Linux 生存一個星期以上(包含中文輸入、上網等等)

[TOC]

這個章節會帶大家認識一個很簡單的純文字格式 Markdown,方便大家整理筆記。同時希望大家學會一個 terminal based 的文字編輯器,方便往後在 server 環境底下的操作。

Markdown

這是一個簡便的語法,它的概念是在純文字的檔案中用一些簡單的標記,就能做出大小標題、粗斜體、超連結、表格、程式碼上色等語法。

如果大家了解網頁的格式 HTML 的話,那 markdown 的語法能直接對應到 HTML 的語法,所以這個格式在網路的世界十分流行。它的副檔名為 .md,近代程式的 REAME 許多都用 markdown 寫成(例:README.md

相關資源

Markdown 語法

學習目標

  1. 這一系列的筆記就是用 markdown 寫成,你可以點右上角的 Raw 按鈕看到它的原始檔。
  2. 試著把 Linux 學習過的指令,或者自己常用的組合指令用 markdown 記錄。

Text Editor

在 Linux 的世界很多都是純文字檔案,再加上一些規定的語法成為新的格式。前面的 markdown 就是個例子。甚至許多可以執行的程式都只是個腳本檔,能用一般的編輯器(editor)打開就能讀懂。你可以試試

# cd is a shell script
nano (which cd)       # thanks TP's idea

常見的 editor 有:nano、vi、vim、emacs。到底什麼是最好用的文字編輯器,這是一場永無止盡的戰爭,近年來又有 Notepad++(GUI)、Sublime Text (GUI)、Neovim 的加入,這話題將不會有結論。對初學者而言,至少學會一個 editor 是必要的。

雖然一開始都說是介紹文字編輯器,但後來會開始學程式設計,所以最後大家在討論的都是「程式碼的編輯器」。

當在編輯一些設定檔、程式碼時,為了避免打錯關鍵字但難以查覺,多數人會把程式碼的關鍵字上色。按照程式碼不同的屬性、功能上色之後,多數人發現能更好的理解程式的結構,因此 editor 大多帶有語法上色(syntax highlighting)。

除了語法上色,這些 editor 都有自己的設定檔規範,可以讓使用者自行修改 editor 的行為。把自己常見的編輯器改得合乎自己習慣,是長期生活在 terminal 世界的第一步,大家可以參考(抄)別人的範本開始。

讓自己的編輯器有家的感覺。

除了設定檔之外,功能多的編輯器還會有「外掛」的功能,可以讓使用者增加自己的套件。這也等大家熟悉環境之後再自行玩玩吧。

Nano

這是一個操作簡單好懂的編輯器,沒有語法上色註1。多數的系統都有內建,所以到一個新的環境時幾乎都能使用。

鳥哥有教。其實直接執行它 nano 它的指令都會顯示在編輯畫面中。

註1:nano 其實有辦法做語法上色喔,詳見 Arch wikinanorc。Thanks @concise

Emacs

抱歉,我不會。但它是一個很好的編輯器。(誠徵大大補全)

Vim

一個老字號但維持穩定開發的編輯器。他有個特色是編輯器的模式,有些模式能編輯文字,有些不行,但能做選取、搜尋等動作。還有特有的指令合成方式(像連續技、buff 這樣)

初學者通常會難以習慣,初期不熟模式、指令記不住的話會很難操作。所以建議一開始先記住最基本的指令,隨時掌握自己在的模式,日後再慢慢加深對 vim 的了解。

如果真的很沒概念,鳥哥也有寫介紹。

Vim 相關資源

Open Vim

互動式的線上學習網站,很短,跟著操作完能會 Vim 基本動作、存檔。

學習 Vim 的心法與攻略 (ptt)

了解最常用的 normal 與 insert 模式及最基本的指令。這篇的內容理解之後,就能用 vim 處理文字編輯了。

Vim adventure

如果很難學習 hjklwb 移動的話,這是個要用 vim 指令控制的小遊戲。

Vim 本身的使用手冊

可以使用 vimtutor 指令,或者在 vim normal 模式時鍵入:help

學習目標

  1. 能在 terminal 中編修一個文字檔名為 foo.txt

    Hint: try nano

    nano foo.txt
  2. 搭配 root 權限修改系統的設定檔(你在鳥哥可能有經驗了)

    Hint: try sudo

  3. 能在 console 中編寫程式碼。用 1. 的方案也可,但多數人會想要有 syntax highlighting

    Hint: try vi, vim or emacs

  4. 修改 editor 設定讓它更符合自己的習慣。

    Hint: for vim, try editing ~/.vimrc; for emacs, try editing ~/.emacs

  5. 用 terminal editor 使用 markdown 格式記錄這些練習的筆記與答案。

正規表示式 Regex

Vim 在 normal 模式下能用 /{pattern} 搜尋文中的字串。除了直接把想要查的字串寫在 pattern 裡以外,還可以設計規則找出符合 pattern 但不一樣的結果。這樣的規則稱之為正規表示式(Regular Expression, or regex)。

想做很複雜的字串比對時,都應該考慮是否能使用 regex

要做字串比對的地方,工具通常都會提供使用 regex,例如 grepsed。Vim 與 Python 也都有提供 regex 的功能。

Regex 語法派別

既然 regex 是一套字串比對的規則,就有規範它的語法。主要的 regex 語法有兩大類:

  • BRE (basic regex)
    • Ex. [:alnum:]
  • ERE (extended regex)
    • Ex. \w

在 Linux 指令當中通常會因為使用 regex 語法的不同分成多個指令註2。例如 grep 使用 BRE;egrep 使用 ERE。

與文字編輯相關的工具,像 Vim、Python、Perl註3也有他們各自寫 regex 的方式,但多少都與前兩大類相似,使用時都應該先查一下他們的語法。Vim 可以用 :help regex 查看。

註2:哪些指令有無支援 regex 以及支援的語法可以參考 Debian Reference

註3:Perl 的 regex 語法又稱為 pcre style,常被其他工具使用。例如:php

相關資源

Regex One

主要是介紹 pcre 的語法,每一個 example 多介紹一個新的語法。接著還有個 practical examples 練習整理不同的語法。

Regex 101

regex 很容易寫到自己都看不懂,這是一個幫助了解自己或別人寫好的 regex pattern 的網站。

[TOC]

Git (Version Control)

Git 是一個版本控制的工具。

所謂的版本控制就跟玩遊戲一樣可以存取「進度點」,破關前都會保存進度,這樣破關失敗的時候可以還成到保存進度的狀態,再重新打怪。版本控制用在管理程式碼時,就方便讓自己在把 code 搞炸掉的時候,還能回到先前有保存的狀態。

為什麼使用版本控制?

在軟體開發的過程中,程式碼每天不斷地產出,過程中會發生以下情況:

  • 檔案被別人或自己覆蓋,甚至遺失
  • 想復原前幾天寫的版本
  • 想知道跟昨天寫的差在哪裡?
  • 是誰改了這段程式碼,為什麼 ?
  • 軟體發行,需要分成維護版跟開發版

因此,我們希望有一種機制,能夠幫助我們:

  • 可以隨時復原修改,回到之前的版本
  • 多人協作時,不會把別人的東西蓋掉
  • 保留修改歷史記錄,以供查詢
  • 軟體發行時,可以方便管理不同版本

From: Git 教學研究站

Git 會在你的專案(repo)目錄註1底下建一個 .git 的資料夾來管理這些「進度點」,而不會去動專案其他路徑裡的東西。

這些進度點可以傳到 server 上,別人下載下來的時候就可以除了得到現在的 code 以外,還能看到過去開發的記錄;而別人上傳了他的更新進度點之後,你抓下來就可以得到他更改的進度。這個就是「同步」的概念,多人之間能彼此共享、更新彼此開發的成果。

能夠處理 Git 同步操作的伺服器就叫做 git server。Github 就是一間公司提供免費的 git server 讓大家同步公開的 Git 專案。很多 Linux 的工具都使用 git 來讓大家合作開發,也有不少工具已經把 git server 轉到了 Github 上面。所以非常多人在用,因此建議大家不妨申請一個 GitHub 帳號。

註1:所謂的專案目錄就是下 git init 指令的目錄。

Git 雖然最常用來管理程式碼,但它其實可以有效地管理任何純文字的檔案,也可以把 binary 檔案加到 repo 中。

(可能需要有一些 git 操作經驗才能了解以下的術語)

操作建議

建立多而小的進度點

每完成一系列的更動,就趕快 add 和 commit。一開始會煩,但這是好的習慣。

日後更了解 git 操作的時候,會學到一些進階的指令(如 git rebase -i)就能把多個 commit 合成為一個。但要拆開一個大的 commit 會比較複雜。

Commit Style

常見的 commit message 大概會是一行文。如果這個更動需要說明,那就建議按照下面的格式:

  • 第一行少於 50 個字元
  • 第二行留空
  • 第三行以後格式隨意,但單行不超過 75 個字元
  • 善用條列式說明

以下是範例:

Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to
about 72 characters or so.  In some contexts, the first
line is treated as the subject of an email and the rest of
the text as the body.  The blank line separating the
summary from the body is critical (unless you omit the body
entirely); tools like rebase can get confused if you run
the two together.

Further paragraphs come after blank lines.

  - Bullet points are okay, too

  - Typically a hyphen or asterisk is used for the bullet,
    preceded by a single space, with blank lines in
    between, but conventions vary here

From: Git Book

ps 你可以找到很多有趣的 commit message。例如:抱怨

常見問題

Conflict

當單機只有在一個 branch 上開發的時候,很難有 conflict 的問題。但碰到多人共同開發,或把多條 branch merge 在一起時就會有 conflict。

Conflict 的發生,最常見的就是兩個人各自修改了同一個檔案相近位置的內容。這使得 git 在把兩個人的更動融合在一起的時候,會不知道到底要用誰的更動,這時候就無法自動處理了。

可以搜尋「resolve git conflict」找到相關的解決辦法。

Push fail

這通常發在 server 上的進度點比自己本機的還要新,所以必須先把 server 上的更新同步下來。如果都是同一個 branch 的話,你可以試著用 git pull --rebase 去避免額外的 merge。

相關資源

Code School - Try Git

互動式練習,能懂最基本的 Git 指令操作,日常操作也主要是這些指令。並且會帶你建立一個 GitHub 帳號。

Git 教學研究站

中文的介紹,他的互動式練習就是上面 Try Git 的中文化版本。

Code School - Git Real

更完整的互動式練習,如果全部的關卡都做完的話,大部份需要用 git 的狀況都練習過了。

Learn Git Branching

顧名思義,是個練習操作 git branch 的線上學習網站。不過前幾個關卡在介紹 commit 相關的操作,可以試一試。真要練習可以先完成 Main 以下 levels:

  • Introduction Sequence
  • Ramping Up
  • Moving Work Around

其他稍難一點,視情況跳過。但如果想學 git 比較複雜的指令可以回來看它。

Git Tutorial by Atlassian

蠻完整的教學,但可能稍難一點。

學習目標

  1. 用 Git 管理這些練習的筆記(呈接在 Text Editors 的練習)

    Hint: 本教學即為使用 markdown 格式編寫的 Git repo, 存放在 gist.github.com。抓下來可用

    git clone https://gist.github.com/368025d3c541ed983892.git lab_code_intro
    cd lab_code_intro

    可以試著對它做一些 git 指令操作:

    git status 
    git log --oneline --graph
  2. 建立 dotfiles 和 dotvim 來管理你的環境設定檔。dotfiles 就是用來儲存 .xxx 的檔案們,像是 .bashrc.screenrc.tmux.conf.gitconfig 等等,一般可能存放在 ~/.xxx~/.config/xxx 之類。 用版本控制的好處是,這樣在不同的 server 之間設定可以同步。dotvim 是存放 ~/.vim 的 Vim 設定檔。這些設定檔可以透過 soft link 連結回他們原本應該在的位置。

    注意!永遠不要把 private key 放入版本控制中!
    Hint: 搜尋 dotfiles 就會有很多範例(Ex 我的

  3. 建立自己的 Github 帳號,並把 dotfiles / dotvim repo 同步(push)到Github。

    Hint: 建立設立好 ssh key pair 使用 ssh 上傳。Github 有完整的教學

Python

Python 是一種物件導向、直譯式的電腦程式語言,具有近二十年的發展歷史。它包含了一組功能完備的標準庫,能夠輕鬆完成很多常見的任務。

From: Wikipedia

選擇 Python 作為第一個深入學習的語言有很多好處。他的語法跟英文相似,比起其他語言經常用到 ;{}() 來控制語法不同的段落,Python 主要用的是空白與縮排。

Python 能用互動式的方式(read–eval–print loop, REPL)來操作,以邊試邊做的方法來開發很適合初學者。

內建的標準庫(standard library)功能很豐富,在網路、文字處理、檔案處理、甚至 GUI 介面都能用它完成。除此之外,它的第三方套件也很多,在 Linux 上很好安裝,這樣幾乎能用 Python 完成各種事情。

聽說系列

(需要接觸過 Python 之後才能理解)

聽說 Python 跑很慢,是不是不能用來計算/分析/大檔案?

Python 的確執行效率比編譯式的語言差(例:C/C++、Java),但這很可能不是你程式跑得慢的主因,所以也不代表 Python 不能處理計算量高的工作。

碰到程式跑得比想像中慢的時候,有幾個步驟:

  1. 到底是哪幾行程式跑得慢?
  2. 這是最佳的演算法嗎?
  3. 這是最有效率的 Python 語法嗎?

如果用到了最後一步情況還是沒有改善的話,就可以開始把那些部份用其他語言改寫,例如:C。Python 能很容易跟 C 語言的結合。而且常見的 C 語言加速,其實都有 Python 套件能支援了,例如 Numpy,所以大部份的時間,都能在不使用 Python 以外的語言完成高量計算。

我在實習時候,也常碰到需要優化的問題。用 Python 我能很輕鬆(一天內)把工作分配到 4 台主機 64 cores 上跑,也許方法不有效率,但比起我花幾天把 Python 改寫成 C/C++,實作更精密有效的算法(還要是 multithread),仔細處理可能的 corner case,平行化之後本來三四天的計算時間我 2 個小時就能收工。

更重要的是,這個實驗就只跑個兩次。

比起計算時間,開發時間對工程師而言是更加寶貴的。尤其在實驗室,最關心的是這個方法行不行得通,程式跑得慢有很多解決的方式,例如平行化。重點在解決問題,需要用多一點的資源其實不是很重要。

如果問我 Python 還是 Matlab 比較快?這邊有正經的 Python vs Matlab

(一開始選 Python 慢的話有很多條路可以走,但 Matlab 呢? meh)

所以 Python 跑得快不快?它單打獨鬥有極限,但它有很多快樂夥伴。O'Reilly 有本 High Performance Python 值得一看。

Python 2 還是 Python 3,聽我朋友說…比較好?

隨著時間流逝,每過一天我都可以更確信的說**「請學 Python 3」**。

現在有在用 Python 2 多半也是用 2.7 版本,要把 3.3+ 的程式碼改回 2.7 也不難。

相關資源

連同前幾章,如果你要在自己電腦上設定 Python 開發環境,可以參考 Djang Girls Taipei Tutorial。另外,Python Taiwan Wiki 有更完整的 Python 學習資源列表。

MOOCs

很多人都有試過的線上課程,可能有中文字幕。缺點教的是 Python 2.7。

深入淺出 Python

O'Reilly Head First 系列都是給初學者的書,這本有中文翻譯本,內容圖文並茂活潑。不過不是每個人都喜歡這種嘻嘻哈哈的介紹方式。

Introducing Python, O'Reilly

O'Reilly Python 系列的書都寫得很好。這本是比較新出的,好處是它針對初學者,而且比較薄能在短時間看完。建議閱讀 Chp1 到 Chp7 ,以及 Chp8 File Input/Output 部份。

可以在 O'Reilly 的線上商店買電子版拿到 PDF 與 Kindle 版本。

精通 Python 3 程式設計 2ed

另一本 Python 中文入門書,比深入淺出難一點但比較像常規的教科書。

Python 官網

Python 的官網一方面是用來查語言特性之外,還能用來學習怎麼使用 stdlib。除外還有一個簡潔的 Tutorial,可以供初學者參考,適合有學過其他語言的人。

Keep this under your pillow.

Learning Python 5ed

雖然名稱看起來很像是 Python 的入門書,但它的篇幅已經來到 1200 頁,實在無法推薦給初學者。但它把 Python 語言特性說的很清楚,同時考慮到 Python 2 和 3 版本。

我當初看的是這一本 3ed 中文版(現已絕版),那時還沒有考慮 Python 3。

Python Cookbook 3ed(Python 的錦囊妙計 3ed)

這本不是入門書但很適合深入了解 Python,並讓自己的程式碼寫得更 Pythonic。裡面介紹了很多寫法慣例 idioms,同時也有中文版。非常值得在未來比較懂 Python 時買來看。

學習目標

  1. 打開自己 Linux 裡的 Python3,跟著學習用的參考資料動手操作。用 REPL 以及運行腳本兩種方法來執行 Python 程式。

  2. 學習使用 pip 和 pyvenv (virtualenv) 來管理 Python 套件與環境。

    Hint: Python 官網是你的好夥伴。你可以在這裡這裡找到兩者的教學。

  3. youtube-dl 是一個用來下載 Youtube、Crunchyroll 等各大影音串流網站影片的工具。除了用 Linux 的套件管理工具安裝它,它其實是個用 Python 寫成的套件。為了避免跟 Linux 系統環境相衝,請開一個 Python 虛擬環境,並在裡面用 pip 安裝它。

    Note: youtube-dl 除了單純做下載串流檔之外,還支援轉檔、封裝、後製等影像處理,這需要 libav 或 ffmpeg 任一影像處理套件。在 Debian 系列的 Linux 上 libav 會好裝一點。

  4. 用 Python 解決一些實驗室會碰到的 Bioinfo 問題。有個網站 Rosalind 出了一系列的題目,我選了一些讓各位練習,請參考附錄 1

Appendix: Notes for OSX Development Environment

Terminal

OSX 系統有內建一個 Terminals.app 能像在 Linux 上一樣使用。他其實使用上沒什麼問題,不過想要調顏色,有更多自定功能的話,許多人會安裝 iTerm2

Homebrew, Git and Python

OSX 上官方沒有一個管理套件的工具,所以社群自行開發了一個叫做 Homebrew。你可以按照這篇教學安裝 Homebrew。

裝好了之後你可以以下指令去看它該怎麼操作

$ brew --help
$ man brew    # for full documentation

OSX 雖然內建有 git 與 python,但我們可以用 homebrew 安裝比較標準(新)的版本,

$ brew install git python3

如果 homebrew 有問題可以用 brew doctor 來檢測。把錯誤訊息問 google 通常就能找到解決方式。

Text Editors

我最常用的是 Vim。OSX 有內建,但也可以用 homebrew 安裝。

除了 console based 的 Vim,OSX 上也有像 gVim 的 �MacVim。一樣能用 homebrew 安裝。

$ brew info macvim  # 看 MacVim 在安裝有什麼選項可以調整
$ brew install macvim --override-system-vim --custom-icons
$ brew linkapps macvim

使用 Macvim 的時候除了 vim 之外,也可以呼叫 mvim 打開 MacVim。

Terminal Multiplexers

你有可能有聽過 screen 或者 tmux。前者在 osx 上有內建但版本很舊,在顯示顏色上會有問題,因此可以透過 homebrew 再安裝新的。但因為 screen 跟系統提供的重覆到了,所以預設不在 homebrew 的 repo 中,要先新增 repo 清單:

brew tap homebrew/dupes
brew install screen tmux

Git GUI

初學 Git 可能會不熟那些指令、常常不知道自己在 git log 哪個位置。這時候有個圖形化的工具會更方便了解。Git 有內建一個 gitk,但比較陽春。

在 OSX 上可以考慮用 SourceTree

Documentation Searcher

要一直查 Python 官網有時候還蠻麻煩的,未來學了 HTML CSS 等等不同語言或各種 Python 套件,要查個東西會很費時。所以有人開發了一個離線的 documentation 查詢器叫做 Dash。他要錢但有免費版,似乎是會一直跳提示訊息。

Misc.

  • Alfred App:一個延伸版的 Spotlight,查應用程式很快速,同時也可以跟 Dash 整合讓查 doc 更方便。
  • Macdown:OSX 上的 markdown 編輯器。

Appendix: Bioinfo Practices using Python

I want to play a game.

We are going to walk through a series of practice created by Rosalind Team.

Once you register an account at Rosalind, you can use their judging system to work through all problems. However, in this case you cannot arbitrarily skip easy levels and it sucks. So I'm not going to force you using the system. Luckily, in each problem one set of example data and expected output is given, which can be used for checking our answer.

Note: Their code assumes Python 2 but everthing I mention here is Python 3.

Python Basics

Do their Python Village problem sets. If any topic you don't know, go read your Python reference.

Should be very trivial.

Bininfo First Try

Q DNA: Counting DNA Nucleotides

Link: http://rosalind.info/problems/dna/

Hint: use collections.Counter

More Hint: use ' '.join and list comprehension to output the answer

Q REVC: The Secondary and Tertiary Structures of DNA

Link: http://rosalind.info/problems/revc/

Hint: reversed for any sequence object and a dict for nucleotide code mapping

More Hint: done in a list comprehension

Q: GC: Computing GC Content

Link: http://rosalind.info/problems/gc/

This is the first complicated problem that some abstraction should help you come up the solution. Try write some re-usable code blocks, for example, function calls and class definitions.

Don't worry about the computation complexity

Workthrough

You should implement by yourself before looking my solution. Also I didn't see their official solution so my solution can differ a lot from theirs.

Intuitively, we need to implement a FASTA file parser. FASTA contains a series of sequence reads with unique ID. From a object-oriented viewpoint, we create classes Read for reads and Fasta for fasta files.

Read is easy to design and understand,

class Read:
    def __init__(self, id, seq):
        self.id = id
        self.seq = seq

Since we need to compute their GC content, add a method for Read.

class Read:
    # ... skipped
    def gc(self):
        """Compute the GC content (in %) of the read."""
        # put the logic here (think of problem Q DNA)
        gc_percent = f(self.seq)
        return gc_percent

Then we have to implement the FASTA parser, which reads all read entries and converts them through Read. In real world we are dealing with myfasta.fa-like files, but here the input is string.

class Fasta:
    def __init__(self, raw_str):
        """Parse a FASTA formated string."""
        self.raw_str = raw_str
        # convert string into structured reads.
        self.reads = list(self.parse())
        
    def parse(self):
        """Parse the string and yield read in Read class."""
        # though we have no idea right now, the code structure
        # should be something like the following.
        raw_lines = self.raw_str.splitlines()
        for line in raw_lines:
            yield Read(...)

Here I use yield Read(...), which may be unfamiliar for Python beginners. It turns parse(self) function as a generator. Generator makes you focus on the incoming data. Once data is parsed and converted, the result is immediated thrown out by yield. We don't care about how to collect all the results. In our case, we catch all the results into a list by list(...).

So how should we read FASTA file? A simple rule in this case is that every read consists by two continuous row. Also, the first row will always be the first read id.

All we need is read two lines at the same time. Here a Pythonic idiom is introduced. The following code read two non-overlapping lines,

for first_line, second_line in zip(*[iter(raw_lines)]*2):
    yield Read(id=first_line, seq=second_line)

By zip(*[iter(s)]*n) magic, we are very close to implement a full parser. You could find a lot of explanations for this magic.

Read id line percedes with a > sign, so we could use something like first_line[1:] or first_line[len('>'):] for explicity.

Then sorting the GC% of reads in a FASTA file is easy.

fasta = Fasta('...')
sorted_reads = sorted(fasta.reads, key=lambda r: r.gc())  # note 1
top_gc_read = sorted_reads[-1]  # note 2
print(
    '>{0:s}\n'
    '{1:.6f}'  # note 3, 4
    .format(top_gc_read.id, top_gc_read.gc())
)
  1. sorted(list, key=key_func) sorts the list based on the return value of key_func applied to each element.
  2. or top_gc_read = sorted(..., reversed=True)[0]
  3. two string with no operands in between will be joint automatically. In this case it is exactly >{0:s}\n{1:.6f}. This is useful to tidy a super long string.
  4. '...'.format() fills the string with given values. See doc.

In real case FASTA can span across multiple lines, also likely the file we parse is broken. How could we modify this parser to handle these situations?

Q: (next?)

I'm super tired now so I'll leave the rest for you. Try those problems within yellow correct ratio range.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment