Unformatted text preview:

RefactoringPiecemeal GrowthPowerPoint PresentationExtreme Normal Form DefinedSlide 5Why refactoring is importantSlide 7How to refactorHow to RefactorExample: StrategyRefactoring browserCode SmellsDuplicate codeLong methodsFileSystemHandlerSlide 16Long method in CompositeWikiMethod in CompositeWikiSlide 19Data classFeature EnvyMessage chainSlide 23Large classesLong parameter listsCase StatementsRefused bequestRefused BequestTemporary fieldNon-localized planHow to refactor non-localized planWhen to refactorSlide 33RefactoringPiecemeal GrowthThe way living things growThe way software growsMore than just addition -- transformationhttp://c2.com/cgi/wiki?ExtremeNormalFormYour classes are small and your methods are small; you've said everything OnceAndOnlyOnce and you've removed the last piece of unnecessary code. Somewhere far away an Aikido master stands in a quiet room. He is centered.. aware.. ready for anything. Outside a sprinter shakes out her legs and settles into the block, waiting for the crack of the gun while a cool wind arches across the track. Softly, a bell sounds.. all of your tests have passed. Your code is in ExtremeNormalForm.. tuned to today and poised to strike at tomorrow.Extreme Normal Form DefinedAll the code is tested. The code passes all the tests.No one on the team can think of code in the system that they could remove or simplify without reducing the feature set.You never have to go more than one place to change one thing.RefactoringExtreme Normal Form is a result of refactoring Refactoring: changes to the organization of a program, not its function.Behavior preserving program transformations.Why refactoring is importantOnly defense against software decay.Often needed to fix reusability bugs.Lets you add patterns after you have written a program; lets you transform program into framework.Lets you worry about generality tomorrow; just get it working today.Necessary for beautiful software.RefactoringRefactoring: Improving the Design of Existing Code by Martin Fowler with contributions by Kent Beck, John Brant, William Opdyke, and Don Roberts, Addison-Wesley 1999www.refactoring.comHow to refactorMake changes as small as possible.Test after each change.Many small changes are easier than one big change.Each change makes it easier to see that more changes are needed.How to RefactorUse Sunit to write test suiteUse TestRunner to run it; “keep your light green”.Plan change so it is a series of small refactoring.Run tests after every refactoring, once every 5 minutes.Example: StrategyInitially: class C with public method m1) Make a Strategy class S with empty method mFor:2) Add instance variable “strategy” to C, initialize it with an instance of S, and change m to have “strategy mFor: self”3) Move code from m to mFor:4) Move private methods from C to S.Refactoring browserIn Squeak, part of OmnibrowserAutomates many refactorings - renaming, moving code, splittingUndoSmallLint helps you find places that need to be refactored.Code SmellsData class Switch statementsSpeculative generalityTemporary fieldRefused bequestDuplicated codeLong methodLarge classLong parameter listMessage chainFeature envyDuplicate codeEliminate duplication bymaking new methodsmaking new objectsmoving methods to common superclassLong methodsEach method should do one thing.One comment for each method.Method should fit on the screen.Method is all on same level of abstraction.Method should be in right class.FileSystemHandlerdirectoryResponse: aDirectory self indexFileNames do: [:each | indexFile |indexFile := aDirectory construct: each. indexFile safeIsReadable ifTrue: [^FileResponse fileNamed: indexFile]].^DirectoryResponse fileNamed: aDirectory in: selfindexFileNames^#('index.html' 'index.htm' 'default.html' 'default.htm')FileSystemHandlerdirectoryResponse: aDirectory (self indexFilesFor: aDirectory)do: [:indexFile | indexFile safeIsReadable ifTrue: [^FileResponse fileNamed: indexFile]].^DirectoryResponse fileNamed: aDirectory in: selfindexFilesFor: aDirectory ^#('index.html' 'index.htm' 'default.html' 'default.htm') collect: [:each | aDirectory construct: each]Long method in CompositeWikiresponseKeyFor: aRequest | mightNotBeTheRightPlace key |mightNotBeTheRightPlace := aRequest identifier size >= self depth.mightNotBeTheRightPlace ifTrue: [key := aRequest identifier at: self depth]ifFalse: [^aRequest postDataAt: #COMMANDifAbsent: [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: [self rootKey]]].(self containsAction: key) ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier].^keyMethod in CompositeWikiresponseKeyFor: aRequest aRequest identifier size < self depth ifTrue: [^aRequest postDataAt: #COMMAND ifAbsent: [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: [self rootKey]]].(self containsAction: (self keyIn: aRequest)) ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier].^self keyIn: aRequestresponseKeyFor: aRequest (aRequest isKeyMissingFor: self) ifTrue: [^aRequest postDataAt: #COMMAND ifAbsent: [aRequest postDataAt: #DEFAULT_COMMAND ifAbsent: [self rootKey]]].(self containsAction: (self keyIn: aRequest)) ifTrue: [aRequest decodeUrlencodedFormData: aRequest lastIdentifier].^self keyIn: aRequestData classSome classes have only variables and accessors.Look for places where accessors are used and eliminate “feature envy” and “message chains”.Feature Envyteacher classes add: thisClass.teacher classLoad: (teacher classLoad + 1)teacher addClass: thisClassMessage chainEliminate navigation codeEnsures that user of an object doesn’t have to know many classesaFigure boundingBox centerMessage chainLaw of Demeter:Method should only send messages to classes of instance variables and arguments.anX m1 m2 m3 m4 m5 m6 => anX m6Large classesMore than seven or eight variablesMore than fifty methodsYou probably need to break up the classComponents (Strategy, Composite, Decorator)InheritanceLong parameter listsIf you see the same set of parameters repeated in several methods, bundle them into a new object. Create accessers to get the original parameters from the object. Change the methods to use the new object instead of the parameters.Then figure out what other functionality needs to move to the object.Case StatementsUse polymorphism, not case statement.Make class hierarchy, one class for each case.Make a method for each case statement.Make each branch of case statement be a method in a classRefused bequestSubclass does not use all the


View Full Document

UIUC CS 598 - Refactoring

Download Refactoring
Our administrator received your request to download this document. We will send you the file to your email shortly.
Loading Unlocking...
Login

Join to view Refactoring and access 3M+ class-specific study document.

or
We will never post anything without your permission.
Don't have an account?
Sign Up

Join to view Refactoring 2 2 and access 3M+ class-specific study document.

or

By creating an account you agree to our Privacy Policy and Terms Of Use

Already a member?