Tải bản đầy đủ - 0 (trang)
Chapter 21.  Avoid initialization dependencies across compilation units

Chapter 21.  Avoid initialization dependencies across compilation units

Tải bản đầy đủ - 0trang

Summary

Keep(initialization)order:Namespace-levelobjectsindifferent

compilationunitsshouldneverdependoneachotherfor

initialization,becausetheirinitializationorderisundefined.

Doingotherwisecausesheadachesrangingfrommysterious

crasheswhenyoumakesmallchangesinyourprojecttosevere

non-portabilityeventonewreleasesofthesamecompiler.



Discussion

Whenyoudefinetwonamespace-levelobjectsindifferent

compilationunits,whichobject'sconstructoriscalledfirstisnot

defined.Often(butnotalways)yourtoolsmighthappento

initializethemintheorderinwhichthecompilationunits'object

filesarelinked,butthisassumptionisusuallynotreliable;even

whenitdoeshold,youdon'twantthecorrectnessofyourcode

tosubtlydependonyourmakefileorprojectfile.(Formoreon

theevilsoforderdependencies,seealsoItem59.)

Therefore,insidetheinitializationcodeofanynamespace-level

object,youcan'tassumethatanyotherobjectdefinedina

differentcompilationunithasalreadybeeninitialized.These

considerationsapplytodynamicallyinitializedvariablesof

primitivetypes,suchasanamespace-levelboolreg_success

=LibRegister("mylib");

Notethat,evenbeforetheyareeverconstructedusinga

constructor,namespace-levelobjectsarestaticallyinitialized

withallzeroes(asopposedto,say,automaticobjectsthat

initiallycontaingarbage).Paradoxically,thiszero-initialization

canmakebugshardertodetect,becauseinsteadofcrashing

yourprogramswiftlythestaticzero-initializationgivesyouryetuninitializedobjectanappearanceoflegitimacy.You'dthinkthat

thatstringisempty,thatpointerisnull,andthatintegeris

zero,wheninfactnocodeofyourshasbotheredtoinitialize

themyet.

Toavoidthisproblem,avoidnamespace-levelvariables

whereverpossible;theyaredangerous(seeItem10).When

youdoneedsuchavariablethatmightdependuponanother,

considertheSingletondesignpattern;usedcarefully,itmight

avoidimplicitdependenciesbyensuringthatanobjectis

initializeduponfirstaccess.Still,Singletonisaglobalvariable

insheep'sclothing(seeagainItem10),andisbrokenby



mutualorcyclicdependencies(again,zero-initializationonly

addstotheconfusion).



References

[Dewhurst03]Đ55[Gamma95][McConnell93]Đ5.1-4

[Stroustrup00]Đ9.4.1,Đ10.4.9



22.Minimizedefinitionaldependencies.

Avoidcyclicdependencies

Summary

Discussion

Exceptions

References



Summary

Don'tbeover-dependent:Don't#includeadefinitionwhena

forwarddeclarationwilldo.

Don'tbeco-dependent:Cyclicdependenciesoccurwhentwo

modulesdependdirectlyorindirectlyononeanother.Amodule

isacohesiveunitofrelease(seepage103);modulesthatare

interdependentarenotreallyindividualmodules,butsupergluedtogetherintowhat'sreallyalargermodule,alargerunit

ofrelease.Thus,cyclicdependenciesworkagainstmodularity

andareabaneoflargeprojects.Avoidthem.



Discussion

Preferforwarddeclarationsexceptwhereyoureallyneeda

type'sdefinition.YouneedafulldefinitionofaclassCintwo

maincases:

WhenyouneedtoknowthesizeofaCobject:Forexample,

whenallocatingaConthestackorasadirectly-held

memberofanothertype.

WhenyouneedtonameorcallamemberofC:For

example,whencallingamemberfunction.

Inkeepingwiththisbook'scharter,we'llsetasidefromthestart

thosecyclicdependenciesthatcausecompile-timeerrors;

you'vealreadyfixedthembyfollowinggoodadvicepresentin

theliteratureandItem1.Let'sfocusoncyclicdependencies

thatremainincompilablecode,seehowtheytroubleyour

code'squality,andwhatstepsneedbetakentoavoidthem.

Ingeneral,dependenciesandtheircyclesshouldbethoughtof

atmodulelevel.Amoduleisacohesivecollectionofclassesand

functionsreleasedtogether(seeItem5andpage103).Inits

simplestform,acyclicdependencyhastwoclassesthatdirectly

dependuponeachother:

classChild;//breaksthedependencycycle

classParent{//

Child*myChild_;

};

classChild{////possiblyinadifferentheader

Parent*myParent_;

};



ParentandChilddependuponeachother.Thecodecompiles,

butwe'vesetthestageforafundamentalproblem:Thetwo

classesarenotindependentanymore,buthavebecome

interdependent.Thatisnotnecessarilybad,butitshouldonly

occurwhenbotharepartofthesamemodule(developedby

thesamepersonorteamandtestedandreleasedasawhole).

Incontrast,consider:WhatifChilddidnotneedtostorea

backlinktoitsParentobject?ThenChildcouldbereleasedas

itsownseparate,smallermodule(andmaybeunderadifferent

name)intotalindependencefromParentclearlyamoreflexible

design.

Thingsgetonlyworsewhendependencycyclesspanmultiple

modules,whichareallstucktogetherwithdependencyglueto

formasinglemonolithicunitofrelease.That'swhycyclesare

thefiercestenemyofmodularity.

Tobreakcycles,applytheDependencyInversionPrinciple

documentedin[Martin96a]and[Martin00](seealsoItem36):

Don'tmakehigh-levelmodulesdependonlow-levelmodules;

instead,makebothdependonabstractions.Ifyoucandefine

independentabstractclassesforeitherParentorChild,you've

brokenthecycle.Otherwise,youmustcommittomakingthem

partsofthesamemodule.

Aparticularformofdependencythatcertaindesignssufferfrom

istransitivedependencyonderivedclasses,whichoccurswhen

abaseclassdependsonallofitsdescendants,directand

indirect.SomeimplementationsoftheVisitordesignpattern

leadstothiskindofdependency.Suchadependencyis

acceptableonlyforexceptionallystablehierarchies.Otherwise,

youmaywanttochangeyourdesign;forexample,usethe

AcyclicVisitorpattern[Martin98].



Onesymptomofexcessiveinterdependenciesisincremental

buildsthathavetobuildlargepartsoftheprojectinresponse

tolocalchanges.(SeeItem2.)



Exceptions

Cyclesamongclassesarenotnecessarilybadaslongasthe

classesareconsideredpartofthesamemodule,tested

together,andreleasedtogether.Naùveimplementationsofsuch

patternsasCommandandVisitorresultininterfacesthatare

naturallyinterdependent.Theseinterdependenciescanbe

broken,butdoingsorequiresexplicitdesign.



References

[Alexandrescu01]Đ3[Boost][Gamma95][Lakos96]

Đ0.2.1,Đ4.6-14,Đ5[Martin96a][Martin96b][Martin98]

Đ7[Martin00][McConnell93]Đ5[Meyers97]Đ46

[Stroustrup00]Đ24.3.5[Sutter00]Đ26[Sutter02]Đ37

[Sutter03]



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 21.  Avoid initialization dependencies across compilation units

Tải bản đầy đủ ngay(0 tr)

×