編程領域都有哪些牛逼閃閃的「禁術」?
用的好牛逼閃閃,用不好遺恨無窮,以至於很多人因噎廢食,比如經典的goto……
巫毒編程
巫毒編程指的是不求甚解只求結果的編程方式,最終導致編程從科學變成玄學,變成無法推論和預期的巫術,每次改個需求或加個功能都要祈禱計算機之神保佑別引發一大堆問題出來。
大家應該都有過這樣的體驗(特別是初學某個語言或技術的時候),當寫一個複雜程序的時候,出現了異常或者是錯誤的結果,折騰半天找不出原因,後來亂改改代碼莫名其妙的好了。如果就這麼停手不追問為什麼,那就是巫毒編程了。
比較典型的例子: 為了過驗收,到處加try catch。 有一些不知原因的問題,就這樣被掩蓋了。問題其實還在的,很可能從程序BUG升級成業務錯誤或者漏洞。也可能是通過try catch解決了眼下問題,但是最終原因不清楚,最後整個系統充滿這樣的情況,變得脆弱不堪。
巫毒編程導致的問題很多,在初學階段不求甚解導致基礎不紮實,在項目階段就是給自己和隊友埋下地雷,項目裡面到處是地雷的時候,就沒辦法做下去了。結對編程
兩名心有靈犀的男性程序員雙手重疊放於鍵盤上,並以身體一前一後的姿勢進行編碼。
蓄力術
指的是接到產品經理需求後無動於衷,然後開始聊QQ、刷知乎、看B站。臨近Deadline時再開始實現需求,並把一周的工作量在一天之內完成。
一本正經胡說八道術
在和產品經理進行需求對峙時,一本正經地把不喜歡實現的功能通過玄學等方式口述出來,讓產品經理知難而退。
開光術
在每個頭文件或實現文件頂部放置一個佛祖像,或在所有即將上線的最終產品、二進位、硬體等介質並邀請和尚施法開光,線上可獲得穩定增益。
不穩定輸出
在程序出現問題時亂改代碼以達到解決問題目的,雖然最後不知道到底哪裡出了問題,不過線上沒事就行了。
潔癖重構術
把同事所有代碼中的大括弧改為寫在下一行,並且不喜歡用if elseif / switch case寫超過3個statement的程序,通通改為寫成一個映射表進行跳轉。
二分調試法
在無法找到問題時,嘗試把相關代碼刪除一半並編譯運行,如問題依然存在,則再刪除一半代碼編譯運行。
在面對一個需求時覺得有的步驟可以寫一個工具方便自己更好地完成該需求,從而暫時丟棄當前需求去實現自動化工具,在實現工具的時候就會發現有更多可以自動化的東西,然後開始造底層庫的輪子。
- 線上debug:不知道這麼改對不對,先發到線上去試試。。。呃,確實不對,趕緊回滾!
- 撞大運編程:隨便改改,好像運行正確了,雖然不知道什麼原因。
- 萬能重構:別人的代碼寫的太爛,得重構;系統拆分不合理,得重構;性能太差,得重構;學習了一項新技術,得重構。
- TBC
以上,全乾過。
人生,完整了。
沒人提continuation?Scheme語言核心裡沒有try/catch,沒有return,沒有break,沒有continue。因為這些結構都可以用continuation加宏實現,別的語言需要放在編譯器、解釋器、VM里的東西,Scheme放到庫里就可以了。
#define private public
#define protected public
「親愛的同志們:
再過兩個小時,飛往XX海島的飛機就要起飛了。就在剛才,我終於改好了xx bug / 重構了xx 功能,code 已經 check in,不用感謝我,都是應當做的。
下下個星期見,我會想你們的!
btw,島上的網路可能不好,聯繫我就靠心電感應吧。」
第二天,面對編譯時的上百個error,運行時的莫名死鎖,項目經理和程序員們向彼此咆哮了起來,"WTF"的聲音在公司里此起彼伏。
放假之前,commit一套自以為NB的代碼,八成會出事。Self-modifying code.
歌詞大意就是手寫的代碼總是不夠快,在特定的情況下總是可以編譯出運行速度更快的代碼。 我當面問John Reiser當年和Rob Pike搞的bitblt[1]是什麼飛機,他淡淡地說就是裡面移動矩形的函數move根據不同的起始和終止位置會動態生成相對應優化過的代碼, 每個move(src_position, dest_position)調用的都是最優的實現。這種類似JIT(just-in-time)的思想會讓你真正地把代碼和數據看成一樣的東西,很多時候給出意想不到的高效解法。 還有一些有意思的討論在這裡[2],以及評論中 @韋易笑 的回復。
[1] Hardware/software trade-offs for bitmap graphics on the blit[2] http://yarchive.net/comp/self_modify.html
C++:我向合作者承諾我不會率先使用十幾個typename
Modern C++ Design (豆瓣)
Alexandrescu"s downloadable Loki C++ library, which provides powerful out-of-the-box functionality for virtually any C++ project
當然,還有中文編程
Forking 的兄弟 Spooning
1983 年已經有!
在代碼交付給客戶前,在預編譯頭文件中加一句
#define true (time(0) &<= time_a_month_later || rand() &> 80)
time_a_month_later就是交給客戶使用一個月後的時間。
這樣可以確保用戶每個月都請求一次技術支持。
F-algebra與各種recursion schemes。感覺原來在ML系語言里使用ADT的方式簡直是刀耕火種。。
Cloud Debug:將測試環節延後,產品先賣錢,等玩家罵娘再出補丁。
Cloud Pot-Distribute:你重啟了嗎,換個電腦,你操作有問題,策劃傻逼,需求不清楚
Perfect Solution:這個做不了,你們把策劃案改一下。
True Agile Development:小王,這個是他們源碼,改改上線
React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
聽起來像「禁術」的樣子……
Lisp 宏
因為安全性上的顧慮和當時我對 Lisp 還不夠熟悉,帶我入坑的人(做公司項目)一直不肯教我這個可以用代碼生成代碼的黑科技,直到後面我在個人項目里初次嘗試後,就停不下來了。
就是要注意生成出來的代碼重複不要太多,宏衛生,而且不要混淆直接注入的代碼和生成代碼。最大的缺陷是調試起來比較麻煩,生成的代碼出了錯誤不太容易看出到底在哪裡出了問題,因為錯誤棧基本沒有可讀性。
感謝@可知不可知 在評論中提到的assert.h和#define NDEBUG,我這個小方法還是自己做比較短的小程序的時候用吧,希望不會有什麼誤解。
下面是原來的回答
禁術之
/*用來測試的代碼塊
。。。
。。
。。。。
。。//*/
λ
女裝
Eval == Evil
會繞過所有編譯期語法檢查;非常不便於調試;極易導致安全漏洞;會阻止編譯器的進一步優化。
推薦閱讀:
※由小鮮肉變大叔是一種什麼樣的體驗?
※手握權力是種怎樣的體驗?
※穿Lolita裝是種怎樣的體驗?
※被惡意詆毀是種怎樣的體驗?
※熊孩子的哪些神句震驚了你?