Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Refactoring to Patterns
- Are patterns a panacea to all your design ills? Of course not.
- > Only hard workd and dedication can work magic.
- Patterns help mostly when you already know the problem space. To help understand a problem space, refactor *towards* a pattern, even if you don't end up with some shinny example at the end.
- ## Creation Refactorings
- ### Replace Constructor Sprawl with *Creation Methods*
- - Constructors on a class make it hard to decide which constructor to call during development
- - Communicates what kind of instances are available better than uber-constructors
- **Before**
- ```
- Loan(commitment, riskRating, maturity)
- Loan(commitment, riskRating, maturity, expiry)
- Loan(commitment, outstanding, riskRating, maturity, expiry)
- Loan(capitalStrategy, commitment, riskRating, maturity, expiry)
- Loan(capitalStrategy, commitment, outstanding, riskRating, maturity, expiry)
- ```
- **After**
- ```
- createTermLoan(commitment, riskRating, maturity)
- createTermLoan(capitalStrategy, commitment, riskRating, maturity)
- createRevolver(commitment, outstanding, riskRating, expiry)
- createRevolver(capitalStrategy, commitment, outstanding, riskRating, expiry)
- createRevolvingConvertible(comitment, outstanding, riskRating, maturity, expiry)
- createRevolvingConvertible(capitalStrategy, comitment, outstanding, riskRating, maturity, expiry)
- ```
- ### Move creation helper classes into a *Factory*
- - If it takes lots of different classes to create some other class, then they should be bundled up, with a bow.
- - Now the client only has to do one thing, say, let yourEx = new Chimera().
- - Negative: You'll have to add new methods when you want new kinds of instances
- ### Encapsualte composite code with a *Builder*
- - Simplifies the number of concepts and classes that a client has to understand
- - Reduces error-prone nature of composing something in many locations
- - Negative: It may hide too many details about the super object that it's creating
- ## Simplification
- ### Compose a *Smaller Method*
- - If you can't rapidly understand a method's logic, then transform the logic into small, intention-revealing steps.
- - Allows you to start coding without knowing the details of how something is done within a method.
- - Negative: You can end up with a lot of small, private methods.
- **Before**
- ```
- public void add(Object element){
- if(!readOnly){
- int newSize = size + 1;
- if(newSize > elements.length){
- Object[] newElements = new Object[elements.length + 10];
- for(int i = 0; i < size; i++){
- newElements[i] = elements[i]
- }
- elements = newElements;
- }
- elements[size++] = element;
- }
- }
- ```
- **After**
- ```
- public void add(Object element){
- if(readOnly){
- return;
- }
- if(atCapacity()){
- grow();
- }
- addElement();
- }
- ```
- ### Replace Conditional Logic with a *Strategy*
- - When conditional logic controls variations of the same algorithm, encapsulate that algorithm into it's own class
- - Enables a different (maybe more performant) algorithm to be swapped out at runtime
- - Negative: Complicates the design and adds more concepts outside of the core problem
- ### Add more class functionality with a *Decorator*
- - Instead of adding new code to old classes, wrap the old class in a new "something" that adds the functionality.
- - Keeps old clients unaware of the changes
- - Negative: Unless you're programming to interfaces with strict composition, this can lead to too many unexpected classes
- ### Replace State-Altering Conditionals with *State Classes*
- - Centralize so that one class controls the details of state transitions.
- - If done right, then from the client, you can understand the semantics behind
- - Negative: If done wrong, then you'll have to manage nonsense concepts when passing control between classes
- ## Generalization
- ### Create a *Template Method*
- - Two methods perform similar steps, in the same order, but the details are different.
- - Example: every iterator method *ever*
- - Removes duplicate code
- ### Extract a *Superclass* and share methods
- - When you end creating 3+ similar classes, it's time to let our powers combine
- - Eliminates duplicate code that's shared between multiple classes
- ### Unify Interfaces with *Adapter*
- - Commonly used when you need the two classes to talk to each other but their interfaces are just different enough that the compiler has a tantrum.
- - Can also be used to simplify the surface area of a class where you only need a subset of it's functionality.
- - Negative: Can inadvertently hide some nice-to-have functionality and end up re-creating it later.
- ## End Notes
- - Let the domain's specifics guide refactoring more than language specifics.
- - Refactorings work in tiny steps. They are evolutions, not revolutions.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement