日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
程序員真香定律:源碼即設(shè)計(jì)

本文轉(zhuǎn)載自微信公眾號(hào)「 碼磚雜役 」,轉(zhuǎn)載本文請(qǐng)聯(lián)系 碼磚雜役 公眾號(hào)。

創(chuàng)新互聯(lián)公司是一家專業(yè)提供定結(jié)企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、HTML5、小程序制作等業(yè)務(wù)。10年已為定結(jié)眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進(jìn)行中。

我們經(jīng)常談?wù)摷軜?gòu),討論設(shè)計(jì),卻甚少關(guān)注實(shí)現(xiàn)和代碼本身,架構(gòu)和設(shè)計(jì)固然重要,但要說代碼本身不重要,我不同意,Robert C.Martin大叔也不同意,Martin認(rèn)為“源碼即設(shè)計(jì)”。

在討論具體的實(shí)施細(xì)則之前,我們不妨討論一下什么是好代碼?蘿卜特 C.Martin認(rèn)為:衡量代碼質(zhì)量的唯一標(biāo)準(zhǔn)是:WTF/min,也就是review代碼的時(shí)候每分鐘說“握草”的次數(shù)。這個(gè)定義雖有辱斯文,但粗野中不失奔放,調(diào)皮中又蘊(yùn)含哲理。

好的代碼如同文筆優(yōu)美的散文,行云流水,賞心悅目,閱讀的時(shí)候,如沐春風(fēng),帶給人愉悅與啟迪。

好的代碼猶如構(gòu)思精巧的小說,它或許不夠平鋪直述,卻足夠引人入勝,讀到最后,你會(huì)豁然開朗,臥槽,原來是這樣的啊,那一刻,你會(huì)覺得過程中的曲折和探索都是值得的。

好的代碼,透過一個(gè)個(gè)函數(shù),你仿佛可以窺視到作者有趣的靈魂;透過一行行代碼,你仿佛在與一個(gè)充滿智慧的朋友聊天,她總是條理清晰,邏輯嚴(yán)謹(jǐn),有條不紊,娓娓道來。

而壞的代碼,猶如病毒,它不僅癱瘓你的程序,還有很強(qiáng)的傳播效應(yīng),等到它擴(kuò)散開來,神仙難治。

壞的代碼,像一個(gè)泥團(tuán),又或者像一座屎山,閱讀的時(shí)候,你仿佛被困于黑暗的迷宮,又仿佛在跟一個(gè)絮絮叨叨的人交談,她的腦回路經(jīng)常短路,說話含混不清,主次不分,叨逼半天,你依然get不到她的中心思想,你常常感覺智商受到了莫大的侮辱,甚至感覺像被人喂吃shit,你面露艱難神色,心中萬馬奔騰。

有很多區(qū)分好壞代碼的規(guī)則,我也看過一些,對(duì)于文章中提到的一些標(biāo)準(zhǔn)做法,就不重復(fù)嚼舌頭根子了,我想結(jié)合自己的工作經(jīng)歷,談一談自己的切身體會(huì)。

閑扯半日,言歸正傳,要編寫彌漫好味道的代碼,要遵循哪些約束和指引呢?

一致性

持之以恒的遵從一致性規(guī)則,在代碼風(fēng)格上,爭(zhēng)論個(gè)三天三夜估計(jì)也定不出個(gè)好壞出來,但好的風(fēng)格一定是強(qiáng)一致性的,這一點(diǎn)應(yīng)該比較容易達(dá)成一致吧?風(fēng)格的好壞其實(shí)更多受習(xí)慣的影響,頭發(fā)少一點(diǎn)的程序員應(yīng)該都有自己風(fēng)格變遷的經(jīng)歷,多年前自己篤信不疑的good style或許正是當(dāng)前深惡痛絕的bad style,所以我主張?jiān)趕tyle上擱置嘴炮,一個(gè)項(xiàng)目應(yīng)該有一個(gè)編碼規(guī)則,好的規(guī)則應(yīng)該是以理服人的,好的規(guī)則應(yīng)該是拒絕任性?shī)A帶私貨的,規(guī)則定了之后,就遵照?qǐng)?zhí)行吧,可能某個(gè)風(fēng)格跟你不相符,但沒關(guān)系,你要知道,這并不意味,你在style之戰(zhàn)敗下陣來,也并不表示它說服了你,你遵守的是規(guī)則和紀(jì)律本身。

