Introduction to Refactoring

478 views

Published on

Introduction to refactoring, covering the SOLID principles, some examples of code smells and refactoring examples.

SOLID OO design principles:
- Single Responsibility Principle
- Open Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle

Code Smells:
- Comments
- Long Method
- Long Parameter List
- Duplicated Code
- Large Class
- Type Embedded in Name
- Uncommunicative Name
- Inconsistent Names
- Dead Code
- Speculative Generality

Refactorings:
- Rename Method
- Extract Method
- Replace Temp With Query
- Introduce Parameter Object
- Extract Class
- Extract Subclass
- Replace Parameter with Method
- Substitute Algorithm

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
478
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
12
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Introduction to Refactoring

  1. 1. Refactoring Improving the design of existing code … …. without changing the behavior! agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  2. 2. Why do good developers write bad software? • Project and budget pressure lead to taking shortcuts • You realize there are better ways to do something • Requirements change over time ! • When it’s hard to change update your code this lead to less optimal design e fix our w How do ? oftware s agile42 | The Agile Coaching Company How do w e know ou r software is “bad” … when it works fin e! www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  3. 3. Software development is not a Jenga game • Single Responsibility Principle • Just because you can, doesn’t mean you should. • Open Closed Principle • Open chest surgery is not needed when putting on a coat. • Liskov Substitution Principle • If it looks like a duck, quacks like a duck,
 but needs batteries – you probably have the wrong abstraction • Interface Segregation Principle • You want me to plug this in, where? • Dependency Inversion Principle • Would you solder a lamp directly to the electrical wiring in a wall? agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  4. 4. Single Responsibility Principle • A responsibility can be defined as a reason to change ! ! ! ! ! ! ! • Just because you can, doesn’t mean you should. agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  5. 5. Open Closed Principle • open for extension, but closed for modification ! ! ! ! ! ! ! • Open chest surgery is not needed when putting on a coat. agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  6. 6. Liskov Substitution Principle • use a subtype without changing the correctness of the program ! ! ! ! ! ! ! • If it looks like a duck, quacks like a duck,
 but needs batteries – you probably have the wrong abstraction agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  7. 7. Interface Segregation Principle • states that no client should be forced to depend on methods it does not use ! ! ! ! ! ! ! • You want me to plug this in, where? agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  8. 8. Dependency Inversion Principle • no dependencies on implementations only on abstractions ! ! ! ! ! ! ! • Would you solder a lamp directly to the electrical wiring in a wall? agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  9. 9. Dependency Inversion Example class EventLogWriter { public void Write(string message) { //Write to event log here } } ! class AppPoolWatcher { // Handle to EventLog writer to write to the logs EventLogWriter writer = null; ! // This function will be called when the app pool has problem public void Notify(string message) { if (writer == null) { writer = new EventLogWriter(); } writer.Write(message); } } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  10. 10. Dependency Inversion Example EventLogWriter AppPoolWatcher // This can be watcher.Action ! writer = new EventLogWriter(); watcher = new AppPoolWatcher(); done in some class = writer; // This can be done in some other class watcher.Notify("Sample message to log"); agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  11. 11. Dependency Inversion Example class AppPoolWatcher { // Handle to EventLog writer to write to the logs INofificationAction action = null; ! ! public INofificationAction Action { get { return action; } set { action = value; } } // This function will be called when the app pool has problem public void Notify(string message) { action.ActOnNotification(message); } } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  12. 12. Refactoring Improving the design of existing code Without changing the behavior agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  13. 13. Refactoring Released in 2000, already a golden oldie, a book I recommend everyone to read. ! The book defines the technique of refactoring and is a reference for refactoring types. agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  14. 14. Code Smells Refactoring Cheat Codes agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  15. 15. Code Smells • The term code smells was introduced by Kent Beck, based on an important lesson he learned from his Grandmother about children and diapers.
 
 „If it stinks, change it”—Grandma Beck agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  16. 16. Code Smells • Duplicated Code • Primitive Obsession • Inappropriate Intimacy • Long Method • Switch Statements • Large Class • Parallel Inheritance Hierarchies • Alternative Classes with Different Interfaces • Long Parameter List • Divergent Change • Shotgun Surgery • Feature Envy • Data Clumps agile42 | The Agile Coaching Company • Incomplete Library Class • Lazy Class • Data Class • Speculative Generality • Refused Bequest • Temporary Field • Comments • Middle Man • Dead Code www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  17. 17. Comments and Naming • Comments • Rename Method • Add comments only to explain purpose • Extract Method • If comments need to explain how code work, it smells. ! • Instead use meaningful names, e.g.:
 schedule.add(Course course) ! ! ! ! ! ! • Type Embedded in Name • Rename Method • Uncommunicative Name • Inconsistent Names agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  18. 18. Excess and Duplication • Excess • Long Method • Long Parameter List • Large Class • Long methods, large classes and endless parameters make code unreadable. ! • Duplicated Code • Extract Method • Replace Temp with Query • Introduce Parameter Object • Extract Class • Extract Subclass ! ! ! • Replace Parameter with Method • Pull Up Field • Form Template Method • Substitute Algorithm agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  19. 19. The Past and the Future • Dead Code • Delete Code • or worse, commented code ! • Delete it, we have version control for that! ! ! ! • Speculative Generality • Collapse Hierarchy • Don't attempt to predict future needs with unnecessary generalization. • Inline Class • Remove Parameter • Rename Method YAGNI! agile42 | The Agile Coaching Company KISS www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  20. 20. Rename Method // this method will return the maximum void getMaximumCreditLimit() { // credit limit. return maximumCreditLimit; void getIt() { } return _mCL; void getInvoiceCreditLimit() { } int maximumCredit; void getivcdlmt() { float usedCredit; int m; float u; => . . } . . } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  21. 21. Extract Method void printOwing(double amount) { void printOwing(double amount) { printBanner(); printBanner(); printDetails(amount); //print details } System.out.println ("name:" + _name); System.out.println ("amount" + amount); } void printDetails (double amount) { => System.out.println ("name:" + _name); System.out.println ("amount" + amount); } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  22. 22. Replace Temp With Query double basePrice = _quantity * _itemPrice; if (basePrice() > 1000) if (basePrice > 1000) return basePrice() * 0.95; return basePrice * 0.95; else else return basePrice() * 0.98; return basePrice * 0.98; … double basePrice() { => return _quantity * _itemPrice; } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  23. 23. Introduce Parameter Object double invoicedAmount(Date start, Date end) { double invoicedAmount(Period range) { double result; double result; for (Invoice invoice: invoices) { for (Invoice invoice: invoices) { if (range.contains(invoice.getDate()) { if (invoice.getDate().after(start) || result += invoice.getAmount(); invoice.getDate().before(end)) { } result += invoice.getAmount(); } } return result; } return result; } => ! } class Period (Date start, Date end) { . . . boolean contains(Date date) { return date.after(start) || date.before(end); } } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  24. 24. Extract Class class Person... public String getName() { class Person... public String getName() { return _name; } public String getTelephoneNumber() { return ("(" + _officeAreaCode + ")" + _officeNumber); } String getOfficeAreaCode() { return _officeAreaCode; } String getOfficeNumber() { return _officeNumber; } private String _name; private String _officeAreaCode; private String _officeNumber; agile42 | The Agile Coaching Company return _name; => ! } public String getTelephoneNumber(){ return _officeTelephone.getTelephoneNumber(); } TelephoneNumber getOfficeTelephone() { return _officeTelephone; } private String _name; private TelephoneNumber _officeTelephone = new TelephoneNumber(); class TelephoneNumber... public String getTelephoneNumber() { return ("(" + _areaCode + ") " + _number); } String getAreaCode() { return _areaCode; String getNumber() { return _number; } private String _number; private String _areaCode; www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  25. 25. Extract Subclass class JobItem ... public JobItem (int unitPrice, class JobItem ... public JobItem (int unitPrice) { boolean isLabor, Employee employee) { _unitPrice = unitPrice; _isLabor = isLabor; _employee = employee; ! } public int getUnitPrice(){ return (_isLabor) ? _employee.getRate(): _unitPrice; } ... class Employee... public Employee (int rate) { _rate = rate; } public int getRate() { return _rate; } private int _rate; _unitPrice = unitPrice; ! => } public int getUnitPrice(){ return _unitPrice; } ... class LaborItem ... public LaborItem (Employee employee) { super(0); _employee = employee; } public int getUnitPrice(){ return_employee.getRate(): } ... ! class Employee... public Employee (int rate) { _rate = rate; } public int getRate() { return _rate; } private int _rate; agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  26. 26. Replace Parameter with Method public double getPrice() { int basePrice = _quantity * _itemPrice; int discountLevel; if (_quantity > 100) discountLevel = 2; else discountLevel = 1; double finalPrice = discountedPrice (basePrice,discountLevel); return finalPrice; } ! private double discountedPrice (int basePrice, int discountLevel) { if (discountLevel == 2) return basePrice * 0.1; else return basePrice * 0.05; } agile42 | The Agile Coaching Company public double getPrice() { if (getDiscountLevel() == 2) return getBasePrice() * 0.1; else return getBasePrice() * 0.05; } ! => private double getBasePrice() { return _quantity * _itemPrice; } ! private int getDiscountLevel() { if (_quantity > 100) return 2; else return 1; } www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  27. 27. Substitute Algorithm String foundPerson(String[] people){ for (int i = 0; i < people.length; i++) { if (people[i].equals ("Don")){ return "Don"; } if (people[i].equals ("John")){ return "John"; } if (people[i].equals ("Kent")){ return "Kent"; } } return ""; } => String foundPerson(String[] people){ List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"}); for (int i=0; i &lt; people.length; i++) if (candidates.contains(people[i])) return people[i]; return ""; } agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.
  28. 28. References • SOLID:
 http://en.wikipedia.org/wiki/SOLID_(object-oriented_design) ! • SmellsToRefactorings:
 http://users.csc.calpoly.edu/~jdalbey/305/Lectures/SmellsToRefactorings ! • Martin Fowler refactoring site: http://refactoring.com/ ! • Dependency Injection: http://martinfowler.com/articles/injection.html agile42 | The Agile Coaching Company www.agile42.com | All rights reserved. Copyright © 2007 - 2014.

×