程序員的成長從開竅開始系列 一、如何擺脫低級錯誤的困擾

最近,有兩位Google Maps API的初學者向我請教他們按照最簡單例子寫的程序為什么不能正常的運行。

其中一位用GTalk跟我交流,我仔細了看了他的代碼,沒看出問題,把代碼保存在本地,打開Firefox的錯誤控制臺,用Firefox打開他的頁面。出錯的那一行被清晰的顯示出來,我再仔細端詳那句話,原來有兩個應該是英文逗號的地方,寫上了中文逗號。

另一位,在我的論壇跟我交流他的Google Maps API中遇到的問題,我看他代碼的時候也沒有馬上發現問題。然而,同樣在用Firefox打開后,問題很明顯的找到了,原來是一個方法openInfoWindow被他寫成OpenInfoWindow了。

在我幫助別人解決的程序調試問題中,這是非常常見的。人人都可能打出中文逗號,人人都可能把大小寫寫錯。但是在我幫助他們解決問題以后,他們總是感慨的說,謝謝我解決了這個問題,這個問題困擾了他們幾個小時,甚至是幾天。

這其實并不是只有初學者才會遇到的問題,我還幫助過些有非常豐富經驗的工程師解決問題,有時候問題僅僅出自某個參數沒有傳遞進來,或者是拼接字符串的時候少些了一個冒號,或者是拼接地址的時候漏掉了http:。我甚至幫助一些人調試一些我根本不懂的語言的程序,因為多半出現的問題,都和語言特性無關,不是程序員寫錯了字符,就是寫錯了邏輯,或者是錯誤理解了一個函數。

出問題是正常的,寫程序是一個復雜的邊思考邊打字的過程,筆誤和一時糊涂都是難以避免的。程序員一般把這種問題叫做低級問題,因為這類問題跟你的智商完全無關,任何人都可能犯。

但是,問題在于,有時候即使是很優秀的程序員,也會被一個低級錯誤困擾,可能會幾天都解決不了。所以,關鍵在于,如何找到問題。

遇到問題的時候:

  1. 不要怨天怨地。出了問題,當然有可能是系統的bug,API的問題,但是那些幾率往往比你犯低級錯誤的幾率要低多了,先從自己身上找原因,是不是自己寫錯了。
  2. 要掌握工具。最低限度你要會寫Log,最好是Log和調試器結合。好 的工具可以大大的提高效率。以前有人跟我說,Dll不能調試,我發現可以;有人說多線程不能調試,我發現可以;有人說COM不能調試,我發現可以;有人說 IE插件不能調試,我發現可以;有人說OE插件不能調試,我發現也可以。當然,你確實會遇到不能調試的時候,當年我們做東芝芯片的嵌入程序,一個組都沒有 一個仿真器和調試器,但是至少可以用Log嘛,無非是麻煩點。
    ?
  3. 分析問題要有邏輯。遇到問題可以先把所有的可能性都列出來,然后一個一個分析,肯定能找到原因的。
  4. 要學會隔離問題。問題涉及到的代碼越多,越難以理解,問題越難以解決。遇到這樣的情況,可以利用Log或者調試器,一行代碼一行代碼的給它們洗清嫌疑,這樣很快你就可以找到出問題的地方。如果代碼特別長,程序特別復雜,可以用二分法來做,效率很高。
    ?
  5. 千萬不要懶惰,不要事事求別人。一次復雜的調試過程就像一部偵探劇,如果你有非常好的邏輯性,那這部劇的主角就是福爾摩斯,劇情一定非常精彩。我說這個是有巨大風險的,說真的我幫人調東西挺上癮的,很有意思。但是我還是要告訴大家,一次高難度的調試之后,你的滿足感絕對不亞于寫了一個偉大的程序。
    ?