我經(jīng)歷過一些c的項(xiàng)目,函數(shù)命名有大駝峰,有小駝峰,有下劃線連詞,還有駝峰加下劃線(有些是兩個(gè)),還有函數(shù)名下劃線或者兩個(gè)下劃線開頭,總結(jié)一下它的規(guī)律就是沒有規(guī)律,非常隨心所欲,令我莫衷一是。

變量(包括文件、類/結(jié)構(gòu)體、函數(shù))命名,比如ohmygod,你可能搞不清哪些字母是一伙的,所以需要界定單詞。駝峰通過單詞首字母大寫來界定單詞,另一個(gè)慣用做法是用下劃線拼接單詞。駝峰的弊端是丑,下劃線拼接的弊端是增加了標(biāo)識(shí)符長(zhǎng)度(相比首字母大寫),好處是跟std c/c++、linux kernel的做法一致,喜歡kernel的碼農(nóng)容易找到如家般的歸屬感。

c++有namespace避免沖突,c經(jīng)常用prefix防止命名污染全局空間,但我認(rèn)為命名簡(jiǎn)潔扼要很重要,所以我支持簡(jiǎn)短的前綴而反對(duì)冗長(zhǎng)的前綴。

代碼密度

實(shí)現(xiàn)同樣的功能,你喜歡100行代碼,還是20行代碼?如果貴司不以代碼行數(shù)考核績(jī)效我建議你把代碼寫的精簡(jiǎn),而如果貴司以代碼行數(shù)考核績(jī)效,我建議你離職,開滴滴,送外賣或者擺攤都行,因?yàn)樵谶@種公司耗費(fèi)青春基本上也不會(huì)有什么發(fā)展前途。

把簡(jiǎn)單的東西搞復(fù)雜化很容易,你只需要找一個(gè)能力平庸的人就能實(shí)現(xiàn)化簡(jiǎn)為繁的愿望,而化繁為簡(jiǎn)則堪稱化腐朽為神奇。也許你要說,我欠缺簡(jiǎn)化的能力,這并不奇怪,坦白講,這不是一件容易的事,你做不到?jīng)]關(guān)系,但你擁有正確的理念更重要,它將幫助你認(rèn)清前進(jìn)的方向,而不是在錯(cuò)誤的道路上越走越遠(yuǎn)。

有些項(xiàng)目,充斥各種無效代碼,其實(shí)你只需要稍加思考,你就能識(shí)別出來。

比如大塊注釋掉的代碼像發(fā)臭的尸體一樣遍布其中。比如大量功能重復(fù)的代碼像垃圾一樣堆砌在那里。

比如本不需要返回值的函數(shù),執(zhí)拗的固定返回true,然后在調(diào)用的地方還要裝模作樣的check一下返回值,如果返回false,再記一條日志,再assert一下,再拋個(gè)異常,這樣顯得很有職業(yè)操守,美其名曰面向failed編程,處理了各種異常情況。

又或者函數(shù)一進(jìn)來,不管三七二十一,對(duì)入?yún)⒁活D無腦檢查,一頓操作猛如虎,一看代碼二百五,宣稱這是符合ISO XX標(biāo)準(zhǔn)的安全做法,全然忘記你在編寫的是一個(gè)私有實(shí)現(xiàn)函數(shù),你在調(diào)用它之前已經(jīng)檢查過一遍,私有函數(shù)是一個(gè)受控的安全上下文,這不僅不優(yōu)雅而且不綠色(低效耗電)并且不安全(在該崩的時(shí)候沒崩把雷埋到了更隱蔽的地方),話說你看標(biāo)準(zhǔn)庫(kù)函數(shù)strcpy/strcat,vector operator[]檢查傳參了嗎?

提高代碼密度或者說濃度有利于理清思路,有利于突出重點(diǎn),有利于提高維護(hù)性,而充斥各種無效語句的代碼只會(huì)把關(guān)鍵語句淹沒在汪洋大海,使得review代碼的人get不到重點(diǎn),看不清主次。像聽一個(gè)絮絮叨叨的人做報(bào)告,滿篇廢話,像看一個(gè)劇情拖沓的連續(xù)劇,昏昏欲睡,像喝一瓶二鍋頭兌十斤白開水,口能淡出個(gè)鳥來。

重構(gòu)是程序員的口頭禪,重構(gòu)是在保持程序功能不變的情況下調(diào)整架構(gòu)和實(shí)現(xiàn),我認(rèn)為提高代碼密度應(yīng)作為重構(gòu)的一項(xiàng)追求。

linux kernel、lua、nginx、skynet這些優(yōu)秀的開源庫(kù)代碼濃度都很高,建議讀者朋友品嘗一下。

封裝

