Upload
others
View
16
Download
0
Embed Size (px)
Citation preview
IntroductiontoSoftwareTechnologySoftwareQuality
KlausOstermann
SomeslidesonrefactoringadaptedfromCS246courseatUWaterloo
EinführungindieSoftwaretechnik1
SoftwareQuality
EinführungindieSoftwaretechnik2
} Howcanwemaintainorimprovethequalityofsoftware?
} Whatissoftwarequality,anyway?} Correctimplementationofrequirementsspecification} Designquality,modularity
} Extensibility,Maintainability,Understandability,Readability,Reusability…
} Robustnesstochange} LowCoupling,HighCohesion
} Reliability,FaultTolerance,Testability,Performance,…
SoftwareQuality
EinführungindieSoftwaretechnik3
} Howcanwemeasuresoftwarequality?
} Whataboutsoftwaremetrics?Whatisasoftwaremetric?
“Youcan’tcontrolwhatyoucan'tmeasure”TomDeMarco,1986
Measurementistheempirical,objectiveassignmentofnumbers,accordingtoarulederivedfromamodelor
theory,toattributesofobjectsoreventswiththeintentofdescribingthem.
Kaner&Cem,“SoftwareEngineerMetrics:Whatdotheymeasureandhowdoweknow?”
ExamplesofSoftwareMetrics
EinführungindieSoftwaretechnik4
} LinesofCode(LoC)} Bugsperlineofcode} Commentdensity} Cyclomaticcomplexity
} measuresthenumberoflinearlyindependentpathsthroughaprogram'ssourcecode
} Halsteadcomplexitymeasures} Derivesoftwarecomplexityfromnumbersof(distinct)operandsand
operators} Programexecutiontime} TestCoverage} Numberofclassesandinterfaces} Abstractness=ratioofabstractclassestototalnumberofclasses} …
Metricsarerarelyused
EinführungindieSoftwaretechnik5
} Fewcompaniesestablishmeasurementprograms,evenfewersucceedwiththem
} ThosethatusemetricsoftendosoonlytoconformtocriteriaestablishedincertainqualitystandardssuchasCMM} seeN.E.Fenton,"SoftwareMetrics:Successes,Failures&New
Directions”,1999
} Onecouldinterpretthisasevidenceoftheimmaturityandunprofessionalismofthefield} Aren’ttheengineerssosuccessfulbecausetheycanmeasure
quality?} Butthisisagainthemisleading“softwareasengineeringproduct”
analogythatwasalreadyrefutedinthefirstlectureofthiscourse
Metricsarerarelyuseduseful!
EinführungindieSoftwaretechnik6
} Formallydefinedmetricsareobjective,butwhatdothesemeasurementsmean?} Whatcanweconcludeaboutqualityifthecyclomaticcomplexityofourcodeis12?
} Answer:Nothing.
} Problem:Oftenunclearwhetherthemetriccorrelatestoanyusefulqualityfactor} Similartotheattemptofmeasuringtheintelligenceofapersonintermsoftheweightorcircumferenceofthebrain
} Ifafuturepotentialemployertellsyouabouttheirextensivesoftwaremetricssuite,run!J
TomDeMarco23yearslater…
EinführungindieSoftwaretechnik7
“Thebook’smostquotedlineisitsfirstsentence:“Youcan’tcontrolwhatyoucan’tmeasure.”Thislinecontainsarealtruth,butI’vebecomeincreasinglyuncomfortablewithmyuseofit.Implicitinthequoteisthatcontrolisanimportantaspect,maybethemostimportant,ofanysoftwareproject.Butitisn’t.Manyprojectshaveproceededwithoutmuchcontrolbutmanagedtoproducewonderfulproducts.”TomDeMarco,“SoftwareEngineering:AnIdeaWhoseTimeHasComeandGone”,2009.
SoftwareQuality
EinführungindieSoftwaretechnik8
} Ifmetricsdon’twork,howdoweassessthequalityofsoftware?
} Answer:Byacase-by-caseanalysisofeachindividualsoftwareproject} Reasonaboutdesignquality,extensibility,…} Reasonbycomparingtodesignsthathaveprovenuseful
} Designpatternsetc.
} Reasonbylookingfor“codesmells”andanti-patterns} Byextensivetestsuites} Byusinganalysistools:Staticanalysis,dynamicanalysis,formalverification
CodeSmells
EinführungindieSoftwaretechnik9
} Codesmell:Anysymptominthecodeofaprogramthatpossiblyindicatesadeeperproblem} TermpopularizedbyKentBeckinhis“Refactoring”book
} Commoncodesmells} Duplicatedcode} Longmethod,Largeclass} Featureenvy,inappropriateintimacy} Contrivedcomplexity
Anti-Pattern
EinführungindieSoftwaretechnik10
} Ananti-patternisapatternthatmaybecommonlyusedbutisineffectiveand/orcounterproductiveinpractice.
} Adescriptionofanti-patternsisuseful} Onecanrecognizetheforcesthatleadtotheirrepetitionandlearnhowothershaverefactoredthemselvesoutofthesebrokenpatterns.
} Examples:} Actionatadistance:Unexpectedinteractionbetweenotherwiseseparatedpartsofasystem
} Sequentialcoupling:Aclassthatrequiresitsmethodstobecalledinaparticularorder
} Circulardependency:Unnecessarydirectorindirectmutualdependenciesbetweensoftwaremodules
Anti-Pattern
EinführungindieSoftwaretechnik11
} MoreExamples:} AbstractionInversion:Re-implementlow-levelfunctionsusinghigh-levelfunctions
} Interfacebloat:Makinganinterfacesopowerfulthatitistoohardtoimplement
} Busyspinorbusywaiting:ConsumingCPUwhilewaitingforsomethingtohappen
} Seehttp://c2.com/cgi/wiki?AntiPatternsCatalogforanextensiveoverviewovercommonantipatterns
Whattodoaboutanti-patternsandcodesmells?
EinführungindieSoftwaretechnik12
} Refactoringsformalizetheideatosystematicallyremoveanti-patternsandcodesmells} Oftenformalizedtoadegreethatitcanbeautomatedintheformof
anIDEtool} Standardreference:à} Refactoringscanoftenbeunderstoodtoimprovethemodularityofthecode
} Refactoringsdonotchangethebehaviorofcode,e.g.,addafeature
} Let’slookatsomesmellsandassociatedrefactoringsinmoredetail!
Badsmellsandassociatedrefactorings
EinführungindieSoftwaretechnik13
} Duplicatedcode–“The#1badsmell”} Wehavealreadydiscussedhowtoabstractoverdifferentformsofduplicatedcodeinthelectureonreuse
} Sameexpressionintwomethodsinthesameclass?} Makeitaprivateauxiliaryroutineandparameterizeit
(Extract method refactoring)
} Samecodeintworelatedclasses?} Pushcommonalitiesintoclosestmutualancestorandparameterize} UsetemplatemethodDPforvariationinsubtasks
(Form template method refactoring)
Badsmellsandassociatedrefactorings
14
} Duplicatedcode} Samecodeintwounrelatedclasses?
} Oughttheyberelated?¨ Introduceabstractparent(Extract class, Pull up method)
} Doesthecodereallybelongtojustoneclass?¨ Maketheotherclassintoaclient(Extract method)
} Canyouseparateoutthecommonalitiesintoasubpartorotherfunctionobject?¨ Makethemethodintoasubobjectofbothclasses.¨ StrategyDPallowsforpolymorphicvariationofmethods-as-objects
(Replace method with method object) = apply strategy pattern
ExtractClassRefactoring
EinführungindieSoftwaretechnik15
You have one class doing work that should be done by two. Create a new class and move the relevant fields and methods from the
old class into the new class.
Pull-UpMethodRefactoring
EinführungindieSoftwaretechnik16
You have methods with identical results on subclasses. Move them to the superclass
ExtractMethod Refactoring
EinführungindieSoftwaretechnik17
void printOwing() { printBanner(); //print details System.out.println ("name: " + _name); System.out.println ("amount " + getOutstanding()); }
void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails (double outstanding) { System.out.println ("name: " + _name); System.out.println ("amount " + outstanding); }
You have a code fragment that can be grouped together. Turn the fragment into a method whose name explains the purpose of the method.
18
Badsmellsincode
} Long method } Oftenasignof:
} Tryingtodotoomanythings} Poorlythoughtoutabstractionsandboundaries
} Besttothinkcarefullyaboutthemajortasksandhowtheyinter-relate.Beaggressive!} Breakupintosmallerprivatemethodswithintheclass
(Extract method) } Delegatesubtaskstosubobjectsthat“knowbest”(i.e.,templatemethodDP)(Extract class/method, Replace data value with object)
ReplaceDataValuewithObjectRefactoring
EinführungindieSoftwaretechnik19
You have a data item that needs additional data or behavior. Turn the data item into an object.
20
Badsmellsincode
} Long method } Fowler’sheuristic:
} Whenyouseeacomment,makeamethod.} Often,acommentindicates:
¨ Thenextmajorstep¨ Somethingnon-obviouswhosedetailsdetractfromtheclarityoftheroutineasawhole.
} Ineithercase,thisisagoodspotto“breakitup”.
21
Badsmellsincode} Large class
} i.e.,toomanydifferentsubpartsandmethods} Twostepsolution:
1. Gatherupthelittlepiecesintoaggregatesubparts.(Extract class, replace data value with object)
2. Delegatemethodstothenewsubparts.(Extract method)
} Likely,you’llnoticesomeunnecessarysubpartsthathavebeenhidingintheforest!
} Resisttheurgetomicromanagethesubparts!
22
Badsmellsincode
} Large class } Counterexample:
} Libraryclassesoftenhavelarge,fatinterfaces(manymethods,manyparameters,lotsofoverloading)¨ Ifthemanymethodsexistforthepurposeofflexibility,that’s
OKinalibraryclass.
23
Badsmellsincode
} Long parameter list } Longparameterlistsmakemethodsdifficultfor
clientstounderstand} Thisisoftenasymptomof
} Tryingtodotoomuch} …toofarfromhome} …withtoomanydisparatesubparts
"ifyourprocedurehasmorethanabouthalfadozenparameters,youprobablyforgotafew.“–AlanPerlis
24
Badsmellsincode
} Long parameter list } Intheolddays,structuredprogrammingtaught
theuseofparameterizationasacureforglobalvariables.} Withmodules/OOP,objectshavemini-islandsof
statethatcanbereasonablytreatedas“global”tothemethods(yetarestillhiddenfromtherestoftheprogram).
} i.e.,Youdon’tneedtopassasubpartofyourselfasaparametertooneofyourownmethods.
25
Badsmellsincode} Long parameter list
} Solution:} Tryingtodotoomuch?
¨ Breakupintosub-tasks(Extract method)
} …toofarfromhome?¨ Localizepassingofparameters;don’tjustpassdownseverallayers
ofcalls(Preserve whole object, introduce parameter object)
} …withtoomanydisparatesubparts?¨ Gatherupparametersintoaggregatesubparts¨ Yourmethodinterfaceswillbemucheasiertounderstand!
(Preserve whole object, introduce parameter object)
PreserveWholeObjectRefactoring
EinführungindieSoftwaretechnik26
int low = daysTempRange().getLow(); int high = daysTempRange().getHigh(); withinPlan = plan.withinRange(low, high);
withinPlan = plan.withinRange(daysTempRange());
You are getting several values from an object and passing these values as parameters in a method call.
Send the whole object instead.
IntroduceParameterObjectRefactoring
EinführungindieSoftwaretechnik27
You have a group of parameters that naturally go together. Replace them with an object.
28
Badsmellsincode
} Divergent change } Occurswhenoneclassiscommonlychangedindifferentwaysfor
differentreasons} Likely,thisclassistryingtodotoomuchandcontainstoomany
unrelatedsubparts} Overtime,someclassesdevelopa“Godcomplex”
} Theyacquiresdetails/ownershipofsubpartsthatrightlybelongelsewhere
} Thisisasignofpoorcohesion} Unrelatedelementsinthesamecontainer
} Solution:} Breakitup,reshuffle,reconsiderrelationshipsandresponsibilities
(Extract class)
29
Badsmellsincode} Shotgun surgery
} …theoppositeofdivergentchange} Eachtimeyouwanttomakeasingle,seeminglycoherent
change,youhavetochangelotsofclassesinlittleways
} Alsoaclassicsignofpoorcohesion} Relatedelementsarenotinthesamecontainer!
} Solution:} Looktodosomegathering,eitherinaneworexistingclass.
(Move method/field)
MoveMethodRefactoring
EinführungindieSoftwaretechnik30
A method is, or will be, using or used by more features of another class than the class on which it is defined.
Create a new method with a similar body in the class it uses most. Either turn the old method into a simple delegation, or remove it altogether
MoveFieldRefactoring
EinführungindieSoftwaretechnik31
A field is, or will be, used by another class more than the class on which it is defined. Create a new field in the target class, and change all its users.
32
Badsmellsincode} Feature envy
} Amethodseemsmoreinterestedinanotherclassthantheoneit’sdefinedine.g.,amethodA.m()callslotsofget/setmethodsofclassB
} Solution:} Movem()(orpartofit)intoB!
(Move method/field, extract method) } Exceptions:
} Visitor/iterator/strategyDPwherethewholepointistodecouplethedatafromthealgorithm¨ FeatureenvyismoreofanissuewhenbothAandBhaveinterestingdata
33
Badsmellsincode} Data clumps
} Youseeasetofvariablesthatseemto“hangout”togethere.g.,passedasparameters,changed/accessedatthesametime
} Usually,thismeansthatthere’sacoherentsubobjectjustwaitingtoberecognizedandencapsulated
void Scene::setTitle (string titleText, int titleX, int titleY, Colour titleColour){…}
void Scene::getTitle (string& titleText,
int& titleX, int& titleY, Colour& titleColour){…}
34
Badsmellsincode} Data clumps
} Intheexample,aTitleclassiswaitingtobeborn} Ifaclientknowshowtochangeatitle’sx,y,text,andcolour,
thenitknowsenoughtobeableto“rollitsown”Titleobjects.} However,thisdoesmeanthattheclientnowhastotalktoanother
class.
} Thiswillgreatlyshortenandsimplifyyourparameterlists(whichaidsunderstanding)andmakesyourclassconceptuallysimplertoo.
} Movingthedatamaycreatefeature envyinitially} Mayhavetoiterateonthedesignuntilitfeelsright.(Preserve whole object, extract class, introduce parameter
object)
35
Badsmellsincode} Primitive obsession
} Allsubpartsofanobjectareinstancesofprimitivetypes(int, string, bool, double, etc.)e.g.,dates,currency,SIN,tel.#,ISBN,specialstringvalues
} Often,thesesmallobjectshaveinterestingandnon-trivialconstraintsthatcanbemodellede.g.,fixednumberofdigits/chars,checkdigits,specialvalues
} Solution:} Createsome“smallclasses”thatcanencapsulatecoherent
subsetsoftheprimitivedataandvalidateandenforcetheconstraints.
(Replace data value with object, extract class, introduce parameter object)
36
Badsmellsincode} Switch statements
} Wesawthisbefore;here’sFowler’sexample:
Double getSpeed () { switch (_type) {
case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() – getLoadFactor() * _numCoconuts; case NORWEGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage);
} }
37
Badsmellsincode} Switch statements
} Thisisanexampleofalackofunderstandingpolymorphismandalackofencapsulation.
} Solution:} RedesignasapolymorphicmethodofPythonBird (Replace conditional with polymorphism, replace type code with
subclasses)
Replace conditional with polymorphism, replace type code with subclasses
EinführungindieSoftwaretechnik38
Replace conditional with polymorphism
replace type code with subclasses
39
Badsmellsincode} Lazy class
} Classesthatdoesn’tdomuchthat’sdifferentfromotherclasses.} Ifthereareseveralsiblingclassesthatdon’texhibitpolymorphic
behaviouraldifferences,thenconsiderjustcollapsingthembackintotheparentandaddsomeparameters
} Often,lazy classesarelegaciesofambitiousdesignorarefactoringthatguttedtheclassofinterestingbehaviour
(Collapse hierarchy, inline class)
Collapse hierarchy, inline class
EinführungindieSoftwaretechnik40
A class isn't doing very much. Move all its features into another class and delete it.
A superclass and subclass are not very different. Merge them together.
41
Badsmellsincode} Speculative generality
} “Wemightneedthisoneday…”} Fairenough,butdidyoureallyneeditafterall?} Extraclassesandfeaturesaddtocomplexity.
} “ExtremeProgramming”philosophy:} “Assimpleaspossiblebutnosimpler.”} “Ruleofthree”.
} Keepinmindthatrefactoringisanongoingprocess.} Ifyoureallydoneeditlater,youcanadditbackin.(Collapse hierarchy, inline class, remove parameter)
42
Badsmellsincode} Message chains
} Aclientasksoneobjectforanotherobject,whichtheclientthenasksforyetanotherobject,whichtheclientthenasksforyetanotheranotherobject,
} Navigatingthiswaymeanstheclientiscoupledtothestructureofthenavigation.
} Anychangetotheintermediaterelationshipscausestheclienttohavetochange(cf.LawofDemeter)
} Solution:Hide delegate
Hide delegate refactoring
EinführungindieSoftwaretechnik43
A client is calling a delegate class of an object. Create methods on the server to hide the delegate.
44
Badsmellsincode} Middle man
} “Allhardproblemsinsoftwareengineeringcanbesolvedbyanextralevelofindirection.”} OODPsprettywellallboildowntothis,albeitinquitecleverand
elegantways.
} Ifyounoticethatmanyofaclass’smethodsjustturnaroundandbegservicesofdelegatesubobjects,thebasicabstractionisprobablypoorlythoughtout.
} Anobjectshouldbemorethanthesumofitspartsintermsofbehaviours!
(Remove middle man, replace delegation with inheritance)
RemoveMiddleManRefactoring
EinführungindieSoftwaretechnik45
A class is doing too much simple delegation. Get the client to call the delegate directly
ReplaceDelegationwithInheritance
EinführungindieSoftwaretechnik46
You're using delegation and are often writing many simple delegations for the entire interface.
Make the delegating class a subclass of the delegate
47
Badsmellsincode} Inappropriate intimacy
} Sharingofsecretsbetweenclasses,esp.outsideoftheholyboundsofinheritancee.g.,publicvariables,indiscriminatedefinitionsofget/setmethods,C++
friendship,protecteddatainclasses} Leadstodatacoupling,intimateknowledgeofinternalstructures
andimplementationdecisions.} Makesclientsbrittle,hardtoevolve,easytobreak.
} Solution:} Appropriateuseofget/setmethods} Rethinkbasicabstraction.} Mergeclassesifyoudiscover“truelove”(Move/extract method/field, change bidirectional association to
unidirectional, hide delegate)
48
Badsmellsincode
} Alternative classes with different interfaces } Classes/methodsseemtoimplementthesame
orsimilarabstractionyetareotherwiseunrelated.
} Solution:} Movetheclasses“closer”together.
¨ Findacommoninterface,perhapsanABC.¨ Findacommonsubpartandremoveit.
(Extract[super]class,movemethod/field,renamemethod)
ExtractSuperclassRefactoring
EinführungindieSoftwaretechnik49
You have two classes with similar features. Create a superclass and move the common features to the superclass.
50
Badsmellsincode
} Data class } Classconsistsof(simple)datafieldsandsimpleaccessor/mutator
methodsonly.} Solution:
} Havealookatusagepatternsintheclients} Trytoabstractsomecommonalitiesofusageintomethodsofthedata
classandmovesomefunctionalityover} “Dataclassesarelikechildren.TheyareOKasastartingpoint,but
toparticipateasagrownupobject,theyneedtotakeonsomeresponsibility.”
(Extract/move method)
51
Badsmellsincode} Comments
} XPphilosophydiscouragescomments,ingeneral:} Instead,makemethodsshortanduselongidentifiers
} Inthecontextofrefactoring,Fowlerclaimsthatlongcommentsareoftenasignofopaque,complicated,inscrutablecode.} Theyaren’tagainstcommentssomuchasinfavourofself-
evidentcodingpractices.} Ratherthanexplainingopaquecode,restructureit!(Extract method/class, [many others applicable] …)
} Commentsarebestusedtodocumentrationalei.e.,explainwhyyoupickedoneapproachoveranother.
52
Summary} Fowleretal.‘sRefactoringisawell-writtenbookthatsummarizesalotof
“bestpractices”ofOOD/OOPwithniceexamples.} ManybooksonOODheuristicsarevagueandlackconcreteadvice.} Mostoftheadviceinthisbookisaimedatlow-levelOOprogramming.
} i.e.,loops,variables,methodcalls,andclassdefinitions.} Nextobviousstepupinabstraction/scaleistoOODPs.
} i.e.,collaboratingclasses
} Thisisanexcellentbookfortheintermediate-levelOOprogrammer.} ExperiencedOOprogrammerswillhavediscoveredalotofthetechniques
alreadyontheirown.
} Manysourcesaboutrefactoringontheweb:} http://refactoring.com/
Testing
SomeslidesbyT.BallandJ.Aldrich
EinführungindieSoftwaretechnik53
Whytest?
EinführungindieSoftwaretechnik54
Testing:Challenges
EinführungindieSoftwaretechnik55
} Testingiscostly} Testeffectivenessandsoftwarequalityhardtomeasure} Incomplete,informalandchangingspecifications} Downstreamcostofbugsisenormous} Lackofspecandimplementationtestingtools} Integrationtestingacrossproductgroups} Patchingnightmare} Versionsexploding
Example:TestingMSWord
EinführungindieSoftwaretechnik56
} inputs} keyboard} mouse/pen} .doc,.htm,.xml,…
} outputs(WYSIWYG)} Printers} displays} doc,.htm,.xml,…
} variables} fonts} templates} languages} dictionaries} styles
} Interoperability} Access} Excel} COM} VB} sharepoint
} Otherfeatures} 34toolbars} 100sofcommands} ?dialogs
} Constraints} hugeuserbase
FromMicrosoftOfficeEULA…
EinführungindieSoftwaretechnik57
FromGPL
EinführungindieSoftwaretechnik58
Thegoalsoftesting
EinführungindieSoftwaretechnik59
} Not-quite-rightanswers} Makesureitdoesn’tcrash} Regressiontesting–nonewbugs} Makesureyoumeetthespec} Makesureyoudon’thaveharmfulsideeffects
} Actualgoals} Revealfaults} Establishconfidence} Clarifyorrepresentthespecification
THElimitationoftesting
EinführungindieSoftwaretechnik60
Testingcanonlyshowthepresenceoferrors,nottheirabsence
-E.W.Dijkstra
…tobecontinuedinthenextlecture!