分享成为高效程序员的7个重要习惯
作者:Phil Chu
作為軟件工程師,你希望從工作中獲得的是:穩定的薪水、參與好項目的機會、好工作的跳板或只是和其他程序師成為好基友。這里的“高效”,我指的是按時完符合要求的項目的能力。經歷過不少軟件編寫工作后,我相信以下實踐會幫助你學會“高效”,同時提高專業聲望、拉長職業壽命,和獲得個人滿足。
Programmer(from good-wallpapers)
1.理解你的需求
成為高效程序員的第一步是,保證時間的合理分配。沒有什么比將時間花在完全沒有前途的工作上更浪費的了。
盡快開工
盡快完成一個直觀的系統。這意味著先創建界面,無論是程序界面還是用戶界面,然后生成內部功能的存根代碼(如果有必要的話)。這么做便于“客戶”查看,通過執行用戶界面或編寫程序界面的代碼,可以發現最初代碼存在的矛盾或遺漏。甚至在第一次交付以前,你有可能會注意到問題或可改進的地方。
有一個經典觀念認為,如果你提前設計好所有東西,那么之后你要做的就只剩寫代碼了。如果你之前做過完全相同的項目,那么這個說法當然正確。但如果不是,你很可能會陷入死角,也就是你只是在猜想或執行一個可疑的假設。
很早以前在一家無限網絡的新公司工作時,我們開了兩個月的會來設計一個將在6個月內發布的無線門戶和網關。最終,我們厭煩了開會,開始編寫代碼。頭兩周內,我負責的部分與原始設計不符,兩個月后的第一個無線連接測試表明,我完全誤解了無線協議。
這不是說設計是沒必要的。但在一定程度上,設計只是一種猜想。設計應該通實執行來確認,并且早執行總是比晚執行好。
即使原始設計是充分的,只要你發現可以調整的地方,你就要改進它。硬件產品、建筑和大型軟件項目等會受到僵死的“預制”的損害,但對于軟件,你可以在項目早期提煉項目要求,然后制作適合的界面。但是,這必須盡早完成。
盡早開工有利于樹立你的職業形象。如果能向你的老板展示一些成果,他會很高興的。另一方面,提早開工有助于緩解焦慮。
經常交付
一旦你完成一些可用的東西了,不要只是把它留作“概念實證”。要讓其他人試執行它、看看他們的反應,然后讓它指導開發過程的優先次序。觀察人們如何使用你的軟件,這是無可代替的方法。客戶問卷調查和焦點研究可能會提供一些有用的意見,但有可能會讓開發者的設計決定和特點被客戶牽著鼻子走,這是一種冒險。
特別是要盡快將軟件交付QA人員,經常提交成果,最好是按預定的時間間隔。讓他們測試每天的成果,或至少是每周的成果也是好的。這會讓QA人員覺得自己全程參與項目開發,從而培養職業責任感,更樂意發現和報告問題。最需要優先解決的是導致產品失效的問題,如崩潰或死循環——讓問題盡可能涵蓋多方面,熟悉整個產品,這樣才有可能提早發現設計問題。
在一個小型3D軟件公司,我負責移植從SGI出品的龍頭產品到Windows NT。6個月后,移植沒完成,倒有了崩潰的傾向,我很不情愿地將第一輪成果交付測試團隊。幸運的是,因為漏洞太多,QA經理堅持要我立刻解決導致測試
人員無法有意義地使用程序的問題。如果是我自己測試,我應該會忙于看起來更困難更重要的核心3D問題,可能會怠慢看來起比較普通的問題,如用戶界面、載入-保存功能和與計劃支持的硬件之間的兼容性。
程序師常常不想過早將代碼交付測試人員——他們不想聽到自己已經知道的漏洞;而測試人員極有可能不想測試基本上行不通的東西。但測試人員的工作就是找到這些問題。如果程序師想盡快看到成果的話,應該把漏洞報告當成好東西。
2.把工作當真
將軟件放在盡可能接近完工的狀態下運行。你永遠不知道你什么時候得演示系統、發送評估備份或甚至交付。
使用真實數據
如果你只用作為著冰山一角的樣本數據作測試,那么,你的程序可能一撞上真實數據的大冰山就沉了。
我曾參與開發一種用于評估先進的半導體絕對值的供應鏈管理產品。跨過交付這道大坎后,我們接到消息說他們輸入的第一批真實數據仍然在處理中——已經兩天了。我同情主程序師,他不得不在管理人員和客戶的催促之下忙活了兩周。很高興遇上這事的人不是我。
使用正式版本
記住,用你自己的機器創建的東西不是正式的。
在最近的一個游戲開發項目中,我負責用戶界面,我陸續從QA那接到報告說有些顏色不對。最后,我發現問題只出現在交付版本中,另一位程序師使用專門的主機調試工具找到了漏洞。結果竟是一個我在兩個月前犯下的愚蠢錯誤,沒有指定初始顏色值。調試版本總是選擇特定的默認值,但是交付版本會更改,最終結果是不太確定的。如果我注意經常地運行交付版本,我會立刻發現問題的,而不是損失大量的時間。
經常合并
及時將你的代碼并入主代碼庫中——你拖得越久,這項工作就越累。
我曾與一名程序師共事,他覺得每天數據庫中出現的所有新代碼和數據變化都“很麻煩”。確實,這讓所有其他程序師每天都要花一定時間合并,他才能夠只掃視一下代碼和數據就開始運行一些不錯的獨立樣本。但每一次階段性交付時,我們都要花好幾天再次把單獨的代碼接到當前的代碼庫中,有時候甚至得拖延交付或冒著損失整個項目的風險。
將你的代碼與正式版本分開意味著程序師不能評估你的代碼,以及測試員不能盡早發現漏洞。可能你并不想其他人挑剔你的代碼,但早發現問題總是比晚發現好的——所以,忍了罷。
code(from etsy.com)
3.理解你的代碼
生活中充滿了奇妙的神秘,但你的代碼可不適合出現這些神秘。你不必知道你的車怎么工作的——如果引擎發出奇怪的聲音,把它交給汽車技師就好了。但換成是你的代碼,如果連你都不知道它是怎么運行的或出了什么錯,那就沒人知道了。
有自己的編寫風格
我童年時的鋼琴教師是這么評價我和我姐姐哥哥的:“你姐姐的時間感強,你哥哥的鍵盤打得不錯。”然后他停頓了一下說:“你嘛,嗯,你很努力。”
編程是一種有些人能做有些人不能做的事,但還有一些人則是天才。雖然我有過多年的練習,鋼琴還是彈不好;雖然我那么喜歡打球,水平仍然一般般。但我確實認為我有編程和寫作的天賦。不要吃驚,我認為好程序就像好散文。散文和代碼都是文本,有語法、句法、拼寫和語義。對于大多數寫代碼的人和寫作的人,有這些就夠了,但好作家和好程序師還要有一種美感,他們的作品在結構和風格上是有特點的,往往能借此識別出作者。
許多Windows程序師都感到好奇:為什么壞脾氣的老Unix/Mac/Amiga/Lisp程序師對Win32/MFC/.NET很不滿,但如果所有應用界面都來自Microsoft,你可能就不知道還有什么東西是更好的。
復制粘貼
風格化編程的反面是復制粘貼。從什么地方復制一些可能有用的代碼,稍作調整,合并,重復,然后就大功告成了。你的軟件簡直就是大雜燴。
離開一家公司的幾個月后,一位前同事電郵問我,他復制粘貼了十頁的代碼組成一個算法,為什么運行不了。我實在不知道怎么回答了。如果你不能解釋你自己的代碼應該是怎么運行的,你還指望誰來拯救你?
我甚至在診斷自己從樣本代碼復制粘貼過來的代碼時也犯過難。從復制粘貼開始新代碼是合情理的,但你不能因為看起來能運行就放手不管了——你得返回去看看你是否讀懂了每一條,根據自己的目的理清代碼。
清理代碼
保持你的房子/公寓/房間整潔的最好辦法就是每天花一點時間清理它,或至少每周清理一次吧。如果等到住所亂到一定程度才打掃,那么這麻煩就非常大了。除非你雇個清潔工。
假設你沒辦法奢侈到雇一個人每天幫你清理代碼的程度,那么你就應該定時地檢查你的代碼、清理累積的死代碼、淘汰過時的注釋和錯誤的名稱,否則你必定會得到一份不敢拿出來見人的代碼。如果你不覺得丟不起人,好吧,你行。
我指導過的一名程序員總是向我報告,她的代碼“完成”了。這是管理者樂意聽到的話,卻讓我非常抓狂。她的代碼從來沒有做完——你得調試它、維護它、改進它,直到它徹底沒問題。
問題?注釋?
有些人認為編程是一門手藝活,也有些人認為編程是一項工程。更經常的是,它是一門考古學。你挖掘代碼的沉積物,想知道這些奇怪的人工產品是用來干什么的。為后來人著想一下,留點線索吧。
我問之前提到的那位程序員“完成”注釋了沒有。結果是,一個函數名稱為“GetData”的注釋居然是“Gets data”。這不只是廢話——簡直是侮辱。什么數據?什么格式?來自哪里?更不要提像服務器不可用或傳送中斷時會怎么樣這種小細節了。
將你的代碼做成文檔,以防有人隨時要拿來用。可能要用的人就是你本人——想想如果不這么做,你得重新訪問代碼多少次啊?
與之前的一個老板合作時,他叫我瀏覽一段沒人有時間看的代碼。一開始,我認為它很糟,不知道寫的都是什么東西。之后我慢慢摸索出來這段代碼是干什么的,所以我勉強同意它不算太糟。最后我終于認出這貨竟是我兩年以前寫的。教訓:多留點注釋。
當你寫代碼時,記得注釋,而不是等著出現什么方便的清理短語——注釋你的代碼,讓它甚至可以清楚地反映你在編寫時的想法。你可以成為自己的編寫伙伴。
現在你可以用javadoc和doxygen等生成漂亮的HTML或來自源代碼注釋的其他格式化的文件。理想的情況是,你每天晚上做的就是doc生成的部分,可以通過你的內聯網獲得。
注意警告
無視編輯器和運行時間警告會害到你自己。有“警告”就有原因。
我曾做過一個基于Unix的應用,它不能成功地連接某些函數。我們通過在運行時再次連接這些函數解決問題。六個月后,當我們執行一個干凈的新版本時,我們才發現原來我們關掉了能提醒我們未知連接漏洞的警告。在供應商的斥責下,我們將連接問題解決了。但結果是,原來我們只要通過重新排列庫就能連接上了。
提高編輯器的警告水平,注釋代碼以及記錄創建和運行時間的警告信息,最好包括解決警告的標準,這樣你就會知道是否解決問題或忽略問題。
Programmer(from photobucket)
4.優化編程
帶著目的寫代碼
復制粘貼代碼的人的另一個極端是,只是為了讓代碼看起來更漂亮(至少對他們而言)而改變代碼。雖然有編程審美感是值得贊揚的,但改變代碼以便讓你覺得漂亮只是浪費時間(無用的冒險)。瀏覽并改變別人寫的代碼,讓它看起來更漂亮,真是讓人生氣。
我有一個挑剔的同事,瀏覽我們的代碼庫時將所有的附加語都刪除了。如果他只是清理了入門級員工寫的代碼,那可能沒人會說什么,但那些附加語是我們團隊的技術領導寫的,他可是我們公司最出色的人物之一。
不要搞破壞
“代碼重構”現在十分流行,但程序員往往以為它是指代碼清理或重新設計。這個技巧是指重新組織代碼,同時不破壞其他東西。如果你以改進的名義破壞已經存在的功能,那么你的意思就是:要么你的時間比其他人的時間金貴,要么你不破壞就不會整代碼。
我有一個特別討人嫌的同事,他決定重新執行我們系統中的解析器,但結果讓代碼變成其他所有人都不知道怎么寫了。我讓他恢復原狀,之后發現代碼能編寫了,卻不能運行了—–問他怎么回事,他說“應你的要求”,他移除了整個解析器。真沒團隊精神。
保持代碼運行需要一些耐心和額外的工作——你勤奮地回歸測試你的工作,在將函數添加到新代碼中時,你可能需要暫時留住老代碼和界面。但對于所有與這個代碼庫有關的人來說,這是必須做的。
找到瓶頸
人們總是談論“最佳”,但這不是一個正確的詞。我們極少將最佳作為目標——相反的,我們的目標是改進和權衡以達到足夠好的表現。
在谷歌的電話面試時,我被問到如何在一組有序的數字中搜索某個數字。顯然,提問的人是在問二進制搜索法。但在現實生活中,我可能會做出“錯誤”的選擇——從頭找到尾。如果程序表現足夠好了,還花兩倍的時間寫兩倍的、必須維護和調試的代碼,那是毫無意義的,特別是如果那段代碼并非程序的瓶頸(我嚴重懷疑如果那個數據是瓶頸部分,你居然還會將它線性排列)。
如果你確實需要在程序的速度或空間方面達到最佳,折騰除了瓶頸以外的其他任何部分都只是浪費時間。
5.自我管理
你可能對你那位討厭的老板有各種抱怨,你的抱怨可能沒錯。所以你得成為你自己的管理者。即使你的老板人不錯,他也不會站在你背后告訴你該寫什么、怎么寫才會快(盡管我肯定許多老板恨不得這么做)。
估計時間
程序師不能提供有用的時間估計,這是出了名的。但我認為這是無理指責,因為管理層往往作出更差的預測,并且程序員的警告往往被無視(這可能是所有工程的共同災難)。但是,合理的時間估計對于按時完成項目仍然是關鍵的。
在一個商業軟件項目中,我的有些同事居然樂得忘了產品交付日期——有人問是否已經交付了,另一個人才很驚訝地發現,日子已經過去好幾天了。
更糟的也更普遍的是,程序員能給出的時間估計是“只需要幾天。”每次我聽到這話,或者我自己說出這話,我都感到害臊。
一家圖像軟件公司的總裁想讓產品支持VRML(那時它是下一件大任務),包括我們將在兩個月內發行的產品也支持VRML。他可能想到(他是正確的)我會拒絕開始新項目,所以他問了另一個工程師,得到了他想到的回答:“只需要幾天。”兩天后,我告訴總裁,我們剛剛浪費了他和我的兩天時間,因為有兩百多個更重要的漏洞要修復,他認為我的理由算是充分。(后話:VRML沒有太成功。)
另一位程序員完全沒有時間估計的概念。但沒有必要完全拒絕時間的模糊屬性——畢竟只是估計,事實上你應該避免太確切。如果你是一名有經驗的工程師,你就知道你以前做類似的工作需要多長時間,如果你不是,那你就問問有經驗的人。
我有一個聰明的朋友,經常被指派去開發實驗原型,他問我:“你怎么估計時間?”我認為這是一個反問句,但甚至純研究人員也要估計時間。有人支付他們,希望得到結果,即使它是許多演示樣本或某段時間發表的文章。
如果你確實估計不準需要多少時間,那么你就不是做這項任務的合適人選。
有時候程序師不情愿承諾時間是因為他們害怕保證。確實,這個世界沒那么美好,經理會在時間上跟你討價還價,競爭對手可能用嚴苛或不切實際的安排來擠兌你,希望你失敗。在你承諾時間后,你就悲劇了,你別想得到任何你希望的結果。
我曾有個老板問完成時間后會追問一句:“你保證?”但問他硬件條件和其他相關事宜時,他會說:“我盡量。”
我能說的只有,抓緊時間以及給出現實估計。任何讓步都應該根據實際的介于產品和資源之間的交易。要根據假設、相關事宜和資源做時間安排,找個地方寫下來,這樣以后你就不用麻煩你不太給力的記性了。
計劃進度
在決定上哪去以前,你不會跳上車的,對吧?你在開車時心里可能就有路線了。相同地,在你開始用電腦寫以前,你應該知道你今天想完成什么,有一些想法了。
每天都會遇到分心的事,所以你不可能總是完成你想完成的事。與那些將軟件工程團隊當作自動販賣機的人的想法相反的是,有些任務不是一天就能完成的。所以想想你到周五要完成什么,如果你完成了,那么周末你就可以好好過了。
6.不斷學習
一名社團足球隊成員曾經問我,我們每天束緊防滑釘練習,你們“C語言編程的秘密是什么?”如果存在這樣的秘密的話,我肯定會在晚間電視節目上宣傳如何靠房地產發財。對不起,沒有捷徑——你必須學習、練習和犯錯。你不一定得依靠團體訓練或學校教育——有許多國立的和當地的專業團體、書籍,當然還有網絡。
編程是科學
編程被稱作“計算機科學”是有原因的。無需正規的計算機科學教育,任何人都可以輕易地開始編程(可能太容易了)。特別是,那些學過其他工程和理科的人,可以非常快地上手編程,然后以此謀生。但對于高效地處理重大任務,你必須知道軟件的固有功能和限制、識別前提,這樣你才不會白費力氣地做重復的工作。你不必知道所有事,但你應該至少粗略地了解許多領域,必要時能做一些額外的研究。
例如,創建了新文件格式的人應該知道一些關于編輯器的事。我不是指所有代碼生成的優化如循環展開,而是基本的問題和各種編輯的短語和大部分指定標記和語法的重要性。今天,大多數人會默認地使用XML,那是件好事,
但在那之前,一般是粗略地寫一些文本格式,指向一些生成的樣本文檔作為文件,之后其他寫了另一個解析器的人會補上一些在文檔中閱讀的東西,但不是全部。在出了差錯的情況下,你有兩種方式推卸責任——要么讀者不行,要么作者太差。無論怎么樣,更受歡迎的產品會贏。
我對3D圖象行業最不能容忍的事情之一是,過多的文件格式不明。當我執行一個3D作品的OBJ文件解析器時,我測試的每份導出作品都生成明顯不同的文件,比如空白和換行不同。與之形成對比的是,我的一個初出茅廬的同事用語法和詞法分析器設計了一個新游戲交換格式(現在,這不再是什么大不了的事了—-大多數新圖象文件格式好像都是基于XML的)。
只會將簡單的腳本和用戶界面放在一起的程序員和可以處理實際問題的程序員,如果說這二者有什么區別的話,那就是對復雜計算的理解能力,如算法怎么影響問題的大小。每一位程序員都應該知道基本的復雜性術語和對常見問題的復雜程度有常識性認識。
我的第一份工作是計算機輔助半導體設計,涉及許多可擴展性的問題,包括一些NP-complete問題(非常難處理)。但是,每次看到在線性時間中不能解決的問題,和我們自夸可能意味著大部分是線性時間的“線性”算法,有些工程師會興奮地說:“這是旅行商問題!”(游戲邦注:旅行商問題,即TSP是一個有著重要工程背景、在圖論中的典型組合優化問題,已被證實是一個NP完全問題。也就是,如果一個旅行商不得不到幾個城市做生意,怎樣走最短的路線使他一次到達這幾個城市。)
免費啤酒、自由討論、免費軟件
好吧,其實沒有免費啤酒;但現在程序員過得還不錯(盡管經濟衰退和外包業惹爭議)——畢竟你需要的東西網上教程、討論組上都有,還有免費軟件可以用。你要解決的只有硬件和寬帶問題。
the-social-programmer(from geekherocomic.com)
7.尊重
高效軟件工程師的要求之一是,被認真對待。你必須得到你的同事和老板的尊重,至少出于你的技術能力、對自己的工作有主導權、對他人有一定影響力。
愚蠢問題
真的,這個世界上存在許多愚蠢的問題。提出一個聰明的問題會增加別人對你的尊重,但這是一項技術活。一個揭露未解決的事的好問題會讓別人看到你深刻的內涵,你敏銳的思維。要求說明關于技術參數的問題,顯示了你閱讀和發現問題的能力。
如果你的問題沒有得到答案,可能是問題本身有誤,所以不要再重復發問了。換一種方式提問,帶上更多細節或背景。如果被提問的是你或花時間回復新手問題的是你,你會感謝上述考慮的。
能與技術支持人員保持良好關系,這是讓我對自己都感到驕傲的事。但我確實記得一件往事,那時我拋出一個問題:“幾周前提出來的那個問題是怎么回事?”你可以想象別人是多么惱火地回答——“你說的怎么回事是指什么,并且,你說的是什么問題?”
粗魯無禮是沒有回報的,特別是如果你是要求免費指導或咨詢討論組。即使你是在支持協議的保護之下發問,激怒了你的技術顧問對長期合作也會很不利。
我曾經向臭脾氣的新人們解釋為什么他們的問題有問題或者什么是他們從一開始就做錯了的,真是太累人了。現在,我給你快速生效的傻瓜過濾器——“我想知道的只是……”或果斷無視。
讓所有人知道你讀了文件和谷歌搜索了該問題。除了避免回復必然的“RTFM”(游戲邦注:RTFM意為:去讀該死的指導手冊。當你需要信息或者解決問題時,在請求對方幫助之前,應該花一些時間嘗試自己去尋找需要的東西。)和“Google is your friend”,都顯示了你做足了功課,那些幫助的人不必搜索相同的資源。如果你確實指望他們為你搜索那些資源,那你的意思就是,你的時間比他們的金貴,你在謀殺他們的時間。
白癡答案
如果你要表現得你知道自己在說什么,那么你確實應該知道你到底在說什么。工程師的交流有時候更多地是炫耀自己的知識而不是提供信息(如果你也能這么做,那我向你致敬)。這往往無益于求職面試,面試官其實是假借“發現你是怎么想的”的幌子,向求職者拋出空洞的問題。當然,如果求職者有一點自知之明的話,也可能產生出乎意料的結果。
有一位技術總監打電話面試我,要我概述C++編輯的結果堆棧框架,并且口頭答復他。我一步一步地打草稿,每次我給他正確的答案,他都反過來要我說一個錯誤的答案,以便我們可以仔細檢查為什么那個選擇不管用。我不知道我這么寫是不是在彰顯我有多聰明或他有多聰明。
作為一名工程師,你不能太倚重錢財和長相——信譽才是你的資本。所以如果你犯錯了,就坦率承認吧。
我有幸與一名資深工程師共事,他從來不犯錯。當他的Java代碼在多重處理器系統中崩潰時,原來是出現了大漏洞。當我拿代碼指出UI代碼不支持多線程運行時,他堅持說只有一個線程。當我列出代碼中的7條線程(我能找出的)時,他同意不應該保留這么多線程,并且最好修改一下。但他還是按老樣子編寫代碼——他沒有修復任何漏洞,他只是用更多代碼掩蓋了漏洞。
最后,一個節省時間的建議:不要糾結于愚蠢的爭論。愚蠢是會傳染的。(本文為游戲邦/gamerboom.com編譯,拒絕任何不保留版權的轉載,如需轉載請聯系:游戲邦)
Seven Habits of Highly Effective Programmers
by Phil Chu
The following blog was, unless otherwise noted, independently written by a member of Gamasutra’s game development community. The thoughts and opinions expressed here are not necessarily those of Gamasutra or its parent company.
Want to write your own blog post on Gamasutra? It’s easy! Click here to get started. Your post could be featured on Gamasutra’s home page, right alongside our award-winning articles and news stories.
For my second gamasutra blog (I’ll stop counting at some point), I’m reposting one of the software development essays I wrote between my last salaried job and my first serious contract gig (during which my claims to be “self-employed” sounded like a euphemism) under the theory that if I wrote down all my opinions I wouldn’t have to repeat them during job interviews.
That turned out not to be a great theory, but anyway, here’s the first of those essays, and the most popular:
As a software engineer, you might want any number of things out of your job – a steady paycheck, the opportunity to work on interesting projects, a springboard to the next better job, or maybe you just like hanging out with other programmers. But by “effective”, I mean the ability to complete projects in a timely manner with the expected quality. After working on dozens of software releases, I believe the following practices will bring you there, and while they may involve sticking your neck out, I’d like to think they will also advance your professional reputation, career longevity, and personal satisfaction.
Understand Your Requirements
The first step in becoming an effective programmer is to ensure that you are spending your time wisely. And there is no greater waste of time than in working on something that is not useful or never shipped.
Build Early
Get a demonstrable system working as early as possible. This means establishing the interface first, whether it’s an API or user interface, and stubbing the encapsulated functionality as necessary.
This allows your “customers” to check it out, by exercising the user interface or writing code to the API, and any inconsistencies or omissions in the initial spec can be detected early. Chances are, you will notice problems or potential improvements even before releasing this first deliverable.
There is a classical school of thought that believes if you design everything up front, then all you have to do is write the code and you’re done. That works great if you’ve done the exact same project before. Otherwise, it’s more likely you’ll run into a point where you’re just guessing or operating on questionable assumptions.
Upon joining an early-stage wireless internet startup, I found myself in two months of design meetings for a wireless portal and gateway due to launch in six months. Eventually we got tired of meeting and finally started coding. Within two weeks, my part of the project had no resemblance to the original design, and the first wireless connection test two months later revealed a fundamental misunderstanding of the wireless protocol.
This is not to say that design is unnecessary. But after a certain point, design is just speculation. Design should be validated with implementation, and better to do that early and continuously than late and, well, too late.
Even if the original design is sufficient, once you have something you can tweak, you can improve upon it. Hardware products (who designed this VCR?), buildings, and large-scale software projects suffer from interfaces that were frozen in “preproduction”, but with software, you have an opportunity early in the project to refine your understanding of the requirements and produce a suitable interface. But it must be done early.
Getting something ready early is also good for your occupational well-being. Your boss will appreciate seeing evidence that something is actually getting done and having something available to demo. On the other hand, a drawn out period with nothing to show is a recipe for anxious management.
Deliver Often
Once you have something working, don’t just leave it as a “proof of concept”. Let people play with it, see their reactions, and let this guide and prioritize your development. There is no substitute for watching how people use your software. Customer questionnaires and focus studies might provide some useful input but run the risk of transferring feature and design decisions from the developer to the customer.
In particular get the software into the hands of the QA staff as soon as possible and feed them regular builds, preferably at scheduled intervals. Having them test automated daily builds is ideal, but even a weekly build is pretty good. This will help them feel involved in the full life-cycle of the project and they should be best-trained at identifying and reporting problems. The highest priority should be given to issues that prevent them from using the product, e.g. crashes or dead-end paths – you want them to cover as much as possible as soon as possible and get a feel for the whole product so design issues can be identified early.
At a small 3D graphics software vendor, I was put in charge of porting the flagship product from SGI workstations to Windows NT. After six months, the port was so incomplete and crash-prone that I was reluctant to give the first “alpha” build our test group. Fortunately, the QA manager insisted, and the resulting bombardment of bug reports forced me to immediately focus on the problems that prevented the testers from exercising the application in any meaningful way. Left to my own devices, I would have worked on what seemed to be the harder and more important core 3D issues, and probably delayed too long on seemingly mundane issues like the user interface, load-save functionality, and compabilility with all the varieties of consumer hardware we were planning to support.
Programmers often don’t want to release code to testers early – they don’t want to hear about a bunch of bugs they already know about, and quite possibly the testers don’t want to test something that barely works. But it’s the testers’ job to find these problems and programmers need to realize bug reports are a good thing, if they arrive early enough.
Keep It Real
Keep your software running in as close to a shipping state as possible. You never know when you’ll have to demo the system, send out an evaluation copy, or even deliver (“OK, time to wrap things up!”)
Use Real Data
If you just test with sample data, that big iceberg of real data out there is going to sink your program.
One of the leading semiconductor fabs evaluated a supply chain management product I was working on. After crunching out a milestone delivery to them, we got word back that the first batch of data they fed it from their own operations was still processing – for two days. I sympathized with the lead programmer, who had to dig down and emergency-optimized everything he could for two weeks with both management and client breathing down his neck. I’m just glad it wasn’t me on the line.
Use Real Builds
Remember the development build on your machine is not the real build.
On a recent game development project where I worked on the user interface, I got intermittent reports from QA that some colors were not correct. Eventually, I realized the problem only showed up in release builds and another programmer used the special console debugging hardware to track down the bug. Which turned out to be a silly mistake I’d made two months previous, failing to specify an initial color value in a few cases. The debug build always selected a specific default value, while the release build optimized that away and the result was less determinate. If I’d made a point of running the release build frequently, I would have spotted my mistake immediately, instead of losing it in the sands of time.
Merge Often
Don’t procrastinate on merging your code with the main code base – the longer you wait, the harder it gets.
I worked with a programmer who “couldn’t be bothered with” all the new code and data changes that showed up in the repository every day. And certainly, daily merges did take up some time for all the other programmers, and this programmer was able to run some impressive standalone demos with a snapshot of the code and data. But every time we had a milestone delivery, it took days to get the isolated code reattached to the current codebase again, sometimes compromising the milestone delivery and risking the funding for the entire project.
Keeping your code out of the official build means that programmers cannot evaluate your code and testers cannot spot bugs early. Maybe you don’t want people picking on your code or bugs, but it’s better to identify those issues early than later – suck it up.
Understand Your Code
Life is full of wonderful mysteries, but your code is not the place for them. You don’t have to know how your car works – if the engine starts making strange noises, you drop it off the mechanic.
When it comes to your code, if you don’t understand how it works, or doesn’t work, no one will.
Code with Style
My childhood piano teacher once commented to me, “Your sister has a good sense of timing, and your brother has a good feel of the keyboard.” Then he paused. “You, uh, you work hard.”
Programming is one of those things that a lot of people are more or less competent at, but some in particular have a flair for it. I’m a lousy piano player despite years of lessons, and I’m a mediocre basketball player although I enjoy playing it immensely. But I do like to think I have a flair for programming and writing. And not surprisingly, I think good programming is like good writing. Both prose and code are textual, have grammar, syntax, spelling and semantics and spelling. For most coders and writers, this is enough, but the best writers and coders have an esthetic and their work features structure and style that can often be identified with the author.
Many Windows programmers wonder why grumpy old Unix/Mac/Amiga/Lisp programmers rail against Win32/MFC/.NET, but if all the API’s you’ve seen are from Microsoft, you probably don’t know there’s anything better.
Perhaps not everyone is capable of writing stylish code – I’ve heard it said that good object-oriented programmers, in particular, are born and not made. But like fine music, wine, and literature, you can learn to appreciate good code.
Cut-and-Paste
The opposite of stylish programming is cut-and-paste. Grab some code from somewhere that is supposed to do something like what you want, tweak it until it sort of works, stir, repeat, and voila, you have the software equivalent of mystery meat.
A few months after leaving one company, a former coworker emailed me a single function consisting of ten pages of cut-and-paste code and asked why it wasn’t working. I could have very well asked why it should work at all. If you can’t explain how your own code is supposed to work, how can you expect anyone to help you with it?
I’ve even had trouble diagnosing my own code that was cut-and-pasted from sample code. It’s a reasonable way to start new code, but you can’t just leave it alone when it seems to work – you have to go back and make sure you understand it line by line and clean it up for your own purposes.
Keep it Clean
The key to keeping your house/condo/apartment clean is to spend a little time cleaning it every day, or at least every week. If you wait until your abode is an unsightly mess, it’s just too much damn trouble to clean it all up and you end up just doing a halfhearted job. Or your hire a cleaning service.
Assuming you don’t have the luxury of hiring someone to come in and clean up your code every week, you should periodically inspect your code, sweep up accumulated hard-coded numbers, outdated comments, misleading function names, or you’ll inevitably end up with uninhabitable code that’s embarrassing to show anyone else. And if you’re not embarrassed, well, you should be.
One programmer I supervised kept reporting to me that her code was “done”. This is what management normally likes to hear, but it drives me crazy. Code is never done – you have to debug it, maintain it, evolve it until it’s put out to pasture.
Questions? Comments?
Some like to think of programming as a craft. Others, engineering. More often than not, it’s archaeology. You dig through sediments of code and wonder what purpose all these strange artifacts served. Do future generations a favor and leave some clues.
I asked the aformentioned engineer whose code was “done” to add comments. The result, a function named GetData was prefaced by the comment “Gets data.” That’s not just useless – it’s insulting.
What data? (factory automation schedules) In what format? (a proprietary XML format) From where? (an in-house server, using TCP/IP) Not to mention little details like what happens when the server is unavailable or the transmission is broken.
Document your code as if someone else might have to take it over at any moment and know what to do with it. That person might actually be you – how often have you had to revisit your own code and thought to yourself, what was I trying to do here?
On a contract with a previous employer, I was asked to look over a piece of code that no one else had time to attend to. At first, I thought it was a mess and didn’t know what was going on in there. Then I gradually figured out what the code was doing, and I grudgingly admitted the code wasn’t too bad. And then I eventually realized that I had written the code two years ago. Note to self: need more comments.
With that in mind, annotate your code as you write it, instead of waiting for a convenient cleanup phase in “post” – annotating as you code can even clarify your thoughts while you’re programming.
You can be your own pair-programming buddy.
As a bonus, these days you can generate nice HTML or otherwise-formatted documentation from source code comments, using javadoc, doxygen, whatever. Ideally, the doc-generation is part of your nightly build and available via your intranet.
Full Warning
Ignore compiler and runtime warnings at your own peril. They are called “warnings” for a reason.
I shipped one Unix-based application that had a problem linking some functions successfuly – we worked around it by relinking those functions at runtime. When we performed a clean rebuild six months later for the next release, it was revealed that we had turned off linker warnings which would have alerted us of a known linker bug. In our defense, we had swept the linker problems under the carpet at the Unix vendor’s suggestion, (thanks, SGI!) but it turned out we could get the link to work just by reordering our libraries.
Crank up the warning levels on your compilers, sprinkle your code with assertions, and log the build and test-time warnings. Better yet, include a count of those warnings in your build metrics so you know if you’re dealing with them or letting them accumulate.
Optimal Programming
Code with Purpose
On the other extreme from cut-and-pasters are those who change code just to make it look prettier (at least to them). While it’s laudable to have a programming esthetic, it’s a waste of time (and a useless risk) to change code just so it looks better to you. It’s aggressively annoying to go through and change code that other people have written just so it looks better to you.
A fastidious coworker of mine went through our codebase and removed all the expletives. Probably no one would have complained if he had just cleaned up the code written by the entry level employees, but the expletives belonged to the technical lead of our group who was also one of the few distinguished Fellows at the company.
Do No Harm
“Refactoring” is all the rage, now, but programmers often take it to mean any code cleanup or redesign. The trick is in reorganizing code for the better without breaking anything. If you break existing functionality in the name of progress, you’re sending one of two messages: 1) your time is more important than everyone else’s, or 2) you’re incapable of touching code without breaking it.
I had one particularly contentious coworker who decided to reimplement the parser in our system but left the code in an unbuildable state by everyone else. I asked him to revert his changes and then found the code was buildable but not runnable – asked about it, he replied that he removed the parser entirely “per your request”. Not a team player.
Keeping the code functioning takes some patience and extra work – you have to be diligent about regression-testing your work and chances are you’ll need to keep old code and interfaces around for a while as you migrate functionality to your new code. But for everyone to work with the same codebase, that’s what you have to do.
Find the Bottleneck
People always talk about “optimization”, but that isn’t really a correct word. We’re rarely shooting for the optimum – instead, we make improvements and tradeoffs to achieve good-enough performance.
I was asked in a phone interview with Google how I would search for a number in an array of ordered numbers. Obviously, the questioner was asking for a CS 101 answer – binary search. But in real life, I would probably do the “wrong” thing – search the array from beginning to end. There’s no point in taking twice the time to write twice as much code that has to be maintained and debugged if the application performance is good enough, and in particular if that piece of code is not the bottleneck in the application. (And I seriously doubt you’d have that data laid out linearly in a fixed array like that if it was the bottleneck)
If you do need to optimize for speed or space in you application, attacking anything other than the bottleneck is a waste of time.
Manage Thyself
You probably have a lot of complaints about your boss being a lousy manager, and you’re probably right. So you have to be your own manager. Even if you have a decent boss, he’s not going to stand behind you telling you what to type and how fast (although I’m sure many would like to).
Are We There, Yet?
Programmers are notoriously inadequate at providing useful schedule estimates. I think this is a bad rap, since management, left to their own devices, often make even worse predictions, and unwelcome news from engineers is often ignored. (A common theme in any engineering disaster). But still, awareness of the schedule is critical to actually getting the project done on time.
On one commercial software project, some of my coworkers were blissfully unaware of the product release date – one inquired whether it had been released already, another was surprised to find it was going out in a few days.
The worst, and most common, schedule estimate that a programmer can give is “it should just take a couple of days”. Every time I hear that, even from my own mouth, I wince.
The president of a graphics software company really wanted support for VRML (at the time it was the Next Big Thing) included in the product we were releasing in two months. He probably figured (correctly) that I would resist starting a new feature, so he went to another engineer and got the answer he wanted: “a couple of days”. Two dayslater, I told the president we-just-wasted-two-days-of-his-time-and-mine-while-there-are-two-hundred-high-priority-bugs-to-fix, which he found to be a persuasive argument. (postscript: VRML didn’t exactly take off like gangbusters)
And then there are programmers who are unable to come up with time estimates at all. But there’s no need to get thrown off by the fuzzy nature of the request – it is an estimate after all, and in fact you should avoid using formulas. If you’re an experienced engineer, you know how long comparable tasks have taken you before, and if you’re not experienced, you can ask someone who is.
A smart friend of mine who was often assigned to developing experimental prototypes asked me, “how can you schedule research”. I think it was a rhetorical question, but even pure researchers have schedules. Someone is paying them and expects results, even if it’s a number of demos or published papers in a certain timespan. And if you really don’t have the foggiest idea how long something will take, then you’re the wrong person for the task.
Sometimes programmers are reluctant to commit to a schedule because they’re afraid of the accountability. It is true, in this imperfect world, managers will try to bargain you down on schedules, political factions may saddle you with tough or unrealistic schedules in the hopes that you will fail, and it is a sadly common story that after you commit to a schedule, you don’t get everything you need.
I had one boss who after asking for an estimated completion time would say, “do you promise?” But ask for a commitment on the required hardware and other dependencies, and it was “I’ll try.”
All I can say is, stick to your guns and give a realistic prediction. Any concessions should be based on pragmatic tradeoffs between features and resources. Be clear about the assumptions, dependencies and resources on which the schedule is based, and get it written down somewhere so you can jog defective memories later.
Plan Your Progress
You wouldn’t just hop into your car before deciding where you want to go, right? And probably you have a route in mind before you start driving, too. Similarly, before you sit down at our computer, you should know what you want to accomplish that day and have some idea how.
Distractions will come up day-to-day, so you won’t always be able to accomplish what you want. And contrary to those who treat software engineering groups as vending machines (they would probaby shake us vigorously if they could) some tasks take more than a day. So think about what you want to accomplish by Friday, and if you do, then you can enjoy the weekend that much more.
Continuous Education
A corporate soccer team member once asked me, as we were lacing up our cleats, “what’s the secret to C programming?” If there was such a secret, I’d be hawking it on late night TV along with ab machines and how to get rich in real estate. Sorry, there’s no shortcut – you have to learn and practice and make some mistakes. And you don’t necessarily have to rely on corporate training or going back to school – there are plenty of (inter)national and local professional groups, books, and of course, the Internet.
It’s Science
It’s called “computer science” for a reason. It’s easy (maybe too easy) for anyone to to start programming, without a formal computer science education. In particular, those from other engineering and science disciplines can pick up programming quickly and make a good living. But to effectively tackle non-trivial tasks, you need to know the inherent capabilities and limitations of software and recognize prior work, so you don’t waste time reinventing the wheel, badly. You don’t have to know everything under the sun, but you should have at least a cursory familiarity with many areas and be prepared to do some additional research as necessary.
For example, anyone who creates a new file format should know something about compilers. I don’t mean all the code-generation optimizations like loop unrolling, but the basic issues and various phases of compilation and most of all the importance of specifying the tokenization and grammar. Nowadays, most people by default will use XML, and that’s a good thing, but before then it was typical to cobble up some text format, point to some generated sample files as documentation, and then everyone else who wrote another parser would cobble something up that would read in some files but not all. In the problematic cases then you could point fingers either way – either the reader is bad or the writer is bad. Whichever product is more popular wins.
One of my pet peeves with the 3D graphics industry is the plethora of ill-defined file formats. When I implemented an OBJ file parser for a 3D content creation product, each exporting product that I tested against generated markedly different files, using different whitespace and newline conventions, for example. In refreshing contrast, a coworker of mine fresh out of school designed a new game interchange format using a grammar and lexer specification. (These days, it’s not much of an issue anymore – most new graphics file formats seem to be based on XML.)
And if anything differentiates programmers who can just put together simple scripts and user interfaces and those who can tackle real problems, it’s an understanding of computational complexity, i.e. how algorithms scale with the size of the problem. Every programmer should know basic complexity terminology and have a general knowledge of the complexity of common problems.
My first job was in computer-aided semiconductor design, which has a lot scalability issues, including some NP-complete (essentially intractable) problems. But some of the engineers would run around excitedly saying “it’s the traveling salesman problem!” every time they saw a problem that couldn’t be solved in linear time, and in other cases we boasted of “linear-time” algorithms which probably meant linear-time most-of-the-time. Or some of the time.
Free Beer, Free Speech, Free Software
OK, there’s no free beer, but this is a good time to be a programmer (well, recession and outsourcing controversy notwithstanding) – just about everything you need is on the Internet tutorials, discussion lists, and free software. All you need is the hardware and a broadband connection.
R-E-S-P-E-C-T
One requirement for being an effective software engineer is to be taken seriously. You need to have the respect of your peers and managers, at least for your technical capabilities, to have control over your own work and influence over others.
There is Such a Thing as a Stupid Question
Really, there are lots of stupid questions. Asking intelligent questions that enhance others’ respect for you is a professional skill. A good question that exposes unresolved issues tells people that you know your stuff and you’re sharp enough to catch all the implications. Asking for clarification about a specification shows you know how to find and read the spec and your ability to detect ambiguities.
If you don’t get any answers to your question, chances are there’s something wrong with the question, so don’t just repeat it. Ask the question differently, with more specifics, or more background.
If you’ve been on the other end of a technical support line or even just spent time on discussion lists answering newbie questions, you’ll appreciate the consideration.
I pride myself on cultivating good relations with developer support staff by submitting elaborate bug reports and precise questions. But I do remember one lapse where I tossed out something along the lines of “What’s the deal with that issue that came up several weeks ago?” You can imagine the prickly response – “What do you mean by what’s the deal, and what issue are you talking about?”
It doesn’t pay to be rude, especially if you’re essentially asking for free tutoring or consulting on a discussion list. Even if you’re asking under the auspices of a support contract, irritating your support contact isn’t going to help you in the long term.
I used to take pains to explain to belligerent newbies why their questions didn’t make sense or what they were fundamentally doing wrong. Now, the bozo filter kicks in quickly – one “All I want to know is….”, and they’re ignored.
Let everyone know that you read the documentation and googled the subject. Besides avoiding the inevitable “RTFM” and “Google is your friend” responses, this shows you’ve done your homework and those who want to be of assistance don’t have to search through the same resources. If you do expect them to search through those resources for you, then you’re saying your time is more important than theirs, and you are just one more perpetrator of the “tragedy of the commons”.
There is Such a Thing as a Stupid Answer
If you’re going to act like you know what you’re talking about, you really better know what you’re talking about. Engineers sometimes communicate more to show off their own knowledge rather than to inform (although, if you can do both, kudos to you). This is often inflicted in employment interviews, under the guise of “finding out how you think” the candidate is asked inane puzzle questions.
This can backfire, though, if the candidate has any self respect.
One CTO interviewed me over the phone by asking me to sketch out the resulting stack frame from a C++ compilation and then report the result back to him verbally. We went through it step by step and every time I gave him a correct answer he asked me to give a wrong answer instead so we could go over why that choice wouldn’t work. I couldn’t tell if we were trying to demonstrate how smart I was or how smart he was.
There’s also the blame game. As an engineer, you can’t rely on your money and looks – all you’ve got is your credibility. So if you make a mistake – ‘fess up.
I had the privilege of working with a senior engineer who was never wrong. When his Java code was crashing on multiprocessor systems, it was Sun’s bug. When I took over the code and pointed out the UI code was not supposed to run in multiple threads, he insisted there was only one thread. When I listed the seven threads (that I could find) in the code, he agreed I shouldn’t have all those threads and I’d better fix it. He programmed in that fashion too – he didn’t fix any bugs, he just covered them up with more code.
Finally, a bit of time-saving advice: Don’t get dragged into stupid arguments. Stupidity is contagious.(source:gamasutra)
from:?http://gamerboom.com/archives/65164
總結
以上是生活随笔為你收集整理的分享成为高效程序员的7个重要习惯的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一道简单的算法题
- 下一篇: 五种应该避免的代码注释