Refactoring Methods
Composing Methods Properly
- Turn the fragment into a method whose name explains the purpose of the method
- Benefit is that original method become shorter and easier to comprehend
- A method's body is just as clear as its name
- Put the method's body into the body of its callers and remove the method
- You have a temp that is assigned to once with a simple expression and the temp is getting in the way of other refactorings
- Replace all references to that temp with the expression
- You are using a temporary variable to hold the result of an expression
- Extract the expression into a method. Replace all references to the temp with the expression. The new method can then be used in other methods
- By replaceing the temp with a query method, any method in the class can get the information cleanly
- Put the result of the complicated expression, or parts of the expression, in a temporary variable with a name that explains the purpose
- You have a temporary variable assigned to more than once, but is not a loop variable nor a collecting temporary variable
- Make a separate temporary variable for each assignment
- When your code assigns to a parameter in a function/method, use a temporary variable instead
- You have a long method that uses local variables in such a way that you cannot apply Extract Method
- Turn the method into its own object so that all the local variables become fields on that object. You can then decompose the method into other methods on the same object
- You want to replace an algorithm with one that is clearer. Replace the body of the method with the new algorithm
Moving Features Between Objects
- Look for a method in the class that reference another object more than the object it lives in
- Create a new method with similar body in the class it uses most and either remove the old method or turn old method into a simple delegation
- Use move method when classes have too much behavior or when classes are collaborating too much or highly coupled
- A field is 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
- You have a monolithic class, handling multiple responsibilites, consider it splitting
- An example could be that presentation and business logic is handled by same class
- A class is not doing much then move its feature into other class and delete it
- Instead of returning a delegate object, expose the delegate method (functionality implemented by delegate object), which a client can directly call
- For example - Instead of returning 'Department' object and then retrieve 'Department Manager' details, the client should be able to get person's department manager details directly from person's object
- A class simply take calls and forward them to other components without doing any work, This is unneeded layer and can be removed completely
- For example, Consumer is calling AccountManager and then AccountManager is retrieving consumer's account information from AccountDataProvider. In this case, the AccountManager class can be completely removed and Consumer can directly gets its account detail using AccountDataProvider class
- A server class being used needs an additional method but the class can't be modified
- Create a method in the client class with an instance of the server class as its first argument
- For example - Date class exists in third party library and doesn't contain method NextDay(), which is being used in client heavily. Creates a new method NextDay(previousDay) in client
- A server class being used needs several additional methods but can't be modified
- Creates a new class a subclass or wrapper of the original class and implement those additional methods
- For example - Date class is implemented in third party library and doesn't contain PreviousDay(), NextDay(), NextWeek() etc. but being used heavily by Client. Create a new class DateExt, wrap around Date class and implement required methods
Organizing Data
- Rather than accessing the field directly, access it indirectly using accessors
- It is debatable though for class method to access the field indirectly
- It is useful for lazy initialization though
- Data item need additional data or behavior, turn data item into an object
- For example - Initially 'Order' object might need only 'Customer Name' but then later other customer details are also required
- Multiple orders belong to same customer and in this case using 'Customer' object as value would be incorrect way of representing it. All orders belong to same customer's reference, so refactor by changing value to reference
- An important property of value object is that they should be immutable. Any time you invoke a query on one, you should get the same result
- Example - A money class with currency and value can be represented as value object. Salary might differs but at that time, each salary will be encapsulating its own money object
- Array should be used to contain collection of similar objects in some order
- Convention such as first element of array is person's name is hard to remember
- Array in which certain element means different things, replace the array with an object that has field for each element
- A well layered system separates code that handles the user interface from code that handles the business logic
- The data cannot be just moved, it need to be duplicated and synchronized
- It can be done by making presentation class an observer of the domain class and on any changes in domain, observers are notified
- In case of two classes that need to use each other's features, but there is only a one-way link, add back pointers and change modifiers to update both sets
- Bidirectional associations force an interdependency between the two classes. Any change to one class may cause a change to another. If the classes are in separate packages, you get an interdependency between the packages. Many interdependencies lead to a highly coupled system, in which any little change leads to lots of unpredictable ramifications
- Two-way association is being used but one class no longer needs features from the other. Drop the unneeded end of the association
- You have a literal number with a particular meaning, create a constant, name it after the meaning and replace the number with it
- For example, instead of 3.14159265 use Pi
- Make public field as private and provide accessors
- When you make data public, other objects can change and access data values without the owning's object knowing about it
- In case method returns a collection, make the collection read only and provide add / remove methods
- A class should represent the record and class has only private fields and accessors methods. Later this class can be refactored.
- Replace numeric type codes or enumerations as class if it doesn't change the behavior of the class
- For example, instead of enumerating Blood Groups, it can be represented as an instance. There is no action being taken or instance behavior is changing due to blood group type
- There are immutable type codes that affects the behavior of the class
- For example, Employee can be "Salesman" or "Engineer" and the behavior of the employee it's salary, department etc. dependent on the type
- You have a type code that affects the behavior of a class and type code changes during the life of the object
- You have subclasses that vary only in methods that return constant data. Change the methods to supperclass fields and eliminate the subclasses
- For example - If a person class has subclasses like Male and Female and subclasses returns the code as 'M' or 'F' than remove subclasses Male & Female and add code as private field in the person class with accessor method as GetCode()
Comments
Post a Comment