我們最常干的一件事就是把重復(fù)編寫的代碼封裝到一個(gè)函數(shù)里去,用多處調(diào)用替代重復(fù)編寫,這個(gè)很好理解,但其實(shí)即使不被多處調(diào)用,把相關(guān)的一段代碼封裝到一個(gè)實(shí)現(xiàn)函數(shù)也是有必要的,因?yàn)榘汛a平鋪開來,把細(xì)節(jié)暴露出來,容易掩蓋重要的東西,即框架和脈絡(luò)會(huì)變得不夠清晰。

一個(gè)見名知義的函數(shù)調(diào)用比堆砌在那里的一段代碼給我的感受好,我如果關(guān)心它是怎么做的,我可以跳轉(zhuǎn)到定義看看實(shí)現(xiàn)。

封裝的一個(gè)核心原則是單一職責(zé),符合單一職責(zé)的函數(shù)更易于被復(fù)用。

解耦

構(gòu)建松散耦合的系統(tǒng)一直是軟件工程的一個(gè)目標(biāo),模塊化的一個(gè)方向便是解耦,但我們口口聲稱心心念想的解耦,在實(shí)施層面又有幾分體現(xiàn)呢?

比如,我們經(jīng)常干的一件蠢事就是把類似配置文件,或者宏定義的東西集中的一個(gè)頭文件里去,看起來很統(tǒng)一也很正規(guī),起碼我之前也是這樣認(rèn)為的,但忽然有一天,發(fā)現(xiàn)自己這樣做顯得很不聰明的樣子,為什么呢?因?yàn)槟阆氚阉心K配置相關(guān)的東西都塞進(jìn)配置公共文件真的合適嗎?是不是把公共接口抽離出來更好,把配置相關(guān)的數(shù)據(jù)下沉到各模塊更合適?

另外,把宏都定義到一起,這意味隨便改點(diǎn)東西,都會(huì)需要修改宏頭文件,而這個(gè)頭文件就會(huì)成為程序世界的中心,修改公共宏文件幾乎會(huì)引起整個(gè)系統(tǒng)的所有源文件rebuild,這簡(jiǎn)直就是AOE團(tuán)滅啊。所以更好的方式是分而治之,去集中式。

我們知道c/c++的編譯單元是source file(.c/.cpp),編譯的第一步是預(yù)處理,所有include都會(huì)展開替換,所以我們要避免引入任何不必要的頭文件,也應(yīng)該把本編譯單元用到的頭文件都include進(jìn)來,這就是所謂的頭文件自給自足。這點(diǎn)很重要,但很多人會(huì)不以為然,甚至有些人會(huì)自作聰明的搞一個(gè)allincluded.h,把常用的一些頭文件全部include進(jìn)來,然后沾沾自喜的自認(rèn)為一勞永逸的完美的解決了問題,包含不必要的頭文件會(huì)增加編譯時(shí)間,會(huì)增加依賴,我們不僅應(yīng)該避免錯(cuò)誤的包含,還應(yīng)該精心設(shè)計(jì)和劃分文件,使得每個(gè)文件的功能足夠內(nèi)聚單一。

縮寫

慎用縮寫,相比縮寫帶來的含混不清,我寧愿多敲幾下鍵盤,如果要縮寫請(qǐng)符合慣例遵從常規(guī),比如AI,比如App,比如cfg,但是你把threshold縮寫成threshod,把Item縮寫成Iem,我特木真的搞不懂你是拼錯(cuò)了還是縮錯(cuò)了?

遵從標(biāo)準(zhǔn)

我遇到過一些項(xiàng)目,每個(gè)模塊單獨(dú)定義自己的int32,float,char,void,比如定義MoKuaiA_int32,MoKuaiB_int32,MoKuaiC_CHAR,不僅如此,它還把inline,true,false,VOID,const,case,static等一眾關(guān)鍵字全部redefine了,令人匪夷所思的是它竟然把標(biāo)準(zhǔn)C API全部重定義一遍,令人發(fā)指的是它竟然不讓你用語言的標(biāo)準(zhǔn)寫法。

我一直搞不懂為什么要這樣做?如果你只是需要解決不同體系結(jié)構(gòu)下long等整型的長(zhǎng)度差異,我想偷偷告訴你,c庫(kù)頭文件stdint.h已經(jīng)從標(biāo)準(zhǔn)層面統(tǒng)一解決了這個(gè)問題,里面int8_t/16_t/32_t/64_t,還有uint8_t等等應(yīng)有盡有。

這樣的做法是很不好的,會(huì)讓符合標(biāo)準(zhǔn)的寫法寸草不生,建議不要這么做。

