| Bad Smells in Code | |||
| Duplicate Code | Same expression in two methods - use Extract Method; same expression in sibling classes - use Extract Method, then Pull Up Method; if classes are not siblings, start with Extract Class | ||
| Long Method | Decompose if you feel the need to comment. Use Extract Method. Introduce Parameter Object, Preserve Whole Object, and Decompose Conditional can help. | ||
| Large Class | Class tries to be omnipotent. Use Extract Class, Extract Subclass, Extract Interface. | ||
| Long Parameter List | First, just use objects that encapsulate data. Parameter → Method, Preserve Whole Object, Introduce Parameter Object will help you. | ||
| Divergent Change | Happens when one class regularly changes for different reasons - meaning it contains too much information or functionality. Extract Class helps. | ||
| Shotgun Surgery | Happens when one change requirement leads to changes in several places. Use Move Method, Move Field to put all changes into one class. | ||
| Feature Envy | A method is more interested in another class than its own. Use Move Method to fix. | ||
| Data Clumps | Data that hang together should be moved to an object. Use Extract Class, Preserve Whole Object, Introduce Parameter Object. | ||
| Primitive Obsession | Small classes do not take more memory or processor than primitive types. Start with Data Value → Object, Type Code → State/Strategy Type Code → Subclasses; then you can get other bad smells and act accordingly. | ||
| Switch Statement | Lack of switches is the symptom of object-oriented code.
Extract Method, Move Method,
Conditional → Polymorphism.
To get rid of checking for null, use Introduce Null Object.
|
||
| Parallel Inheritance Hierarchies | It is a special case of Shotgun Surgery. | ||
| Lazy Class | Class that does nothing should be eliminated. Collapse Hierarchy, Inline Class | ||
| Speculative Generality | Unnecessary generality is hard to understand and maintain. Collapse Hierarchy, Inline Class, Rename Method can help. | ||
| Temporary Fields | An instance variable is set only in certain circumstances - it does not belong there then. Extract Class can help find a place for such variables. | ||
| Message Chain | It's when you get an object, get another object from it, and get another object from the result, etc. Hide Delegate can help. | ||
| Middle Man | If a class does nothing else than passing requests to other classes... Remove Middle Man. | ||
| Inappropriate Intimacy | Classes know too much about each other. Move Method, Move Field. | ||
| Alternative Classes with Different Interfaces | Rename Method, Move Method, Extract Superclass. | ||
| Incomplete Library Class | Introduce Foreign Method, Introduce Local Extension. | ||
| Data Class | Encapsulate Field, Encapsulate Collection to get rid of public fields; Move Method or Extract Method to add functionality to the class. | ||
| Refused Bequest | Subclasses may not need some of the methods from superclasses - meaning we have a wrong hierarchy. Use Push Down Method to move such methods to its right clients. | ||
| Comments | They signal code that is too complicated. Extract Method, Rename Method, Introduce assertion may be helpful. | ||
| Boolean Parameter | If boolean is used to modify behavior, try something different; cure is the same as for Primitive Obsession | ||
| Two String Parameters | Unless the method deals specifically with strings, there's always a chance of mixing the strings Introduce Parameter Object may help.
|
||
| Composing Methods | Action | Reason | |
| Extract Method | pull a piece of code as a method | give code a name | |
| Inline Method | opposite to Extract Method | too trivial | |
| Inline Temp | get rid of temp variable | do not cache results | |
| Temp → Query | get rid of value caching | eliminate dependencies | |
| Explaining Variable | split complicated expression | readability | |
| Split Temp Variable | get rid of variable reuse | one responsibility per var | |
| Remove Parameter Assignment | Use temp variable instead | one responsibility per var | |
| Method -> Method Object | Make an object out of method | helps toExtract Method with too many local vars | |
| Substitute Algorithm | rewrite the code | you tell me (or ask Martin Fowler) | |
| Moving Features | Action | Reason | |
| Move Method | move it from one class to another | it deals with another class | |
| Move Field | move it from one class to another | more used in another class | |
| Extract Class | split a class into two | when it does the job of two | |
| Inline Class | opposite to Extract Class | if it does not do anything | |
| Hide Delegate | create delegate methods to hide the delegate | encapsulation | |
| Remove Middle Man | opposite to Hide Delegate | hide delegate functionality from middleman | |
| Foreign Method | create a method you cannot add to a class | can't modify the class | |
| Local Extension | Decorate the subclass for your purposes | can't modify the class | |
| Organizing Data | Action | Reason | |
| Self Encapsulate Field | add getter/setter | makes data access more flexible | |
| Data → Object | make data item an object | enables adding behavior and features | |
| Value → Reference | turn an object into a reference object | keep one instance, give it its own life | |
| Reference → Value | opposite to Value → Reference | no need to care about the value lifecycle | |
| Array → Object | will have a field for each array element | heterogenous data are treated uniformly | |
| Duplicate Observed Data | copy data to user object; set up observer to synchronize | separate view data from model data in mvc | |
| Unidirectional → Bidirectional | add back pointers; modifiers will change both sets | client of referred class needs to get to referrer | |
| Bidirectional → Unidirectional | drop unneeded end of association | one class does not need features of the other | |
| Magic Number → Symbolic Constant | create a constant with meaningful name | to avoid mentioning the same constant in different places | |
| Encapsulate Field | make it private, add accessors. see Self Encapsulate Field | never make your data public | |
| Encapsulate Collection | return a read-only view of collection, provide add/remove methods | to ensure owner's control over collection manipulation | |
| Record→ Data Class | make a data object for the record | enable adding methods and fields | |
| Type Code → Class | Replace type number with class. see Type Code → Subclasses | get rid of magic numeric codes | |
| Type Code → Subclasses | introduce subclasses instead of typecode. see Type Code → Class | to isolate different behaviors i subclasses | |
| Type Code → State/Strategy | replace typecode with state object. see Type Code → Subclasses, Type Code → Class | additionally, can be used if typecode changes | |
| Subclass→ Fields | introduce fields that differ for subclasses, get rid of accessors and subclasses (I woud add static constant instances to replace these subclasses) | subclasses differ only in constants | |
| Conditionals | |||
| Decompose | turn complicated condition into method | complex conditions are source of errors | |
| Consolidate | turn sequence of conditionals with the same result into method | get rid of repeating evaluations | |
| Consolidate Duplicates | move duplicate code out of conditionals | get rid of duplicated fragments of code | |
| Remove Control Flag | use break or return instead | ancient theory of single exit... | |
| Nested Conditional → Guard Clause | introduce guard conditions instead of tree of conditions | make code look simplistic | |
| Conditional →Polymorphism | move each leg to an overriding method of subclass, keeping original abstract | Polymorphism macht frei | |
| NullObject | introduce a special default null object | get rid of if(==null) checks | |
| Assertion | introduce assertion in the beginning of method | make an assumption explicit | |
| Method Calls | Action | Reason | |
| Rename Method | change the name | to reflect its purpose | |
| Add Parameter | add parameter | information missing | |
| Remove Parameter | remove it | if you don't need it | |
| Separate Query from Modifier | create two method: one for query, one for modification | avoid mixing change and retrieval | |
| Parameterize Method | merge several methods into one, with parameter | avoid duplication | |
| Parameter → Explicit Methods | opposite to Parameterize Method | use when code to run depends on parameter | |
| Preserve Whole Object | pass an object instead of its fields | it is like middle man | |
| Parameter → Method | remove parameter, let receiver invoke the getter | shorter parameter list | |
| Parameter Object | make an object out of a group of parameters that go together | easier to pass around | |
| Remove Setter | remove setters for a field | set immutable field at creation | |
| Hide Method | make method private | if nobody uses it | |
| Constructor → Factory Method | replace constructor with factory method | if you want more than simple construction - e.g. when you replace type code with subclass | |
| Encapsulate Downcast | move downcasting to withing the method that returns the value | get rid of downcasting... generics may help actually | |
| Error Code → Exception | throw exception instead of returning error code | errors need special treatment anyway, they break the natural control flow | |
| Exception → Test | let caller check condition instead of throwing exception on that condition | the caller has to react anyway | |
| Generalization | Action | Reason | |
| Pull Up Field | move field to superclass | avoid its duplication in subclasses | |
| Pull Up Method | move method to superclass | avoid its duplication in subclasses | |
| Pull Up Constructor Body | move constructor body to superclass | avoid duplication of common constructor code | |
| Push Down Method | move method to subclasses | if it is not used in all subclasses | |
| Push Down Field | move field to subclasses | if it is not used in all subclasses | |
| Extract Subclass | create subclass for a subset of features | features are not used in all subclasses | |
| Extract Superclass | for two classes with similar features, create a superclass, move common features there | avoid code duplication | |
| Extract Interface | several classes have a partially common interface - extract the subset to an interface | create a new set of class responsibilities | |
| Collapse Hierarchy | merge together subclass and superclass | when they are not very different | |
| Form Template Method | you have two methods in subclasses that perform similar but different steps in the same order - get the steps into methods, then pull original methods | inheritance helps eliminate duplicate behavior | |
| Inheritance → Delegation | create a field for superclass, and delegate | subclass does not use much of superclass functionality and data | |
| Delegation → Inheritance | make delegating class a subclass of the delegate | if you are using all of the delegate, and are tired writingdelegating methods | |
| Big Refactoring | Action | Reason | |
| Tease Apart Inheritance | create two hierarchies out of one, and use delegates | you have a hierarchy that does two jobs at once | |
| Procedural Design → Objects | turn data to objects, break up behavior, move behavior to objects | you have a procedural-style code | |
| Separate Domain From Presentation | move domain logic from presentation to separate domain classes | -support MVC | |