原則2:頭文件應(yīng)當(dāng)職責(zé)單一。
說(shuō)明:頭文件過(guò)于復(fù)雜,依賴過(guò)于復(fù)雜是導(dǎo)致編譯時(shí)間過(guò)長(zhǎng)的主要原因。很多現(xiàn)有代碼中頭文件過(guò)大,職責(zé)過(guò)多, 再加上循環(huán)依賴的問(wèn)題,可能導(dǎo)致為了在.c中使用一個(gè)宏,而包含十幾個(gè)頭文件。
某個(gè)頭文件不但定義了基本數(shù)據(jù)類型WORD,還包含了stdio.h syslib.h等等不常用的頭文件。
如果工程中有10000個(gè)源文件,而其中100個(gè)源文件使用了stdio.h的printf,由于上述頭文件的職責(zé)過(guò)于龐大,而WORD又是每一個(gè)文件必須包含的,從而導(dǎo)致stdio.h/syslib.h等可能被不必要的展開(kāi)了9900次,大大增加了工程的編譯時(shí)間。
原則3:頭文件應(yīng)向穩(wěn)定的方向包含。
說(shuō)明:頭文件的包含關(guān)系是一種依賴,一般來(lái)說(shuō),應(yīng)當(dāng)讓不穩(wěn)定的模塊依賴穩(wěn)定的模塊,從而當(dāng)不穩(wěn)定的模塊發(fā)生變化時(shí),不會(huì)影響(編譯)穩(wěn)定的模塊。
就我們的產(chǎn)品來(lái)說(shuō),依賴的方向應(yīng)該是:產(chǎn)品依賴于平臺(tái),平臺(tái)依賴于標(biāo)準(zhǔn)庫(kù)。某產(chǎn)品線平臺(tái)的代碼中已經(jīng)包含了產(chǎn)品的頭文件,導(dǎo)致平臺(tái)無(wú)法單獨(dú)編譯、發(fā)布和測(cè)試, 是一個(gè)非常糟糕的反例。
除了不穩(wěn)定的模塊依賴于穩(wěn)定的模塊外,更好的方式是兩個(gè)模塊共同依賴于接口,這樣任何一個(gè)模塊的內(nèi)部實(shí)現(xiàn)更改都不需要重新編譯另外一個(gè)模塊。在這里,我們假設(shè)接口本身是最穩(wěn)定的。
延伸閱讀材料:編者推薦開(kāi)發(fā)人員使用“依賴倒置”原則,即由使用者制定接口,服務(wù)提供者實(shí)現(xiàn)接口,更具體的描述可以參見(jiàn)《 敏捷軟件開(kāi)發(fā):原則、模式與實(shí)踐》 ( Robert C.Martin 著 鄧輝 譯 出版社2003年9月) 的第二部分“敏捷設(shè)計(jì)”章節(jié)。
規(guī)則1:每一個(gè).c文件應(yīng)有一個(gè)同名.件,用于聲明需要對(duì)外公開(kāi)的接口。
說(shuō)明:如果一個(gè).c文件不需要對(duì)外公布任何接口,則其就不應(yīng)當(dāng)存在,除非它是程序的入口,如main函數(shù)所在的文件。
現(xiàn)有某些產(chǎn)品中,習(xí)慣一個(gè).c文件對(duì)應(yīng)兩個(gè)頭文件,一個(gè)用于存放對(duì)外公開(kāi)的接口,一個(gè)用于存放內(nèi)部需要用到的定義、聲明等,以控制.c文件的代碼行數(shù)。編者不提倡這種風(fēng)格。
這種風(fēng)格的根源在于源文件過(guò)大,應(yīng)首先考慮拆分.c文件,使之不至于太大。另外,一旦把私有定義、聲明放到獨(dú)立的頭文件中,就無(wú)法從技術(shù)上避免別人include之,難以保證這些定義最后真的只是私有的。
本規(guī)則反過(guò)來(lái)并不一定成立。有些特別簡(jiǎn)單的頭文件,如命令I(lǐng)D定義頭文件,不需要有對(duì)應(yīng)的.c存在[a1] 。
示例:對(duì)于如下場(chǎng)景,如在一個(gè).c中存在函數(shù)調(diào)用關(guān)系:
void foo() { bar(); } void bar() { Do something; }
必須在foo之前聲明bar,否則會(huì)導(dǎo)致編譯錯(cuò)誤。
這一類的函數(shù)聲明,應(yīng)當(dāng)在.c的頭部聲明,并聲明為static的,如下:
static void bar(); void foo() { bar(); } void bar() { Do something; }
規(guī)則2:禁止頭文件循環(huán)依賴。
說(shuō)明:頭文件循環(huán)依賴,指a.h包含b.h, b.h包含c.h, c.h包含a.h之類導(dǎo)致任何一個(gè)頭文件修改,都導(dǎo)致所有包含了a.h/b.h/c.h的代碼全部重新編譯一遍。
而如果是單向依賴,如a.h包含b.h, b.h包含c.h,而c.h不包含任何頭文件,則修改a.h不會(huì)導(dǎo)致包含了b.h/c.h的源代碼重新編譯。
規(guī)則3:.c/.件禁止包含用不到的頭文件。
說(shuō)明:很多系統(tǒng)中頭文件包含關(guān)系復(fù)雜,開(kāi)發(fā)人員為了省事起見(jiàn),可能不會(huì)去一一鉆研,直接包含一切想到的頭文件,甚至有些產(chǎn)品干脆發(fā)布了一個(gè)god.h,其中包含了所有頭文件,然后發(fā)布給各個(gè)項(xiàng)目組使用,這種只圖一時(shí)省事的做法,導(dǎo)致整個(gè)系統(tǒng)的編譯時(shí)間進(jìn)一步惡化,并對(duì)后來(lái)人的維護(hù)造成了巨大的麻煩。
Lenze 5/7132/23250
SIEMENS 6FM1-726-3BA00 USPP 6FM17263BA00
ALLEN BRADLEY 1336E-B050-AE-EN-HA2-L8E NSFP 1336EB050AE
SIEMENS 6FM1-470-3CA25 USPP 6FM14703CA25
SIEMENS 6ES5-188-3UA12 NSFP 6ES51883UA12
SIEMENS 6FM1-726-3AA00 USPP 6FM17263AA00
GE FANUC IC752WTD802 USPP IC752WTD802
AVTRON AFS110-4CN0-C USPP AFS1104CN0C
ALLEN BRADLEY 1336-B125-E0H USPP 1336B125E0H
ALLEN BRADLEY 2711E-K10C6 NSFP 2711EK10C6
ALLEN BRADLEY 1785-L46B USPP 1785L46B
ALLEN BRADLEY 150-B180NBDB NSFP 150B180NBDB
ALLEN BRADLEY 1333-HAA USPP 1333HAA
ADEPT TECH 90400-11140/XY-HRS-140AH404 USPP 9040011140X
FANUC A06B-6044-H008 USPP A06B6044H008
ALLEN BRADLEY 1336VT-B060-EOS-L3-S1 USPP 1336VTB060EOSL
TB WOODS UVC-4040-0H USPP UVC40400H
SANYO DENKI B21M1K7MXR10 USPP B21M1K7MXR10
SANYO DENKI B21M1K7MXR10-B USPP B21M1K7MXR10B
ORMEC MAC-A110F/KIA USPP MACA110FKIA
ALLEN BRADLEY 1774-LP3 NSFP 1774LP3
COGNEX VM16A-203-0075-RB USPP VM16A2030075RB
MODICON AS-584L-211 USPP AS584L211
NEMATRON CORP IWS5826 USPP IWS5826
CUTLER HAMMER DT367URK NSPP DT367URK
ALLEN BRADLEY 6500-PS7DSP NSPP 6500PS7DSP
DVT DVT550 NSPP DVT550
ISSC 6271002RC NSFP 6271002RC
ASEA BROWN BOVERI GNT2009473R0100 NSFP GNT2009473R0100
SIEMENS 6SE3221-3DC40 USPP 6SE32213DC40
INDRAMAT MAC112C-0-ED-4-C/130-A-0/WI520LV/S005 USPP MAC
ALLEN BRADLEY 150-B180NBDB-8L USPP 150B180NBDB8L
SIEMENS 6SE9-221-3DC40 USPP 6SE92213DC40
ALLEN BRADLEY 1394C-SJT05-C-RL USPP 1394CSJT05CRL
BOSCH 1070080125 USPP 1070080125
ALLEN BRADLEY 6180-FLIEHLHTJEZ USPP 6180FLIEHLHTJEZ
MODICON AS-506P-F32 NSFP AS506PF32
ALLEN BRADLEY 1336-B075-EOH-FA2-L3-S1 USPP 1336B075EOHF
MARPOSS 3413024000 NSPP 3413024000
RELIANCE ELECTRIC 803456-21T NSPP 80345621T
ASEA BROWN BOVERI ACS601-0140-S00B1200901 USPP ACS60101
TELEDYNE M300E NSFP M300E
WESTINGHOUSE 11-210K5RCNA USPP 11210K5RCNA
ALLEN BRADLEY 1336VT-B040-EAR-FA2-L3-S1 USPP 1336VTB040
SIEMENS 6SE3-221-7FG40 NSFP 6SE32217FG40
SIEMENS NXD63S120A USPP NXD63S120A
SIEMENS 6AV7-612-0AB12-0BJ0 NSFP 6AV76120AB120BJ0
MOORE PRODUCTS 39ACM24BAN USPP 39ACM24BAN
ASEA BROWN BOVERI DPH-07551 NSFP DPH07551
ALLEN BRADLEY 2750-AHD NSPP 2750AHD
ALLEN BRADLEY 8510-AA22-A2 USPP 8510AA22A2
EUROTHERM DRIVES 590C/0350/9/1/0 USPP 590C0350910
ALLEN BRADLEY 506309 NSPP 506309
ORMEC GN3-40/2MI USPP GN3402MI
WESTINGHOUSE NCMZ-1799 NSFP NCMZ1799
MODICON AM-M909-002 USPP AMM909002
MODICON AM-M909-022 USPP AMM909022
ALLEN BRADLEY 1772-ME8 USPP 1772ME8
SIEMENS PXD63B140H NSFP PXD63B140H
ENERDYNE DEC2000R2 USPP DEC2000R2
YAMATAKE 80360147-001 USPP 80360147001
SIEMENS 6ES7-626-2AG01-0AE3 USPP 6ES76262AG010AE3
MITSUBISHI SJ-V60-01 NSFP SJV6001
ACCURAY 069829-002 NSPP 069829002
SIEMENS 6ES5-944-7UB21 USPP 6ES59447UB21
BAUMULLER BUM62F-75/975-54-M-041 USPP BUM62F7597554M04
MOTOMAN ROBOTICS USAFED-09-YR21 NSFP USAFED09YR21
SICK OPTIC ELECTRONIC LMS211-30206 NSFP LMS21130206
ALLEN BRADLEY 1785-L80C15 NSPP 1785L80C15
INDRAMAT TRANS-01-109-468-4800 USPP TRANS01109468480
SYMAX 8010-SFW401 NSFP 8010SFW401
INDRAMAT TRANS-01.00 USPP TRANS0100
INDRAMAT TRANS-01.1 USPP TRANS011
INDRAMAT TRANS-01.3 USPP TRANS013
ORBISPHERE 26062 USPP 26062
TRICONEX 3005 USPP 3005
ALLEN BRADLEY 1785-L80C15/F USPP 1785L80C15F
FANUC A06B-0308-B101 USPP A06B0308B101
GENERIC AUTOMATION AMSI-100H-090E-600C-1FNB-H0701 NSPP
GENERAL ELECTRIC DS3815PMMA1F1B USPP DS3815PMMA1F1B
ALLEN BRADLEY 1756-L55M16 NSFP 1756L55M16
FISHER ROSEMOUNT DM6004X1-EA2 NSFP DM6004X1EA2
INDRAMAT KDA1.1-100-300-W1/220 NSFP KDA11100300W1220
ASEA BROWN BOVERI DSQC-115 USPP DSQC115
HONEYWELL 1858-T790G USPP 1858T790G
HONEYWELL 1858-T79H0 USPP 1858T79H0
SIEMENS 1GL5166-0WX446HU7-Z USPP 1GL51660WX446HU7
ASEA BROWN BOVERI YB161102-BS USPP YB161102BS
SIEMENS 6SE3-121-7DG40 NSFP 6SE31217DG40
SIEMENS 6SE9-221-0DC40 NSFP 6SE92210DC40
RELIANCE ELECTRIC 65C-500 USPP 65C500
MODICON AS-D004-030 USPP ASD004030
MODICON AS-D004-040 USPP ASD004040
STANDARD RADIO B36500-00-01-0 USPP B3650000010
ALLEN BRADLEY 143679 USPP 143679
RAYTHEON B36500-0001 USPP B365000001
RELIANCE ELECTRIC 300P4171 USPP 300P4171
FANUC A06B-0760-B204/3000 USPP A06B0760B2043000
TELEMECANIQUE TSX-RAM-51216 NSFP TSXRAM51216
SYMAX 8030-CRM-580 USPP 8030CRM580
SIEMENS 6RA2-477-6GV62-0 USPP 6RA24776GV620
COMPUMOTOR DR-1400A60 USPP DR1400A60
ALLEN BRADLEY 1747-L553P NSFP 1747L553P
ALLEN BRADLEY 20DD125A0NYNAECNE USPP 20DD125A0NYNAECN
MODICON 554-VIC-157-60 NSPP 554VIC15760
INDUSTRIAL COMPUTER 8600-RE/SB386SX/AT-40MB NSFP 8600RE
ALLEN BRADLEY 1785-V30B NSFP 1785V30B
NEC C-526 USPP C526
YASKAWA ELECTRIC UAACLA-37AA2K USPP UAACLA37AA2K
ALLEN BRADLEY 1775-SR5 NSPP 1775SR5
RELIANCE ELECTRIC 45C-340 USPP 45C340
INDRAMAT TDM1.4-100-300-W1 USPP TDM14100300W1
ALLEN BRADLEY 8520-1S5A-BAT-EX4-T1-Y-4-5-7 USPP 85201S5
ALLEN BRADLEY 8520-3S5A-BAT-EX4-S-1-2-3 USPP 85203S5ABA
BOSCH 1070081259-100 USPP 1070081259100
BOSCH 1070081259-102 USPP 1070081259102
ASEA BROWN BOVERI HIEE300115R1 NSFP HIEE300115R1
SIEMENS 6ES5-243-1BA11 USPP 6ES52431BA11
GETTYS 110-235 NSFP 110235
RELIANCE ELECTRIC DSA-MTR-60D NSPP DSAMTR60D
SQUARE D ME36800LS1021 USPP ME36800LS1021
OKUMA 1006-1262-16-010 USPP 1006126216010
OKUMA 1006-1262-47-008 USPP 1006126247008
OKUMA 1006-1262-91-004 USPP 1006126291004
AVTRON AFS056-4CNO-C USPP AFS0564CNOC
MODICON AS-506P-F32 NSPP AS506PF32
ALLEN BRADLEY 1395-B69-C1-P51-X1 USPP 1395B69C1P51X1
CINCINNATI MILACRON 3-700-0282A USPP 37000282A
MODICON MHDA1198N00 NSPP MHDA1198N00
INDRAMAT DSC3.1-150-115 USPP DSC31150115
ALLEN BRADLEY 1336VT-B050-EAS-FA2-L1 USPP 1336VTB050EAS
HORIBA FIA-23A USPP FIA23A
OMRON CFP0269 NSFP CFP0269
ORMEC GN3-20/2MCI USPP GN3202MCI
SQUARE D ME36500LS USPP ME36500LS
GE FANUC IC3606SPCC1D USPP IC3606SPCC1D
GE FANUC IC3606SPCC1H USPP IC3606SPCC1H