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.

Code smells

224 views

Published on

Replacing code smells by Object Oriented design

Published in: Technology
  • Login to see the comments

Code smells

  1. 1. CODE SMELLS
  2. 2. O QUE É UM CODE SMELL?
  3. 3. LEONARDO BERNARDELLI @lbenardelli
  4. 4. •Long Method •Large Class •Primitive Obsession •Long Parameter List •Data Clumps •Switch Statements •Temporary Field •Refused Bequest •Alternative Classes with Different Interfaces •Divergent Change •Shotgun Surgery •Parallel Inheritance Hierarchies •Comments •Duplicate Code •Lazy Class •Data Class •Dead Code •Speculative Generality •Feature Envy •Inappropriate Intimacy •Message Chains •Middle Man •Incomplete Library Class BLOATERS OO ABUSERS CHANGE PREVENTERS DISPENSABLES COUPLERS
  5. 5. RefactoringPara todo existe uma receita CODE SMELL que explica como resolver o problema
  6. 6. http://www.industriallogic.com/wp-content/uploads/2005/09/smellstorefactorings.pdf
  7. 7. class OrdersReport def initialize(orders, start_date, end_date) @orders = orders @start_date = start_date @end_date = end_date end def total_sales_within_date_range orders_within_range = @orders.select { |order| order.placed_at >= @start_date && order.placed_at <= @end_date } orders_within_range. map(&:amount).inject { |sum, amount| amount + sum } end end class Order < OpenStruct end
  8. 8. class OrdersReport def initialize(orders, start_date, end_date) @orders = orders @start_date = start_date @end_date = end_date end def total_sales_within_date_range orders_within_range. map(&:amount).inject { |sum, amount| amount + sum } end private def orders_within_range @orders.select { |order| order.placed_at >= @start_date && order.placed_at <= @end_date } end end class Order < OpenStruct end
  9. 9. class OrdersReport def initialize(orders, start_date, end_date) @orders = orders @start_date = start_date @end_date = end_date end def total_sales_within_date_range orders_within_range. map(&:amount).inject { |sum, amount| amount + sum } end private def orders_within_range @orders.select { |order| order.placed_between?(@start_date, @end_date) } end end class Order < OpenStruct def placed_between?(start_date, end_date) placed_at >= start_date && placed_at <= end_date end end
  10. 10. class OrdersReport def initialize(orders, date_range) @orders = orders @date_range = date_range end def total_sales_within_date_range orders_within_range. map(&:amount).inject { |sum, amount| amount + sum } end private def orders_within_range @orders.select { |order| order.placed_between?(@date_range) } end end class DateRange < Struct.new(:start_date, :end_date) end class Order < OpenStruct def placed_between?(date_range) placed_at >= date_range.start_date && placed_at <= date_range.end_date end end
  11. 11. class OrdersReport def initialize(orders, date_range) @orders = orders @date_range = date_range end def total_sales_within_date_range orders_within_range. map(&:amount).inject { |sum, amount| amount + sum } end private def orders_within_range @orders.select { |order| order.placed_between?(@date_range) } end end class DateRange < Struct.new(:start_date, :end_date) def include?(date) (start_date..end_date).cover?(date) end end class Order < OpenStruct def placed_between?(date_range) date_range.include?(placed_at) end end
  12. 12. Foo Sale Sale where .where(date: range) Persistence where List a List a List sum .sum('cost')
  13. 13. Colaboradores Imediatos Foo DateRange LIST Sale #where I KNOW MY COLLABORATORS COLLABORATORS
  14. 14. SPECULATIVE GENERALITYDEPENDENCY INJECTION É FODA!
  15. 15. 99 bottles of beer on the wall, 99 bottles of beer. Take one down and pass it around, 98 bottles of beer on the wall. 98 bottles of beer on the wall, 98 bottles of beer. Take one down and pass it around, 97 bottles of beer on the wall. 97 bottles of beer on the wall, 97 bottles of beer. Take one down and pass it around, 96 bottles of beer on the wall. … 2 bottles of beer on the wall, 2 bottles of beer. Take one down and pass it around, 1 bottle of beer on the wall. 1 bottle of beer on the wall, 1 bottle of beer. Take one down and pass it around, no more bottles of beer on the wall. No more bottles of beer on the wall, no more bottles of beer. Go to the store and buy some more, 99 bottles of beer on the wall.
  16. 16. A satisfactory modular decomposition technique must satisfy one more requirement: It should yield modules that are both open and closed. • A module will be said to be open if it is available for extension. For example, it should be possible to add fields to the data structures it contains, or new elements to the set of functions it performs. • A module will be said to be closed if is available for use by other modules. This assumes that the module has been given a well-defined, stable description (the interface in the sense of information hiding). In the case of a programming language module, a closed module is one that may be compiled and stored in a library, for others to use. In the case of a design or specification module, closing a module simply means having it approved by management, adding it to the project's official repository of accepted software items (often called the project baseline), and publishing its interface for the benefit of other module designers. Robert C. Martin SOLID
  17. 17. OBRIGADO!

×