https://github.com/tute/refactoring-workshop
Tute Costa - @tutecSmaller code base
Simpler
Prettier
I'm very PASSIONATE about refactoring, I think it's POWERFUL in improving productivity and thus enjoying better daily work.
Code speaks by itself, it's suddenly better than Pivotal Tracker itself or any meeting.
# Probably a comment if hash[row[1]][date] != row[0]vs
if remove_duplicates?
Add comments when needed
Transform comments into methods
Comments are now code. Code describes itself.
It's arguably the easiest pattern.
But the hardest as well.
1. Unreadable Code -> Intention Revealing Method Turns comments unnecessary. Code readsdescribes itself.
-> 2. Undefined Method on nil -> Null ObjectsAvoids nil objects and associated conditionals
3. Ginormous Method -> Replace it with Method Object Refactor big methods at ease in a clean new container
Questions time!
session[:current_user] # => nil session[:current_dinozauh] # => nil if false then 1 end # => nil empty_method() # => nilWhere did this nil come from in my whole code base? From a blog post? From a user? From a car or whatever? Hash with `nil` as value for the key Hash with a key that doesn't exist An if that evaluates to false but there's no else branch An empty method
A symbol is better than nil:
def current_user User.find_by(id: id) || :guest_user end
current_user.emailundefined method `email' for :guest_user:Symbol Now we can find in project that symbol and trace the unexpected nil.
If potentially nil, got to surround with an if
if current_user "Hi #{current_user.name}!" else "Hi guest!" endDo you know your name or do I need to specify what's the "name" for nil? Easy to forget them. The logic of what does it mean an object is nil is scattered accross the entire application.
Instead of nil, return a new object
class NullUser def name 'guest' end end
def current_user User.find_by_id(id) || NullUser.new end
"Ohai, #{current_user.name}!"
1. Unreadable Code -> Intention Revealing Method Turns comments unnecessary. Code readsdescribes itself.
2. Undefined Method on nil -> Null ObjectsAvoids nil objects and associated conditionals
-> 3. Ginormous Method -> Replace it with Method Object Refactor big methods at ease in a clean new container
Questions time!
class ExportJob # Instance variables # Many other methods # And... def row_per_day_format(file_name) file = File.open file_name, 'r:ISO-8859-1' # hash[NivelConsistencia][date] = [[value, status]] hash = { '1' => {}, '2' => {} } dates = [] str = '' CSV.parse(file, col_sep: ';').each do |row| next if row.empty? next if row[0] =~ /^\/\// date = Date.parse(row[2]) (13..43).each do |i| measurement_date = date + (i-13) # If NumDiasDeChuva is empty it means no data value = row[7].nil? ? -99.9 : row[i] status = row[i + 31] hash_value = [value, status] dates << measurement_date hash[row[1]][measurement_date] = hash_value end end dates.uniq.each do |date| if !hash['1'][date].nil? && hash['2'][date].nil? # Only 'bruto' (good) value = hash['1'][date] str << "#{date}\t#{value[0]}\t#{value[1]}\n" elsif hash['1'][date].nil? && !hash['2'][date].nil? # Only 'consistido' (kind of good) value = hash['2'][date] str << "#{date}\t#{value[0]}\t#{value[1]}\n" else # 'bruto' y 'consistido' (has new and old data) old_value = hash['1'][date] new_value = hash['2'][date] str << "#{date}\t#{new_value[0]}\t#{old_value[1]}\t#{old_value[0]}\n" end end str end"Where to even start" anxiety. The method is itself like a whole class with variables, code, different pieces of logic. Any change has repercusions both for the method and for its containing class, which was also big. An instance variable in this method is also used in others. I can't even ...! Refactoring a big method is hard because there's coupling to behavior in the same class, changes here break something there and you have to refactor it as well. Extracting Intention Revealing Methods might require too much state to be pass around in arguments There's too much context, we have to isolate the long method so that any change we make affects only that method, and nothing else.
http://confreaks.com/videos/1071-cascadiaruby2012-therapeutic-refactoring
1. Unreadable Code -> Intention Revealing Method Turns comments unnecessary. Code readsdescribes itself.
2. Undefined Method on nil -> Null ObjectsAvoids nil objects and associated conditionals
3. Ginormous Method -> Replace it with Method Object Refactor big methods at ease in a clean new container
Questions time!
Classes of at most 100 lines of code
Methods of at most 5 lines of code
A method accepts at most 4 arguments
A controller instantiates only one object
They are simple to explain and grasp, and encode many best practices.
There's dozens of refactoring and design patterns, there's many different software-related metrics.
No need to be an erudite: follow the four rules as they lead to green pastures.
Questions time!