Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Refactoring
1
‣ Refactoring is the process of changing a software
system in such a way that it does not* alter the
external behavior of ...
‣ Refactoring (noun): A change made to the
internal structure of software to make it easier to
understand and cheaper to m...
‣ Refactoring does not include any functional
change to the system
‣ Refactoring is not “Rewriting from scratch”
‣ Refacto...
‣ Start with an existing code and make it better
‣ Change the internal structure while preserving
the overall semantics
‣ ...
‣ Improves Quality of the Code
‣ Improves Maintainability while reducing Coupling
‣ Improves the Design of Software
‣ Make...
‣ Refactor When You Add Function
‣ Refactor When You Need to Fix a Bug
‣ Refactor As You Do a Code Review
‣ Refactoring fo...
‣ Changing Interfaces
Don’t publish interfaces prematurely. Modify your
code ownership policies to smooth refactoring
‣ Da...
[Pytel et al.; 2010]
class Address < ActiveRecord::Base
belongs_to :customer
end
class Customer < ActiveRecord::Base
has_o...
<%= @invoice.customer.name %>
<%= @invoice.customer.address.street %>
<%= @invoice.customer.address.city %>,
<%= @invoice....
class Customer < ActiveRecord::Base
has_one :address
has_many :invoices
def street
Address.street
end
def city
Address.cit...
class Invoice < ActiveRecord::Base
belongs_to :customer
def customer_name
Customer.name
end
def customer_street
Customer.s...
class Address < ActiveRecord::Base
belongs_to :customer
end
<%= @invoice.customer_name %>
<%= @invoice.customer_street %>
...
class Customer < ActiveRecord::Base
has_one :address
has_many :invoices
delegate :street, :city, :state, :zip_code, :to =>...
‣ Case Statements
‣ Comments
‣ Long Method
‣ Long Parameter List
‣ Middle Man
‣ Repetitive Boilerplate
‣ Data Clumps
…
Cha...
‣ A class is doing too much simple delegation
One of the prime features of objects is encapsulation,
hiding internal detai...
Get the client to call the delegate directly
‣ If half the methods are delegating to this other class. It is time
to use r...
class Person…
def initialize(department)
@department = department
end
def manager
@department.manager
end
class Department...
‣ 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: d...
When you feel the need to write a comment, first try to refactor
the code so that any comment becomes superfluous.
20
Comm...
21
# Scan the array to see if the symbol exists
# Loop through every array index, get the third value of the list
# in the...
Symptoms that often indicate code smells:
‣ Is it SHORT?
‣ Does it do ONE thing?
‣ Does it have FEW arguments?
‣ Is it a c...
‣ One of the easiest ways to remove duplication is
Extract Method.
‣ Extract the method and call it from multiple places.
...
‣ Ninety-nine percent of the time, all you have to do to
shorten a method is Extract Method
‣ Find parts of the method tha...
‣ You have a code fragment that can be grouped together
Turn the fragment into a method whose name explains the
purpose of...
‣ You have different methods that use the same group of
variables
Treatment: Introduce a Parameter Object
def directions(l...
‣ The code has a temporary variable that’s being used to hold
intermediate results of an expression
Return self on the met...
‣ TDD refactoring
‣ Litter-pickup refactoring
‣ Comprehension refactoring
‣ Preparatory refactoring
‣ Planned refactoring
...
‣ Refactoring plugin (Eclipse)
‣ Aptana Studio 3
‣ RubyMine
‣ Rails tool reek finds code smells
‣ metric_fu (book SaaS: sa...
‣M. Fowler; K. Beck; Addison Wesley, 2002;
Refactoring: Improving the Design of Existing Code
‣Fields, J.; S. Harvie; M. F...
Upcoming SlideShare
Loading in …5
×

Refactoring

570 views

Published on

Refactoring with ruby code examples

Published in: Software
  • Be the first to comment

Refactoring

  1. 1. Refactoring 1
  2. 2. ‣ Refactoring is the process of changing a software system in such a way that it does not* alter the external behavior of the code yet improves its internal structure [Fowler et al.; 2002] ‣ The art of safely* improving the design of existing code [Fowler et al.; 2009] *Importance of Testing in Refactoring 2 Definition
  3. 3. ‣ Refactoring (noun): A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior ‣ Refactor (verb): To restructure software by applying a series of refactorings without changing its observable behavior 3 Definition
  4. 4. ‣ Refactoring does not include any functional change to the system ‣ Refactoring is not “Rewriting from scratch” ‣ Refactoring is not just any restructuring intended to improve the code 4 Refactoring is not
  5. 5. ‣ Start with an existing code and make it better ‣ Change the internal structure while preserving the overall semantics ‣ Refactoring changes the programs in small steps If you make a mistake, it is easy to find the bug 5 Refactoring is
  6. 6. ‣ Improves Quality of the Code ‣ Improves Maintainability while reducing Coupling ‣ Improves the Design of Software ‣ Makes Software Easier to Understand ‣ Helps You Find Bugs 6 Benefits
  7. 7. ‣ Refactor When You Add Function ‣ Refactor When You Need to Fix a Bug ‣ Refactor As You Do a Code Review ‣ Refactoring for Greater Understanding The third time you do something similar, you refactor 7 When
  8. 8. ‣ Changing Interfaces Don’t publish interfaces prematurely. Modify your code ownership policies to smooth refactoring ‣ Databases ‣ Design Changes That Are Difficult to Refactor ‣ When Shouldn’t You Refactor? ‣ It Takes A While to Create Nothing ‣ Refactoring and Performance 8 Problems with refactoring
  9. 9. [Pytel et al.; 2010] class Address < ActiveRecord::Base belongs_to :customer end class Customer < ActiveRecord::Base has_one :address has_many :invoices end class Invoice < ActiveRecord::Base belongs_to :customer end 9 AntiPattern: Voyeuristic Models
  10. 10. <%= @invoice.customer.name %> <%= @invoice.customer.address.street %> <%= @invoice.customer.address.city %>, <%= @invoice.customer.address.state %> <%= @invoice.customer.address.zip_code %> 10 AntiPattern: Voyeuristic Models
  11. 11. class Customer < ActiveRecord::Base has_one :address has_many :invoices def street Address.street end def city Address.city end def state Address.state end def zip_code Address.zip_code end end Principle of Least Knowledge 11
  12. 12. class Invoice < ActiveRecord::Base belongs_to :customer def customer_name Customer.name end def customer_street Customer.street end def customer_city Customer.city end def customer_state customer.state end def customer_zip_code customer.zip_code end Principle of Least Knowledge 12
  13. 13. class Address < ActiveRecord::Base belongs_to :customer end <%= @invoice.customer_name %> <%= @invoice.customer_street %> <%= @invoice.customer_city %> <%= @invoice.customer_state %> <%= @invoice.customer_zip_code %> “use only one dot” 13 Principle of Least Knowledge (Demeter)
  14. 14. class Customer < ActiveRecord::Base has_one :address has_many :invoices delegate :street, :city, :state, :zip_code, :to => :address end class Invoice < ActiveRecord::Base belongs_to :customer delegate :name, :street, :city, :state, :zip_code, :to => :customer, :prefix => true end 14 Thanks to the class-level delegate method! You have the benefit of following the Law of Demeter without so much extra clutter in your models.
  15. 15. ‣ Case Statements ‣ Comments ‣ Long Method ‣ Long Parameter List ‣ Middle Man ‣ Repetitive Boilerplate ‣ Data Clumps … Chapter 3 - Bad Smells in Code [Fowler et al.; 2009] 15 If it stinks, change it [Grandma Beck; 2002]
  16. 16. ‣ A class is doing too much simple delegation One of the prime features of objects is encapsulation, hiding internal details from the rest of the world. Encapsulation often comes with delegation. You ask a director whether is free for a meeting. The Director delegates the message to a diary and gives you an answer. There is no need to know whether the director uses a diary, an electronic gizmo, or a secretary. 16 Remove middle man [Fowler et al.; 2002]
  17. 17. Get the client to call the delegate directly ‣ If half the methods are delegating to this other class. It is time to use remove middle man and talk to the object that really knows what’s going on Inline Method: If only a few methods aren’t doing much, use Inline Method to inline them into the caller. 17 Remove middle man
  18. 18. class Person… def initialize(department) @department = department end def manager @department.manager end class Department attr_reader :manager def initialize(manager) @manager = manager end ... This is simple to use and encapsulates the department. However, if a lot of methods are doing this, I end up with too many of these simple delegations on the person. That’s when it is good to remove the middle man. manager = john.manager Take each method at a time. Find clients that use the method on person and change it to first get the delegate. Then use it: Make an accessor for the delegate: class Person… attr_reader :department manager = john.department.manager 18 Remove middle man
  19. 19. ‣ 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: def get_rating more_than_five_late_deliveries ? 2 : 1 end def more_than_five_late_deliveries @number_of_late_deliveries > 5 end def get_rating @number_of_late_deliveries > 5 ? 2 : 1 end 19 Inline method [Fowler et al.; 2002]
  20. 20. When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous. 20 Comments Should Describe Things That Aren’t Obvious From The Code: Why, not What [9.4 Book SaaS apud John Ousterhout] Comments are a sweet smell [Fowler]
  21. 21. 21 # Scan the array to see if the symbol exists # Loop through every array index, get the third value of the list # in the content to determine if it has the symbol we are # looking for. Set the result to the symbol if we find it. Comments [Fox, A.; Patterson, D.; 2015]
  22. 22. Symptoms that often indicate code smells: ‣ Is it SHORT? ‣ Does it do ONE thing? ‣ Does it have FEW arguments? ‣ Is it a consistent level of ABSTRACTION? 22 SOFA [Martin, R.; 2008]
  23. 23. ‣ One of the easiest ways to remove duplication is Extract Method. ‣ Extract the method and call it from multiple places. ‣ Some kinds of methods become so commonplace that we can go even further. ‣ Take for example attr_reader in Ruby. 23 Repetitive boilerplate [Fowler et al.; 2009]
  24. 24. ‣ Ninety-nine percent of the time, all you have to do to shorten a method is Extract Method ‣ Find parts of the method that seem to go nicely together and make a new method 24 Long method [Fowler et al.; 2002]
  25. 25. ‣ You have a code fragment that can be grouped together Turn the fragment into a method whose name explains the purpose of the method def print_owning(amount) Print_banner puts "name: #{@name}" puts "amount: #{amount}" end def print_owning(amount) print_banner print_details amount end def print_details(amount) puts "name: #{@name}" puts "amount: #{amount}" end 25 Extract method [Fowler et al.; 2002]
  26. 26. ‣ You have different methods that use the same group of variables Treatment: Introduce a Parameter Object def directions(lat, long) ... end def distance(lat, long) ... end def directions(location) ... end def distance(location) ... end 26 Data clumps [Fowler et al.; 2002]
  27. 27. ‣ The code has a temporary variable that’s being used to hold intermediate results of an expression Return self on the methods so it’s possible to chain the calls mock = Mock.new expectation = mock.expects(: a_method) expectation.with("arguments") expectation.returns([1, :array]) mock = Mock.new mock.expects(:a_method_name).with ("arguments").returns([1, :array]) 27 Replace temp with chain [Fowler; 2002]
  28. 28. ‣ TDD refactoring ‣ Litter-pickup refactoring ‣ Comprehension refactoring ‣ Preparatory refactoring ‣ Planned refactoring ‣ Long-term refactoring 28 Workflows of refactoring
  29. 29. ‣ Refactoring plugin (Eclipse) ‣ Aptana Studio 3 ‣ RubyMine ‣ Rails tool reek finds code smells ‣ metric_fu (book SaaS: saikuro (CC), flog (ABC)) ‣ Rake metrics ‣ CodeClimate ‣ Mezuro 29 Tools
  30. 30. ‣M. Fowler; K. Beck; Addison Wesley, 2002; Refactoring: Improving the Design of Existing Code ‣Fields, J.; S. Harvie; M. Fowler; K. Beck; Addison Wesley, 2009; Refactoring Ruby Edition ‣Pytel, C.; Saleh, T.; Addison Wesley, 2010; Rails Antipatterns Best Practice Ruby on Rails Refactoring ‣Martin, R.; Prentice Hall, 2008; Clean Code: A Handbook of Agile Software Craftsmanship ‣Fox, A.; Patterson, D.; Strawberry Canyon, 2015; Construindo Software como Serviço (Capítulo 9) ‣http://refactoring.com/catalog/ 30 References

×