寫代碼是最后的手段
作為一名軟件工程師,你在工作時應(yīng)盡量少寫代碼。碰到問題時,你首先想到的不應(yīng)該是“我怎么解決這個問題”,而是“其他人是不是已經(jīng)解決了這個問題,我能使用他們的方案嗎?”如果你自己去解決一個常見的問題,很有可能別人已經(jīng)有了解決方案。先在網(wǎng)上檢索解決辦法,只有在確定沒人解決過該問題之后,才開始自己動手解決。
DRY
DRY是不要重復(fù)自己(Dont’t Repeat Yourself)的簡稱,指的是不要在程序中編寫重復(fù)的或是基本相同的代碼。正確的做法是將代碼封裝至函數(shù)中,后續(xù)可重復(fù)使用。
正交性
正交性(Orthogonality)是《The Pragmatic Programmer》中提倡并普及的另一個重要編程原則。亨特和托馬斯認為,“該術(shù)語已經(jīng)被用來表示某種獨立性或解耦化。如果兩個或多個事物之間的變化不會相互影響,那么它們之間就存在正交性。在設(shè)計優(yōu)良的系統(tǒng)中,數(shù)據(jù)庫代碼與用戶界面之間是正交的;調(diào)整用戶界面不會影響數(shù)據(jù)庫,替換數(shù)據(jù)庫也不會改變用戶界面?!睂嵺`中請牢記,“A不應(yīng)該影響B(tài)”。假設(shè)我們有兩個模塊module_a和module_b,module_a不應(yīng)對module_b中的內(nèi)容進行修改,反之亦然。如果設(shè)計的系統(tǒng)中A會影響到B,而B又影響C,很快就會失去控制,系統(tǒng)將變得無法管理。
每個數(shù)據(jù)都只應(yīng)保存在一處
假設(shè)手上有一個數(shù)據(jù),我們只需要將其存儲在一個地方。例如,我們正在開發(fā)用來處理手機號碼的軟件,其中有兩個函數(shù)要使用地區(qū)編號的列表,這里要確保程序中只有一個地區(qū)編號列表,而不是為每個函數(shù)重復(fù)創(chuàng)建。正確的做法是創(chuàng)建一個保存地區(qū)編號的全局變量。更好的解決方案則是將信息保存在文件或數(shù)據(jù)庫中。
函數(shù)只做一件事
我們寫的每個函數(shù)應(yīng)該只做一件事。如果發(fā)現(xiàn)函數(shù)太長,請檢查其是否在完成多個任務(wù)。將函數(shù)限制為只完成一個任務(wù)有很多好處。首先,代碼可讀性增強,因為函數(shù)名稱可以直接說明其功能。如果代碼出錯,調(diào)試也將更加方便,因為每個函數(shù)只負責一個特定的任務(wù),我們可以快速隔離并調(diào)試問題函數(shù)。用許多知名程序員的話來說:“軟件的復(fù)雜性大多源自試圖兩件事當一件事做。”
若耗費時間過長,你的做法很可能就是錯的
如果你不是在處理非常復(fù)雜的問題,比如處理大數(shù)據(jù),但是程序卻要花很長時間才能加載,這時可以認為你的做法很有可能錯了。
第一次就要用最佳的方法完成
在編程時你可能會這樣想:“我知道有一個更好的做法,但是我已經(jīng)開始編碼了,不想回頭重寫?!蹦俏医ㄗh你停止編碼,改用更好的方法來完成。
遵循慣例
學(xué)習(xí)新編程語言的慣例,能夠提升閱讀用該語言編寫的代碼的速度。PEP8 是一系列編寫Python代碼的指南,強烈建議閱讀,可前往https://www./dev/peps/ pep-0008/查看。
使用強大的IDE
到目前為止,我們一直使用的是Python自帶的IDE——IDLE來編碼。但是IDLE只是眾多可選IDE中的一個,而且我也不推薦長期使用它,因為其功能有限。例如,如果使用更強大的IDE打開Python項目,每個Python文件都會有不同的選項卡。在IDLE中則是每個文件新開一個窗口,操作煩瑣且文件之間來回切換困難。
筆者使用JetBrains公司開發(fā)的一款名為PyCharm的IDE。他們提供了免費版和專業(yè)版兩個版本,這款I(lǐng)DE有如下特性能夠幫助我們節(jié)省時間。
1.如果想查看某個變量、函數(shù)或?qū)ο蟮亩x,PyCharm提供了一個快捷方式,可以跳轉(zhuǎn)到定義變量、函數(shù)或?qū)ο蟮牡胤剑词故橇硗庖粋€文件)。PyCharm還提供了跳回開始頁面的快捷方式。
2.PyCharm有保存本地歷史的特性,可以極大提升工作效率。PyCharm會在每次項目出現(xiàn)變動時保存一份,因此可以不推送到代碼庫,就能將PyCharm當做一個本地版的版本管理系統(tǒng)。用戶不需要做任何操作,IDE將自動保存。在我了解該特性之前,我經(jīng)常會在解決問題后,想要換一種方案,但是不久后又希望回滾到原方案。如果我不把原方案推送到Github,很可能早就遺失了,不得不重新編寫。但是有了這個特性,我們就能回滾到10分鐘前,然后重新載入當時的項目狀態(tài)。如果又改變主意,也可以隨意地在不同方案之前來回切換。
3.在日常工作過程中,很可能要經(jīng)常復(fù)制粘貼代碼。在PyCharm中,不需要復(fù)制粘貼,在當前界面上直接移動代碼即可。
4.PyCharm支持Git和SVN等版本控制系統(tǒng)。無須使用命令行,即可直接在PyCharm中使用Git。在IDE和命令行之間切換次數(shù)越少,工作效率越高。
5.PyCharm提供了內(nèi)置的命令行和Python Shell。
6.PyCharm內(nèi)置了調(diào)試器(debugger)。調(diào)試器是支持中斷代碼執(zhí)行,逐行查看代碼效果的程序。通過調(diào)試器,我們可以查看不同代碼中變量的值。
記錄日志
記錄日志(logging)指的是在軟件運行時記錄數(shù)據(jù)的做法。我們可通過日志來協(xié)助程序調(diào)試,更好地了解程序運行時的狀態(tài)。Python自帶了一個logging日志模塊,支持在控制臺或文件中記錄日志。
程序出錯時,我們不希望沒有感知——我們應(yīng)該記錄下相關(guān)信息,方便以后核查。記錄日志也有助于收集和分析信息。例如,可以搭建一個Web服務(wù)器來記錄數(shù)據(jù),包括每次收到請求的日期和時間。我們可以將所有的日志記錄在數(shù)據(jù)庫中,編寫程序分析其中的數(shù)據(jù),并生成圖表展示訪問網(wǎng)站的人次。
博客作者亨瑞克·沃納(Henrik Warne)在博客中寫過這樣一段話:“偉大程序員與平庸程序員的區(qū)別之一,就是偉大的程序員會做日志記錄,使得出錯時的調(diào)試變得更簡單?!?/p>
測試
程序測試指的是檢查程序是否“達到了設(shè)計和開發(fā)要求,對各類輸入返回正確的結(jié)果,功能執(zhí)行耗時在可接受范圍,可用性足夠高,可在目標環(huán)境下安裝和運行,并且實現(xiàn)了相關(guān)利益方所期待的效果。”為了進行程序測試,程序員要額外編寫程序。
在生產(chǎn)環(huán)境中,測試是必須完成的。對于計劃部署在生產(chǎn)環(huán)境的程序,我們應(yīng)當認為在沒有編寫測試之前都是不完整的。但是,如果是一個不會再使用的臨時程序,測試可能有些浪費時間。如果編寫的是其他人也將使用的程序,則應(yīng)該編寫測試。很多知名程序員都曾說過:“未經(jīng)測試的代碼就是漏洞百出的代碼?!?/p>
代碼審查
在代碼審查(code review)時,同事會閱讀你的代碼并提供反饋。建議盡可能多地進行代碼審查,尤其對于自學(xué)成才的程序員來說。即使你遵守了本章中所列的所有最佳實踐,也有可能存在錯誤的做法。你需要有經(jīng)驗的程序員對你的代碼進行檢查,指出所犯的錯誤,這樣才有可能解決。
Code Review是一個專注于代碼審查的程序員社區(qū)。任何人都可以登入該網(wǎng)站,提交代碼。社區(qū)的其他成員會審查代碼,并反饋做得好的地方以及可以改進的地方。
安全
對于自學(xué)的程序員來說,安全是一個很容易忽視的問題。在面試時也很少會被問到安全問題,在學(xué)習(xí)編程時我們也不會去考慮安全問題。但是,在實際工作中,我們需要對自己代碼的安全性負直接責任。本節(jié)將給出幾個提高代碼安全性的建議。
我們在本書中已經(jīng)學(xué)習(xí)了使用sudo命令以根用戶的身份執(zhí)行命令。非必要情況下,務(wù)必不要在命令行使用sudo執(zhí)行命令,因為如果有黑客侵入程序的話,將會獲得根訪問權(quán)限。如果你是服務(wù)器管理員,還應(yīng)該禁止根用戶登錄。每個黑客都會盯著根賬號,在攻擊系統(tǒng)時是首要選擇的目標。
另外,總是假設(shè)用戶的輸入是惡意的。部分惡意攻擊的發(fā)生,就是利用了可接受用戶輸入的程序漏洞,因此我們要假設(shè)所有的用戶輸入都是惡意的,并以此為依據(jù)進行編碼。
另一個提高代碼安全性的策略,是最小化你的攻擊面積(attack surface),即黑客可從程序中提取數(shù)據(jù)或攻擊系統(tǒng)的相關(guān)區(qū)域。通過最小化攻擊面積,可以減少程序出現(xiàn)漏洞的可能性。最小化攻擊面積的幾種常見做法包括:避免保存敏感信息,賦予用戶最低的訪問權(quán)限,盡可能少用第三方庫(代碼量越小、漏洞越少),剔除不再使用的功能代碼(代碼量越小、漏洞越少)等。
避免以根用戶身份登錄系統(tǒng),不要信任用戶輸入,以及最小化攻擊面積,是確保程序安全性的幾個重要手段。但這還只是提升安全性的一小部分。我們應(yīng)該試著從黑客的角度進行思考。他們會如何利用你的代碼?這樣可以幫助我們找到之前可能忽略的漏洞。有關(guān)安全的話題非常大,不是本書所能涵蓋的,因此建議大家時刻思考并學(xué)習(xí)如何提升安全性。布魯斯·舒奈爾(Bruce Schneier)對此的總結(jié)十分精辟:“安全是一種思維狀態(tài)?!?/p>
術(shù)語表
生產(chǎn)代碼:某個產(chǎn)品中被用戶使用的代碼。
生產(chǎn):將軟件投入生產(chǎn),指的是對外正式發(fā)布。
DRY:一個編程原則,“不要重復(fù)自己”的英文簡稱。
正交性:該術(shù)語已經(jīng)被用來表示某種獨立性或解耦化。如果兩個或多個事物之間的變化不會相互影響,那么它們之間就存在正交性。在設(shè)計優(yōu)良的系統(tǒng)中,數(shù)據(jù)庫代碼與用戶界面之間是正交的;調(diào)整用戶界面不會影響數(shù)據(jù)庫,替換數(shù)據(jù)庫也不會改變用戶界面。
調(diào)試器:調(diào)試器是支持中斷代碼執(zhí)行,可逐行查看代碼效果的程序。通過調(diào)試器,我們可以查看不同代碼中變量的值。
日志記錄:指的是在軟件運行時記錄數(shù)據(jù)的做法。
測試:檢查程序是否“達到了設(shè)計和開發(fā)要求,對各類輸入返回正確的結(jié)果,功能執(zhí)行耗時在可接受范圍,可用性足夠高,可在目標環(huán)境下安裝和運行,且實現(xiàn)了相關(guān)利益方所期待的效果?!?/p>
代碼審查:他人閱讀你的代碼并給予反饋的過程。
攻擊面積:黑客可從程序中提取數(shù)據(jù)或攻擊系統(tǒng)的相關(guān)區(qū)域。