[譯] 4 種預(yù)編譯頭文件(PCH)削弱代碼的方式

如果使用得當(dāng)僵控,預(yù)編譯頭文件可以為您節(jié)省寶貴的編譯時(shí)間锉屈。但如果使用不當(dāng)贮懈,預(yù)編譯頭文件可能會(huì)隱藏源代碼中的問(wèn)題,而這些問(wèn)題可能會(huì)在你嘗試在另一個(gè)項(xiàng)目中重復(fù)使用部分源代碼時(shí)才被發(fā)現(xiàn)醇王。

本文是Objective-C 中的代碼氣味系列文章中的一篇。

預(yù)編譯頭文件的用途

發(fā)明預(yù)編譯頭文件的目的只有一個(gè):"加快編譯速度"崭添。與反復(fù)解析相同的頭文件相比厦画,這些文件只需提前解析一次。速度非常重要滥朱!編譯速度越快根暑,就能越快查看最近的更改是否成功,越快完成反饋循環(huán)徙邻。

在 Xcode 中排嫌,您可以將所需的頭文件包含在 "prefix header"中,并啟用 "Precompile Prefix Header"缰犁,從而對(duì)其進(jìn)行預(yù)編譯淳地。但前綴頭文件背后的理念與預(yù)編譯不同。前綴頭文件隱含在每個(gè)源文件的開頭帅容。例如颇象,如果你的前綴頭是 Prefix.pch,那么每個(gè)源文件就會(huì)偷偷地

#import "Prefix.pch"

將其放在文件頂端并徘,比其他任何東西都先遣钳。這對(duì)于整個(gè)項(xiàng)目的 #defines 來(lái)說(shuō)很方便。(請(qǐng)記住麦乞,一般來(lái)說(shuō)蕴茴,#defines 是一種代碼氣味)。

對(duì)于預(yù)編譯頭文件來(lái)說(shuō)也很方便姐直。事實(shí)上倦淀,每個(gè)源文件都包含這些預(yù)編譯的頭文件,這也是前綴頭文件的一個(gè)特點(diǎn)声畏。

這就是事情開始出錯(cuò)的地方......

預(yù)編譯頭文件的存在并不是為了讓你省去打字的麻煩

Apple 的 iOS 項(xiàng)目模板以 Prefix.pch 開始撞叽,其中包括 FoundationUIKit。從編譯速度的角度來(lái)看插龄,這非常合理愿棋。問(wèn)題是,人們注意到了這一點(diǎn)辫狼,并說(shuō):"這些文件已經(jīng)隱含包含了初斑。所以我不需要再次包含它們"。發(fā)現(xiàn)這種副作用后膨处,一些程序員開始向 Prefix.pch 添加更多的頭文件见秤。因?yàn)檫@樣就不用再 #import(導(dǎo)入)了砂竖。

目的從 "盡可能快地編譯這個(gè)項(xiàng)目 "轉(zhuǎn)變?yōu)?"節(jié)省自己的打字時(shí)間"。Stack Overflow 的一個(gè)問(wèn)題就反映了這一點(diǎn)鹃答,它問(wèn)道:"為什么有重復(fù)的#import乎澄?甚至維基百科的前綴詞條也反映了這一不正確的結(jié)論:"因此,沒有必要明確包含上述任何文件"测摔。這種誤解非常普遍置济。

這完全是錯(cuò)誤的。

過(guò)度依賴預(yù)編譯頭文件的四個(gè)問(wèn)題

問(wèn)題在于锋八,要成功編譯一個(gè)文件浙于,僅有成對(duì)的頭文件(.h)和實(shí)現(xiàn)文件(.m)已經(jīng)不夠了。你還需要 Prefix.pch——不是因?yàn)樗鼈兪穷A(yù)編譯的挟纱,而是因?yàn)樗鼈兪请[式包含的羞酗。

"所以呢?"你問(wèn)紊服。"是什么阻礙了你檀轨?"基本上,你最終會(huì)創(chuàng)建不完整的源文件欺嗤。至少有四種方式會(huì)導(dǎo)致問(wèn)題:

1参萄、源文件無(wú)法復(fù)制到不同的項(xiàng)目中

假如你在前綴頭文件中添加了 <QuartzCore/QuartzCore.h>。某個(gè)源文件使用了 QuartzCore煎饼。試著將該源文件復(fù)制到另一個(gè)項(xiàng)目中讹挎。

很有可能無(wú)法編譯,因?yàn)榱硪粋€(gè)項(xiàng)目的預(yù)編譯頭文件不同腺占。你設(shè)法創(chuàng)建了一個(gè)不可移植的源文件淤袜!

2、依賴關(guān)系被隱藏

任何導(dǎo)入其他文件的系統(tǒng)都有一個(gè)好處衰伯,那就是可以顯示文件的依賴關(guān)系。你可以掃描 .h 或 .m 文件的開頭积蔚,看看它還使用了哪些其他文件意鲸。這可以讓你快速了解文件的范圍。