要想不遇到問題,寫代碼的時候:

  1. 要對寫出來的代碼負責。我很佩服那些寫代碼寫100行都不執行一次的 高手,如果他們最后不被低級錯誤困擾的話我就更加的佩服了。我寫程序幾乎是寫一行兩行就要執行一次,每句話我都要確保執行效果跟我的預期一致。沒錯這樣寫的時候 可能慢一些,但是調試的時候很輕松,我可以很簡單的確定哪些代碼絕對沒有問題。所以我寫代碼整體速度比一般人高。很多人學習新東西的時候喜歡把例子抄一遍,運行一下,改改,再運行。我喜歡一句一句的抄例子,抄一句兩句執行一次,這樣可以把例子透徹的理解,而且很難會遇到出現了問題找不到原因的時候。
  2. 函數體功能塊不要過長。我認為我的智商并不高,我很難接受一個程序的一個函數體或者一個功能塊超越3屏(當然邏輯真的有那么復雜除外,你會發現越是簡單的邏輯越是容易被人寫的冗長)。很多人對面向對象耳熟能詳,對封裝繼承看起來駕輕就熟。但是動不動就寫出來個函數體超長的程序。這就像寫本書從頭到尾不點句號一樣,會累死讀者的。自己看的時候,估計也會被累的喘不過來氣。這是我對基礎教育的微詞所在,他們連教會學生寫函數都沒教會,雖然表面上他們連面向對象這么高深的東西都教。
  3. 縮進要對。這點很重要,雖然大部分語言不是像Python那樣用縮進來決定邏輯塊的位置,但是人看到縮進的時候,總是會以為這些縮進位置跟邏輯相關。尤其是在有大量的ifelse或者for循環等等的嵌套邏輯的時候,如果縮進錯了,可能會直接讓人把程序的邏輯讀錯。所以我拿到別人的代碼,第一件事情就是整理縮進。我見過一些比較優秀的頁面工程師,他們會在div結束的位置用注釋寫上這個div的id,這樣層級關系就一目了然了。
  4. 不斷重構。隨著程序的不斷修改,有些部分會不斷的增長,原來看著清晰的架構可能因為問題的復雜而慢慢模糊,也可能被修正bug的權宜之計弄的面目全非。不信你找一個經過多次修改的程序看看,是不是滿目瘡痍,是不是都很難認出是你自己的作品了。這在多人參與的項目中更加嚴重,每個人有不同的代碼風格,經過多次雜交后,你肯定認不出你的代碼是騾子是馬,還是四不像了。隨著程序的慢慢成長,原來有些函數體會慢慢膨脹,需要拆分;有些原來簡單的功能塊四處都需要,應該被提煉成函數或者方法,等等。現在不重構,未來等到代碼復雜到無法控制的時候,重構的工作就會變得更加困難。我見過最強的案例是,一個幾千行的電子辭典配套聯機軟件,經過無數次的改版,變成了一個幾乎無法維護的主窗體的cpp有1萬8千行的怪物。最后經過復雜的重構,才變成一個出新版本只需要新增一個驅動程序的可以維護的幾千行的程序。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452529.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452529.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452529.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

脈沖時間寬度c語言,什么是脈沖寬度_脈沖寬度是什么意思

脈沖寬度是個很廣泛的詞,在不同的領域,脈沖寬度有不同的含義。脈沖寬度從學術角度講就是電流或者電壓隨時間有規律變化的時間寬度,平時研究主要是方波,三角波,鋸齒波,正弦函數波等等,這些波形變…

HDU - 5919 Sequence II

題意: 給定長度為n的序列和q次詢問。每次詢問給出一個區間(L,R),求出區間內每個數第一次出現位置的中位數,強制在線。 題解: 用主席樹從右向左的插入點。對于當前點i,如果a[i]出現過…

Django博客--3.創作后臺開啟

文章目錄0.創建admin后臺管理員賬號1.在 admin 后臺注冊模型2.漢化應用的標題3.漢化應用下各個模塊的名稱4.漢化應用下各個模塊的屬性的名稱5.文章列表顯示更加詳細的信息6.簡化新增文章的表單7.自動設置文章作者為當前用戶8.設定創建時間為當前時間9.設定修改建時間為保存時的…

逐步求精

逐步求精定義為為了能集中精力解決主要問題而盡量推遲對問題細節的考慮。 逐步求精最初是由NiklausWirth提出的一種自頂向下的設計策略。按照這種設計策略,程序的體系結構是通過逐步精化處理過程的層次而設計出來的。通過逐步分解對功能的宏觀陳述而開發出層次結構…

raid-6磁盤陣列損壞導致數據丟失的恢復過程(圖文教程)

一、故障描述機房突然斷電導致整個存儲癱瘓,加電后存儲依然無法使用。經過用戶方工程師診斷后認為是斷電導致存儲陣列損壞。整個存儲是由12塊日立硬盤(3T SAS硬盤)組成的RAID-6磁盤陣列,被分成一個卷,分配給幾臺Vmware…

編寫登錄注冊

const readline require(readline-sync);let error 3;let user [{username: 001,password: 123}, {username: 002,password: 456}, {uesrname: 003,password: 789}]//登錄let denglu function () {while (true) {console.log(請輸入您的登錄賬號:);let username…