宏是c的一個(gè)有效武器,在有些情況下確實(shí)行之有效,我是宏的中間派,我既反對(duì)禁用宏,也反對(duì)濫用宏,inline可以部分替代宏,但不能完全替代宏。

但我見過一些項(xiàng)目,到處都是宏,全大寫,至少1/3的代碼都是各種花里胡哨的宏,你review代碼的時(shí)候,不停的跳來跳去,看了一眼,哦,就這樣啊,然后切回來,頻繁的上下文切換是低效的,它打斷了你的思路,讓你看代碼有種撒尿撒到一半憋回去的感覺。其實(shí)很多時(shí)候完全沒有必要,不需要整這些虛頭巴腦的。

命名

命名有一些指引,比如類/結(jié)構(gòu)體應(yīng)該用名詞,函數(shù)應(yīng)該用類似動(dòng)詞或者doSomething這樣的動(dòng)賓結(jié)構(gòu),這些規(guī)矩都是耳熟能詳?shù)摹?/p>

我主張命名應(yīng)該簡(jiǎn)明扼要,不要羅里吧嗦,要準(zhǔn)確的表達(dá)出它要做的事情,如果你碰到命名困難,你可能需要考慮你的類定義或者接口劃分是否合適。

命名是接口的一部分,很重要,好的命名是自注釋的。

如果你沒有思路,那我建議你參考一下STD C/C++ API,畢竟這些接口歷經(jīng)幾十年沒有大的變化,算是經(jīng)受住了歷史的考驗(yàn),比如malloc/free/atoi,stl 容器的成員函數(shù)也有點(diǎn)意思:size(), capacity(),resize(),reserve(),push(),pop(),top(),back(),很干脆,不廢話,我覺得很好。

所以,如果你編寫的是某某管理器,比如ItemManager,我建議你直接取名add(),remove(),而不用AddItem(),RemoveItem(),因?yàn)槟惚旧砭褪荌tem的Manager,操作的必然是Item,而且從參數(shù)上也能體現(xiàn)出來,少即是多,多不如少。

擴(kuò)展性

開閉原則是應(yīng)對(duì)擴(kuò)展性的rule,人無遠(yuǎn)慮必有近憂,說的是我們不能局限于眼前,但也請(qǐng)不要盲目迷信擴(kuò)展性,戲太多也是病。

知乎有一篇神貼講的是如何把helloworld搞成一個(gè)big project,當(dāng)你想給別人項(xiàng)目挑刺的時(shí)候,你可以用擴(kuò)展性說事,但我建議你離開口閉口擴(kuò)展性的人遠(yuǎn)一點(diǎn),據(jù)我觀察,這種人大多比較虛偽而且很水。

避免特例

linus大神分享過他心中的好代碼,說的是針對(duì)鏈表的操作,他更喜歡統(tǒng)一性的處理方式,而不是做特例化的處理,我想這個(gè)例子很有代表性,它其實(shí)代表一種理念,那就是自始至終,我們的頭腦里必須優(yōu)先考慮normal化的處理方式,當(dāng)然這其實(shí)是一個(gè)比較高層次的要求,菜鳥互啄可以先跳過這一層要求。

高效而魯棒

有很多避免運(yùn)行低效的做法,比如減少拷貝,提高局部性,buffer/cache,空間時(shí)間置換,內(nèi)聯(lián),分支預(yù)測(cè),判斷前置,計(jì)算延遲,無鎖技術(shù)。

提高魯棒性的關(guān)鍵是面向failed編程,不信任/零信任設(shè)計(jì),假設(shè)依賴的上下文,上下游都是不可靠的,方法很多,不一一列舉了。

最后

噴了這么多,也給大家一次噴我的機(jī)會(huì),我貼出來自己的代碼,https://github.com/ZhuanJia/mynet,這是13年剛進(jìn)福廠時(shí)候周末自己搗鼓的玩具,它或許有這樣那樣的問題,如果你覺得不錯(cuò),請(qǐng)給我點(diǎn)贊,如果你覺得很水,那我可以甩鍋給時(shí)間,畢竟7年前寫的嘛。橋水的CEO說過,如果你不覺得一年前的自己是傻逼,那說明你這一年沒什么進(jìn)步,何況7年前呢。

所有內(nèi)容純屬虛構(gòu),請(qǐng)勿對(duì)號(hào)入座,如引起不適,請(qǐng)盡快就醫(yī)。

搬磚不容易,累了,擱筆休息,擇日再議!


名稱欄目:程序員真香定律:源碼即設(shè)計(jì)
當(dāng)前網(wǎng)址:http://www.5511xx.com/article/dhsjodd.html