[分享] Include What You Use

作者: lc85301 (pomelocandy)   2020-10-31 11:16:24
最近用了 include-what-you-use 這個工具,分享一下
https://yodalee.me/2020/10/2020_iwyu/
大家都知道,程式不是寫完就算了,是會長大跟更新
這時候 include 就會慢慢過時,可能本來需要的 include 現在不需要了
但通常在改程式碼時不會意識到這點
如果參考 Google 的 cpp coding guide,會看到 Include What You Use 這條準則:
If a source or header file refers to a symbol defined elsewhere, the file
should directly include a header file which properly intends to provide a
declaration or definition of that symbol. It should not include header files
for any other reason.
原始碼檔案和標頭檔所需的符號,都應該引入適當的標頭檔來提供宣告或定義;
不能因為其他理由而引入標頭檔。
Do not rely on transitive inclusions. This allows people to remove
no-longer-needed #include statements from their headers without breaking
clients. This also applies to related headers - foo.cc should include bar.h
if it uses a symbol from it even if foo.h includes bar.h.
不可依賴過渡引入。開發者可以隨時移除不需要的引入,又不會破壞客戶端的相依性;
這也適用於相關的標頭檔:即使 foo.h 已經引入 bar.h,foo.cc 還是要引入 bar.h 。
作者: dces4212 (flawless)   2020-10-31 15:33:00
作者: sarafciel (Cattuz)   2020-10-31 16:06:00
作者: james732 (好人超)   2020-11-01 15:09:00
作者: loveme00835 (髮箍)   2020-11-01 15:46:00
從軟體架構的品質屬性 (Quality Attributes) 來看,如果你改了扣, 卻不知道應該要引入哪些標頭檔, 不會很雷嗎? coding standard 只能告訴你結果, 為了確保這個結果, 其實人員的教育/訓練才是最重要的; 而不是透過工具來把訓練不足的問題掩蓋下來, 這也會衍生其他問題
作者: firejox (Tangent)   2020-11-01 19:19:00
發現人會疏漏的問題就是CI的工作了
作者: loveme00835 (髮箍)   2020-11-01 19:23:00
找錯誤是 testing 在做的事情
作者: firejox (Tangent)   2020-11-01 19:29:00
@@ 找違反coding standard也算testing喔
作者: lc85301 (pomelocandy)   2020-11-01 19:53:00
所以說這個工具就是要丟給 CI 去跑的呀
作者: loveme00835 (髮箍)   2020-11-01 20:06:00
我的意思是 iwyu 應該單純作為 testing/diagnostic tool, 就像 clang-tidy等, 但是找出錯誤時應該是由人類來修正, 並且要有明確的回報機制. fix_include 不應該放進開發流程, 因為我們無法從最後的程式碼看出它和人員素質之間的關係
作者: lc85301 (pomelocandy)   2020-11-01 20:34:00
可以接受我的使用結果,iwyu 在解完 include 之後還是會有錯
作者: CoNsTaR ((const *))   2020-11-01 23:14:00
程式語言都不要 typecheck 好了,寫 type safe 的程式是人類的工作,不該由機器來做,typechecking 是測試在做的事人員的教育訓練才是最重要的
作者: descent (「雄辯是銀,沉默是金」)   2020-11-02 10:03:00
感謝分享
作者: chuegou (chuegou)   2020-11-02 11:13:00
同意推文 類似變數宣告了沒用會跳warning這樣我比較喜歡
作者: hsnuconan (☁☁☁)   2020-11-04 10:09:00
所以過度引入會有什麼副作用嗎? compile過慢嗎?
作者: Killercat (殺人貓™)   2020-11-04 11:26:00
compile三級跳的慢 因為這是連鎖反應另外雖然多半肇因於設計錯誤,但是名稱空間衝突機會也會變大,當你用兩個3rd party的.h裡面的include還互相衝突的時候你真的會欲哭無淚 要改都沒辦法改
作者: LPH66 (-6.2598534e+18f)   2020-11-04 11:33:00
簡單觀念: #include 是編譯器幫你剪貼標頭檔在引入處所以 #include 越多最後編譯時要看的東西就越多那編譯過程中編譯器需要記錄搜尋判斷的東西就越多
作者: ucrxzero (RX-0)   2020-11-04 12:48:00
所有的MACRO 包括include 不是都是展開的概念嗎跟inline 的差別在於inline是編譯器做的是真的函式而preprocessing是text的代換而已Preprocessing->編譯->處理inline補充一下 inline 有自己的scope 較穩定
作者: MOONRAKER (㊣牛鶴鰻毛人)   2020-11-05 16:04:00
阿展開以後compiler不用看過喔 那這個compiler太妙了不用看就可以變出來bin 妙不可言
作者: ucrxzero (RX-0)   2020-11-05 16:46:00
當然要看我又沒有說不用看但不穩定是因為還要加類似do{}while(0)這種東西*MACRO
作者: Lipraxde (Lipraxde)   2020-11-05 18:55:00
我在思考這裡是怎麼談到 inline 的...
作者: eye5002003 (下一夜)   2020-11-06 09:07:00
GCC能幫我列出沒被使用的函式,也許以後還能幫忙抓沒被使用的標頭檔,不過如果你很在乎編譯時間長短的話那還是要親手整理,把標頭檔藏好別到處引用
作者: ucrxzero (RX-0)   2020-11-06 10:13:00
像static 就不會被剪貼進去啊
作者: loveme00835 (髮箍)   2020-11-06 10:19:00
笑死..
作者: ucrxzero (RX-0)   2020-11-06 10:37:00
...
作者: firejox (Tangent)   2020-11-06 12:41:00
inline 只是 inline it if you can ,又沒強制如果 static不會剪貼,那 static inline 又是什麼
作者: CoNsTaR ((const *))   2020-11-06 12:51:00
include 不就單純的剪貼嗎?還會管你是不是 static 喔?語法分析可能都還沒開始,不可能管到語意去吧...
作者: ucrxzero (RX-0)   2020-11-06 13:01:00
好喔最初應該會啦 但你也用不了喔喔我懂你意思了我是說在其他source檔定義static同名一起include header的其他source抓不到那個被定義static的symbol但如果你一開始就把static function 寫在header那當然都可以用 但是你每個source 檔自己定義都是分開的這樣沒錯吧?text剪貼當然是預處理而已
作者: CoNsTaR ((const *))   2020-11-06 13:15:00
呃... 不論某個 symbol 是不是 static、或它被從哪裡 include 到哪裡、或 scope 是什麼 etc...,它被 include 進來就是會增加編譯器的工作,就可能會導致編譯速度變慢,就這樣而已...
作者: ucrxzero (RX-0)   2020-11-06 13:20:00
我用詞錯誤啦 我講到編譯的地方去了不要再鞭了更正 講到連結的地方去了
作者: loveme00835 (髮箍)   2020-11-06 13:22:00
就跟你說從結果論來學習是錯的方法, 買一本書好好把它看完, 沒看完別來誤導其他人
作者: CoNsTaR ((const *))   2020-11-06 13:24:00
沒有要鞭,看了就忍不住想講orz
作者: ucrxzero (RX-0)   2020-11-06 13:28:00
沒錯,這裡傳道授業的地方講話不能太籠統可能會讓人搞混 我剛剛剪貼是講最後的連結的地方不會被連結而不是引用的時候不會被剪貼我略過太多而且用詞不精大家我先去看書明年見看講話的藝術
作者: descent (「雄辯是銀,沉默是金」)   2020-11-06 18:06:00
ucrxzero: 討論就是這樣, 不用太在意
作者: Killercat (殺人貓™)   2020-11-10 07:42:00
我能給的建議是,不要急著發表意見先把想說的在腦袋裡面順一次 想想要不要發表 再寫不過這篇居然沒有人把pImpl拖出來 真令人意外XD
作者: LPH66 (-6.2598534e+18f)   2020-11-10 08:30:00
(離題) 這其實是推文成章的壞處之一: 發完出去了就沒得改(再拉回來) 這麼一提我才發現 pImpl 好像和這段 guide 之間有些微妙的互動...
作者: Lipraxde (Lipraxde)   2020-11-10 08:53:00
Pimpl 在 header 應該沒有用到 impl class 底下的 symbol,應該還好?
作者: Killercat (殺人貓™)   2020-11-10 14:51:00
基本上這條guide就是給沒用pimpl的code補救的方案之一你真的寫成pimpl 這東西應該沒辦法再優化了....就全部被凝縮成一個opaque pointer是還能怎麼最佳化XD應該說 還是能拿掉用不到的header啦 但效果不明顯了
作者: Lipraxde (Lipraxde)   2020-11-10 20:16:00
我是覺得 pimpl 和這條 guide 兩者是獨立的
作者: Killercat (殺人貓™)   2020-11-10 22:39:00
是沒錯,不過要是使用pimpl的話,絕大多數的redundentheader都會在.cpp而不在.h 這條guide最佳化就很有限了
作者: Lipraxde (Lipraxde)   2020-11-10 23:42:00
這條 guide 應該是要人們避免 transitive include,讓人可以安心的拿掉不用的 header。編譯速度有機會變快應該算是屬於附加的,並不是本來的目的。而使用 pimpl 的其中一個目的是可以讓人修改 impl 時不用改到 header,可以避免重新編譯其他 .cpp。就這樣我覺得 pimpl 跟這條 guide 不衝突也不相關。
作者: mickey94378 (Holy)   2020-12-07 20:54:00
推分享

Links booklink

Contact Us: admin [ a t ] ucptt.com