android將字符串轉化為json,將字符串轉換為JSON數組

將字符串轉換為JSON數組我從Web服務獲得以下字符串的JSON,并嘗試將其轉換為 JSONarray{"locations": [{"lat": "23.053","long": "72.629","location": "ABC","address": "D…

談新技術學習方法-如何學習一門新技術新編程語言

學習一門編程語言或者編程技術的方式基本上是這樣一個流程: 1,對學習這門語言或者技術的必要性進行評估。比如你是工作需要,或者興趣所至,甚至是為了把妹。這個必要性關系到你要學多深入,需要學習多長時間。 比如我想…

信息隱藏和局部化

信息隱藏原理:應該這樣設計和確定模塊,使得一個模塊內包含的信息(過程和數據)對于不需要這些信息的模塊來說,是不能訪問的。 局部化是指把一些關系密切的軟件元素物理地放得彼此靠近。 如果在測試期間和以后的軟件維護期間需要修改軟件&#…

圖像識別自動化android,Android自動化測試

寫在開頭:Android UI 自動化測試推薦網易的Airtest,也是谷歌推薦的,操作簡單,而且基于圖像識別根據用戶操作界面自動生成Python測試代碼JUnit單元測試testImplementation junit:junit:4.12image.pngimage.png使用gradle命令進行單…

如何重構“箭頭型”代碼

本文主要起因是,一次在微博上和朋友關于嵌套好幾層的if-else語句的代碼重構的討論(微博原文),在微博上大家有各式各樣的問題和想法。按道理來說這些都是編程的基本功,似乎不太值得寫一篇文章,不過我覺得很多…

Django博客--4.開發博客文章詳情頁

文章目錄0.思路引導1.設計文章詳情頁的 URL2.獲取文章的URL3.編寫 detail 視圖函數4.編寫詳情頁模板5.更改主頁中跳轉詳情頁的地址鏈接6.模板繼承--抽取base.html7.模板繼承--修改 index.html使其繼承base.html8.模板繼承--修改detail.html使其繼承base.html9.結果展示0.思路引…

10、并發容器,ConcurrentHashMap

Java 提供了不同層面的線程安全支持。在傳統集合框架內部,除了 Hashtable 等同步容器,還提供了所謂的同步包裝器(Synchronized Wrapper),我們可以調用 Collections 工具類提供的包裝方法,來獲取一個同步的包…

程序員的本質

Computers are useless. They can only give you answers. – Picasso計算機沒有什么作用。他們只能告訴你答案。——畢加索很多人(包括我岳母)認為計算機變得如此智能,所以在不久的未來將不再需要程序員。另外一些人認為程序員是天才&#x…

模式-視圖-控制器模式2.0

1 MVC的實現   1.1 分析應用問題,對系統進行分離   分析應用問題,分離出系統的內核功能、對功能的控制輸入、系統的輸出行為三大部分。設計模型部件使其封裝內核數據和計算功能,提供訪問顯示數據的操作,提供控制內部行為的操作…

總體設計的原理

1 模塊化 2 抽象 3 逐步求精 4 信息隱藏和局部化 5 模塊獨立

android 手動回收對象,Android Studio Studio回收列表中的JSON對象

我想在recyclerview中顯示一些JSON對象,并且希望它們在日期之后排序,我該如何實現?下面是下載從JSON URL的數據的方法:Android Studio Studio回收列表中的JSON對象public void downloadFromSkistar(){try{URL url new URL("…

剖析管理所有大數據組件的可視化利器:Hue

歡迎關注大數據和人工智能技術文章發布的微信公眾號:清研學堂,在這里你可以學到夜白(作者筆名)精心整理的筆記,讓我們每天進步一點點,讓優秀成為一種習慣! 日常的大數據使用都是在服務器命令行中…

Django博客--5.讓博客支持 Markdown 語法和代碼高亮

文章目錄0.前言1.安裝 Python Markdown2.在 detail 視圖中解析 Markdown3.safe 標簽4.代碼高亮5.效果展示0.前言 Markdown 是一種 HTML 文本標記語言,只要遵循它約定的語法格式,Markdown 的解析工具就能夠把 Markdown 文檔轉換為標準的 HTML 文檔&#…

耦合

模塊的獨立性很重要,因為有效的模塊化(即具有獨立的模塊)的軟件比較容易開發出來。 獨立的模塊比較容易測試和維護。 模塊的獨立程度可以由兩個定性標準度量,這兩個標準分別稱為內聚和耦合。 耦合 耦合是對一個軟件結構內不同模塊之間互連程度的度量。…