如果你的導(dǎo)入是隱式綁定在前綴頭文件中尽爆,情況就不一樣了怎顾。

3、依賴關(guān)系被掩藏

一個(gè)大型項(xiàng)目可能有大量的預(yù)編譯頭文件漱贱。假設(shè)你正在查看一個(gè)源文件槐雾,并試圖找到它的依賴關(guān)系。你很聰明地意識(shí)到幅狮,早期的程序員依賴預(yù)編譯頭文件來(lái)節(jié)省輸入募强,省略了許多 #import株灸。所以你也查看了前綴文件。

但是擎值,如果 Prefix.pch 中的 #import 語(yǔ)句不只幾條慌烧,你的源文件需要哪些語(yǔ)句?全部鸠儿?不需要屹蚊?一些?哪些进每?

4汹粤、依賴關(guān)系失控

即使將所有 #imports明確化,也很容易產(chǎn)生爆炸性的文件依賴關(guān)系田晚。讓依賴樹保持穩(wěn)定已經(jīng)很不容易了嘱兼。

但是,如果沒有努力做到:
a)使所有 #import 明確化肉瓦;
b)馴服它們遭京,
這些依賴關(guān)系就會(huì)悄無(wú)聲息地發(fā)展到不可收拾的地步。依賴關(guān)系的腐爛會(huì)在不知不覺中蔓延多年泞莉,直到為時(shí)已晚哪雕。突然間,你要開發(fā)一個(gè)新項(xiàng)目鲫趁,卻沒有一種簡(jiǎn)潔的方法來(lái)重用以前的代碼斯嚎,而又不會(huì)把它們都變成大量浪費(fèi)的垃圾。

查找并修復(fù)缺失的 #import

由于 Xcode 將前綴頭文件與預(yù)編譯頭文件結(jié)合在一起的方式挨厚,省略 #import 語(yǔ)句是一種常見的 Objective-C 代碼氣味堡僻。但這是一種不尋常的現(xiàn)象,因?yàn)檫@種氣味本身可能在很長(zhǎng)時(shí)間內(nèi)都不會(huì)被注意到疫剃。(無(wú)聲卻致命6ひ摺)。

要解決問(wèn)題巢价,就必須找到問(wèn)題所在牲阁。而要想找到問(wèn)題,就必須暫時(shí)移除阻嗅器:

  1. 編輯你的前綴文件壤躲。暫時(shí)注釋掉所有 #import#include 語(yǔ)句城菊。(譯者注,PS: 個(gè)人感覺對(duì)于一些明確的基類或者基礎(chǔ)的三方庫(kù)就別注釋了??)
    2碉克、嘗試構(gòu)建您的項(xiàng)目凌唬。你會(huì)立刻發(fā)現(xiàn)問(wèn)題所在。

項(xiàng)目越大漏麦,做第一遍修復(fù)工作所需的時(shí)間就越長(zhǎng)客税。如果您覺得累了癞志,可以把它放在一邊揖闸,稍后再繼續(xù)清理否淤。但我還是希望你能把項(xiàng)目清理干凈审残。明確依賴關(guān)系是減少依賴關(guān)系的重要第一步。

譯自 Jon Reid 的 4 Ways Precompiled Headers Cripple Your Code
侵刪

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酥夭,一起剝皮案震驚了整個(gè)濱河市赐纱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌熬北,老刑警劉巖疙描,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異讶隐,居然都是意外死亡起胰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門巫延,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)效五,“玉大人,你說(shuō)我怎么就攤上這事炉峰∥费” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵疼阔,是天一觀的道長(zhǎng)戒劫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)婆廊,這世上最難降的妖魔是什么迅细? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮淘邻,結(jié)果婚禮上茵典,老公的妹妹穿的比我還像新娘。我一直安慰自己宾舅,他們只是感情好敬尺,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贴浙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪署恍。 梳的紋絲不亂的頭發(fā)上崎溃,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音盯质,去河邊找鬼袁串。 笑死概而,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的囱修。 我是一名探鬼主播赎瑰,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼破镰!你這毒婦竟也來(lái)了餐曼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鲜漩,失蹤者是張志新(化名)和其女友劉穎源譬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孕似,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踩娘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喉祭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片养渴。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖泛烙,靈堂內(nèi)的尸體忽然破棺而出理卑,到底是詐尸還是另有隱情,我是刑警寧澤胶惰,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布傻工,位于F島的核電站,受9級(jí)特大地震影響孵滞,放射性物質(zhì)發(fā)生泄漏中捆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一坊饶、第九天 我趴在偏房一處隱蔽的房頂上張望泄伪。 院中可真熱鬧,春花似錦匿级、人聲如沸蟋滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)津函。三九已至,卻和暖如春孤页,著一層夾襖步出監(jiān)牢的瞬間尔苦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留允坚,地道東北人魂那。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像稠项,于是被迫代替她去往敵國(guó)和親涯雅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容