10年程式設計路上的幸酸苦累,寫代碼容易,程式設計並不容易
當我的程式設計生涯開始的時候,我認為“程式設計很簡單……怎麼會需要去學校學習呢?”但經過學習和實踐,我瞭解到程式設計很難。
自我評價對我自己來說一直都很重要,因為在一天結束的時候,不管別人怎麼想,自己的想法都很重要。我會在評價中思考強項、弱項、學習、訓練和個人成長。這個過程讓我反思、理解並思考成為一個程式師究竟意味著什麼。在分享的同時我自己也推薦一個學C/C++的學習群496926338無論你是大牛還是小白,
教育:編碼?程式設計?關鍵性的抨擊?
我在技術領域的第一份工作主要是通過 HTML、CSS 和 JavaScript 操作一些元素並創建視覺效果。在這段時間裡,我沒有真正想到自己是一個程式師,對於這個問題,我從來沒有想要成為一個真正的程式師。不久以後我想使用 NodeJS、PHP 和 MySQL 做更多事情,這時候我開始考慮這個問題。
“經驗告訴我,我會頗具氣勢地拍、打和敲擊鍵盤,但那並不是程式設計。”
程式設計需要思考和理解各種資料類型、結構,並理解程式設計語言賴以構建服務的技術。差異主要在於完成特定任務時所使用的流程。重點不在於資料類型、設計模式、演算法類型、性能或任何與代碼和應用程式品質相關的內容。
思考資料
資料結構是我感受到教育不足的一個方面。
從電腦科學的角度看,集合、堆疊和佇列對我來說是很有趣的,但在 Ruby 程式設計語言中看到一些實際操作之後,
比如,Ruby 中的棧可以像下面的代碼一樣簡單。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Stack
# init stack
def initialize
= Array.new()
end
# put a new item at the end of the stack
def push(x)
.push x
end
# get the last item in the stack
def grab
.pop
end
# is the set empty true false bool
def empty?
.empty?
end
end
# implemented stack
s = Stack.new
putss.grab# "c"
putss.grab# "b"
putss.grab# "a"
s.grab.inspect# nil
佇列和上面創建的資料類型基本上是一樣的,Ruby 已經有一個類了。
1
2
3
4
5
6
7
8
9
10
# ruby Queue Class
q=Queue.new
q<<'a'
q<<'b'
# Tests Examples using Queue
putsq.length# prints 2
putsq.pop# prints a
putsq.length# prints 1
putsq.pop# prints b
putsq.length#prints 0
它的簡單性是基於一個非常簡單的陣列,這本身就體現了它的美。我看到自己在命令列腳本中使用棧或佇列,但我不確定還可以在別的什麼地方使用它們。
二叉搜尋樹在處理搜索資料的時間和速度上吸引了我。我經常發現從資料中獲取資料非常容易,但在陣列中搜索需要花大量時間。這就是為什麼需要二叉搜尋樹,我非常喜歡哈佛的這段視頻。雖然我並沒有使用這些東西來做過什麼,但是非常想用它們來實現點東西,然後將之與原生 Ruby 的陣列方法進行比較,看看二叉樹比普通的陣列或雜湊快多少。我在關於二叉權勢的研究中試圖找到實際的用例,於是發現了這些有意思的文章。
可維護性
我的第一個 Web 應用在可維護性方面可笑極了。沒有編碼規範,沒有設計模式,沒有對定義的方法進行整理,沒有使用命名空間,也沒有物件和模型。如果一定要我去修復缺陷(肯定會有),與其去找實際導致缺陷的方法,還不如重寫來得快些。
設計拙劣導致亂糟糟的代碼。
我難以處理的問題之一是條件嵌套和迴圈嵌套。這些迴圈中存在大量的 if 語句和驗證,但這個問題本身來源於一個系統性的問題,即不清楚怎樣恰當地組織和拆分程式的不同部分。我曾嘗試著在一個巨大的方法中處理所有事情,不關心哪些代碼可以重用,也沒創建一個模組來擴展物件和方法的功能。為了節省篇幅,下面的代碼截取自真實的代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print"
Display Weekdays:
";// Looping in a view ... should have been factored diff
foreach($imageRecords["display"]as$=>$displayRecords){
// WTF is this a nested foreach
foreach($displayRecords as$value=>$dispRecord){
$tempWeekdayValuesArray=array();
if($value==="weekdays"&&!isnull($dispRecord)){
// 3rd nested foreach WTF!
foreach($dispRecord as$weekday=>$weekbool){
// :( condition foreach day ::SHAME::
if($weekday=="monday"&&$weekbool==1){
// logic removed
}
}
}
}
}
我不會把責任推到別人身上,這段壞代碼是我寫的,我會承認這一點,然而其中一些本來可以通過代碼導師、或者通過代碼審查和“拉”請求來加以緩解。回顧這段代碼,我感到慚愧,但這是一件好事,因為它表明了我作為一個開發人員的成長程度。自由在某些意義上是一個問題,但不是在其他方面。例如,對這個項目我被限制於使用 LAMP 技術棧,這是不容協商的,但與此同時,這真的是唯一的限制。我沒有使用設計模式,遵循任何風格指南, 使用代碼分析器,或遵循代碼公約的任何政策。這就創建了一個系統,你可以自由地使用自己的設備,並且如果你還沒有瞭解應用程式的長期性和錯誤修復,那麼它會損害你的最終結果。
我已經真正體會到了文字編輯器的好處,在你編寫代碼時它會給出提示(指出潛在的錯誤)從而為你節省很多時間,同時我也開始欣賞與程式設計相關的一些美好細節。一個寫得很好的代碼庫,會遵循文檔標準、清晰的約定和風格指南,閱讀起來就像一封電子郵件或一篇網文那樣流暢。(當然,有時候使用的程式設計語言本身就更好)總地來說,我也發現我很喜歡這本書中的許多原則, Robert C。 Martin 和其他作者的《敏捷軟體匠人的整潔代碼手冊》 。
測試驅動開發
在我看來,測試驅動開發的好處足以證明其優點,但我明白,並不是每個人都同意測試為代碼庫提供任何價值。我不會爭論測試的有效性,但我確實想分享它如何幫到我。在實際創建代碼之前,為代碼編寫集成測試和單元測試已經在很多方面幫到我。它幫助我編寫更整潔的代碼,高效地編寫代碼,並幫助我解決了我遇到麻煩的問題。
編寫更整潔、更高效的代碼與程式設計中的許多事情有交叉。可讀性、性能和編碼時間是 TDD 幫到我的主要方面。我發現我能編寫代碼,不必重構(多次)使其可以上生產線或進入版本控制庫。它不僅幫助我減少了 bug,而且幫助我減少了跟蹤和修復 bug 所花費的時間。修復 bug 時,我發現我可以接受預期的輸入或輸出,編寫一個與之匹配的測試,然後努力使該測試和所有其他測試通過。這樣可以消除 bug,並確保代碼實現其預期的目的。
在分享的同時我自己也推薦一個學C/C++的學習群496926338無論你是大牛還是小白,是想轉行還是想入行都可以來瞭解一起進步一起學習!群內有很多乾貨和技術分享!
在開始編寫實際的方法或物件之前,TDD 可以説明我組織思路。在更複雜的功能中,它可以幫助我將功能分解成其需要正常工作的集。也就是說,邊界條件就是邊界條件,並且在最初創建代碼時往往更難於考慮到邊界情況。最終我覺得測試驅動開發有助於使我成為更好的程式師。
比如,Ruby 中的棧可以像下面的代碼一樣簡單。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Stack
# init stack
def initialize
= Array.new()
end
# put a new item at the end of the stack
def push(x)
.push x
end
# get the last item in the stack
def grab
.pop
end
# is the set empty true false bool
def empty?
.empty?
end
end
# implemented stack
s = Stack.new
putss.grab# "c"
putss.grab# "b"
putss.grab# "a"
s.grab.inspect# nil
佇列和上面創建的資料類型基本上是一樣的,Ruby 已經有一個類了。
1
2
3
4
5
6
7
8
9
10
# ruby Queue Class
q=Queue.new
q<<'a'
q<<'b'
# Tests Examples using Queue
putsq.length# prints 2
putsq.pop# prints a
putsq.length# prints 1
putsq.pop# prints b
putsq.length#prints 0
它的簡單性是基於一個非常簡單的陣列,這本身就體現了它的美。我看到自己在命令列腳本中使用棧或佇列,但我不確定還可以在別的什麼地方使用它們。
二叉搜尋樹在處理搜索資料的時間和速度上吸引了我。我經常發現從資料中獲取資料非常容易,但在陣列中搜索需要花大量時間。這就是為什麼需要二叉搜尋樹,我非常喜歡哈佛的這段視頻。雖然我並沒有使用這些東西來做過什麼,但是非常想用它們來實現點東西,然後將之與原生 Ruby 的陣列方法進行比較,看看二叉樹比普通的陣列或雜湊快多少。我在關於二叉權勢的研究中試圖找到實際的用例,於是發現了這些有意思的文章。
可維護性
我的第一個 Web 應用在可維護性方面可笑極了。沒有編碼規範,沒有設計模式,沒有對定義的方法進行整理,沒有使用命名空間,也沒有物件和模型。如果一定要我去修復缺陷(肯定會有),與其去找實際導致缺陷的方法,還不如重寫來得快些。
設計拙劣導致亂糟糟的代碼。
我難以處理的問題之一是條件嵌套和迴圈嵌套。這些迴圈中存在大量的 if 語句和驗證,但這個問題本身來源於一個系統性的問題,即不清楚怎樣恰當地組織和拆分程式的不同部分。我曾嘗試著在一個巨大的方法中處理所有事情,不關心哪些代碼可以重用,也沒創建一個模組來擴展物件和方法的功能。為了節省篇幅,下面的代碼截取自真實的代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
print"
Display Weekdays:
";// Looping in a view ... should have been factored diff
foreach($imageRecords["display"]as$=>$displayRecords){
// WTF is this a nested foreach
foreach($displayRecords as$value=>$dispRecord){
$tempWeekdayValuesArray=array();
if($value==="weekdays"&&!isnull($dispRecord)){
// 3rd nested foreach WTF!
foreach($dispRecord as$weekday=>$weekbool){
// :( condition foreach day ::SHAME::
if($weekday=="monday"&&$weekbool==1){
// logic removed
}
}
}
}
}
我不會把責任推到別人身上,這段壞代碼是我寫的,我會承認這一點,然而其中一些本來可以通過代碼導師、或者通過代碼審查和“拉”請求來加以緩解。回顧這段代碼,我感到慚愧,但這是一件好事,因為它表明了我作為一個開發人員的成長程度。自由在某些意義上是一個問題,但不是在其他方面。例如,對這個項目我被限制於使用 LAMP 技術棧,這是不容協商的,但與此同時,這真的是唯一的限制。我沒有使用設計模式,遵循任何風格指南, 使用代碼分析器,或遵循代碼公約的任何政策。這就創建了一個系統,你可以自由地使用自己的設備,並且如果你還沒有瞭解應用程式的長期性和錯誤修復,那麼它會損害你的最終結果。
我已經真正體會到了文字編輯器的好處,在你編寫代碼時它會給出提示(指出潛在的錯誤)從而為你節省很多時間,同時我也開始欣賞與程式設計相關的一些美好細節。一個寫得很好的代碼庫,會遵循文檔標準、清晰的約定和風格指南,閱讀起來就像一封電子郵件或一篇網文那樣流暢。(當然,有時候使用的程式設計語言本身就更好)總地來說,我也發現我很喜歡這本書中的許多原則, Robert C。 Martin 和其他作者的《敏捷軟體匠人的整潔代碼手冊》 。
測試驅動開發
在我看來,測試驅動開發的好處足以證明其優點,但我明白,並不是每個人都同意測試為代碼庫提供任何價值。我不會爭論測試的有效性,但我確實想分享它如何幫到我。在實際創建代碼之前,為代碼編寫集成測試和單元測試已經在很多方面幫到我。它幫助我編寫更整潔的代碼,高效地編寫代碼,並幫助我解決了我遇到麻煩的問題。
編寫更整潔、更高效的代碼與程式設計中的許多事情有交叉。可讀性、性能和編碼時間是 TDD 幫到我的主要方面。我發現我能編寫代碼,不必重構(多次)使其可以上生產線或進入版本控制庫。它不僅幫助我減少了 bug,而且幫助我減少了跟蹤和修復 bug 所花費的時間。修復 bug 時,我發現我可以接受預期的輸入或輸出,編寫一個與之匹配的測試,然後努力使該測試和所有其他測試通過。這樣可以消除 bug,並確保代碼實現其預期的目的。
在分享的同時我自己也推薦一個學C/C++的學習群496926338無論你是大牛還是小白,是想轉行還是想入行都可以來瞭解一起進步一起學習!群內有很多乾貨和技術分享!
在開始編寫實際的方法或物件之前,TDD 可以説明我組織思路。在更複雜的功能中,它可以幫助我將功能分解成其需要正常工作的集。也就是說,邊界條件就是邊界條件,並且在最初創建代碼時往往更難於考慮到邊界情況。最終我覺得測試驅動開發有助於使我成為更好的程式師。