Top Banner
SIMPLIFYING CODE MONSTER TO ELEGANT IN N<5 STEPS Tute Costa - @tutec
28

Simplifying Code: Monster to Elegant in 5 Steps

Jul 14, 2015

Download

Software

tutec
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Simplifying Code: Monster to Elegant in 5 Steps

SIMPLIFYINGCODE

MONSTER TO ELEGANTIN N<5 STEPS

Tute Costa - @tutec

Page 2: Simplifying Code: Monster to Elegant in 5 Steps

REFACTORING PATTERNS(And all these buzz words.)

Page 3: Simplifying Code: Monster to Elegant in 5 Steps

ABOUT TUTE

Page 4: Simplifying Code: Monster to Elegant in 5 Steps

20**: STUDENT/FREELANCERI learned CS theory at school

I practiced at home different languagesI built small projects as a freelancer

Learned web dev alongside good mentors

Page 5: Simplifying Code: Monster to Elegant in 5 Steps

2011/2012: CHEFSURFINGWe wrote so much code.

Every 2 months complexity would bite us.Stop-the-world. Refactor.

Not predictable. Not sustainable.

Page 6: Simplifying Code: Monster to Elegant in 5 Steps

CHEF SURFING FELT LIKE

Page 7: Simplifying Code: Monster to Elegant in 5 Steps

2013: GENERAL ASSEMBLYRails app in BAD shape. But well tested.I was told “refactor allthethings!“Improved productivity week after week

Page 8: Simplifying Code: Monster to Elegant in 5 Steps

GENERAL ASSEMBLY FELTLIKE

Page 9: Simplifying Code: Monster to Elegant in 5 Steps

2014: THOUGHTBOTCode Quality is daily bread and butterWe heavily prioritize what to buildTechnical Debt is not allowedMakes for developers and clients'happiness

Page 10: Simplifying Code: Monster to Elegant in 5 Steps

THOUGHTBOT FEELS LIKE

Page 11: Simplifying Code: Monster to Elegant in 5 Steps

Before:

After:

ANOMALY 1: CODE DOESN'T READ WELL

if hash[row[1]][date] != row[0] # ...

if remove_duplicates?(row, date) # ...

def remove_duplicates?(data, date)

Page 12: Simplifying Code: Monster to Elegant in 5 Steps

INTENTION REVEALING METHOD

1. Add comments if code needs it2. Transform comments into methods

Transform them syntactically, then create the method.

3. Comments are now code.And the code describes itself.

Page 13: Simplifying Code: Monster to Elegant in 5 Steps

INTENTION REVEALING METHOD

Comments are now code.And the code describes itself.

MASSIVESUCCESS.

Page 14: Simplifying Code: Monster to Elegant in 5 Steps

INTENTION REVEALING METHOD

It's arguably the easiest pattern.

But the hardest as well.

Page 15: Simplifying Code: Monster to Elegant in 5 Steps

ANOMALY 2: WHAT IS NIL?Hint: it's a troublemaker.

Source of hard to spot errors:Undefined method ̀name' for nilsession[:current_user] # => nilsession[:current_dinozauh] # => nilif (false) then 1 end # => nilempty_method() # => nil

Page 16: Simplifying Code: Monster to Elegant in 5 Steps

ANOMALY 2: WHAT IS NIL?A symbol is better than nil:

# In Ruby:# 'a' || 'b' # => 'a'# nil || 'b' # => 'b'# false || 'b' # => 'b'def current_user User.find_by_id(id) || :guest_userend

current_user.name

undefined method ̀name' for:guest_user:Symbol

Page 17: Simplifying Code: Monster to Elegant in 5 Steps

ANOMALY 2: SO MANY IFS!If there may be nil we need to enclose it

with an if:if current_user "Hi #{current_user.name}!"else "Hi guest!"end

Page 18: Simplifying Code: Monster to Elegant in 5 Steps

PATTERN: NULL OBJECTSInstead of nil, return a new objectclass NullUser def name 'guest' endend

def current_user User.find_by_id(id) || NullUser.newend

"Ohai, #{current_user.name}!"

Page 19: Simplifying Code: Monster to Elegant in 5 Steps

ANOMALY 3: GINORMOUS METHODclass 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

Page 20: Simplifying Code: Monster to Elegant in 5 Steps

REPLACE METHOD WITH METHOD OBJECT

1/4. Create a class with same initializationarguments as BIG method

class FormatAtoB def initialize(file_name) @file_name = file_name endend

Page 21: Simplifying Code: Monster to Elegant in 5 Steps

REPLACE METHOD WITH METHOD OBJECT

2/4. Copy & Paste the method's body inthe new class, with no arguments

class FormatAtoB def initialize(file_name) @file_name = file_name end

def row_per_day_format 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|

Page 22: Simplifying Code: Monster to Elegant in 5 Steps

REPLACE METHOD WITH METHOD OBJECT

3/4. Replace original method with a call tothe new class

def row_per_day_format(file_name) FormatAtoB.new(file_name).row_per_day_formatend

Page 23: Simplifying Code: Monster to Elegant in 5 Steps

REPLACE METHOD WITH METHOD OBJECT

4/4. Apply "Intention Revealing Method" tothe class. Voilà.

class FormatAtoB def initialize(file_name) @file_name = file_name end

def row_per_day_format load_file_a format_data end

private

def load_file_a

Page 24: Simplifying Code: Monster to Elegant in 5 Steps

REPLACE METHOD WITH METHOD OBJECT

 http://confreaks.com/videos/1071-cascadiaruby2012-

therapeutic-refactoring

Page 25: Simplifying Code: Monster to Elegant in 5 Steps

WE COVERED

Intention Revealing MethodTurns comments unnecessary. Code reads better.

Null ObjectsAvoids nil objects and ifs.

Replace Method with Method ObjectRefactor big methods at ease in a clean new container.

QUESTIONS ABOUT THESE?

Page 26: Simplifying Code: Monster to Elegant in 5 Steps

NEXT STEPS: " "4 RULES1. Classes of at most 100 lines of code2. Methods of at most 5 lines of code3. A method accepts at most 4 arguments4. A controller instantiates only one object

Page 27: Simplifying Code: Monster to Elegant in 5 Steps

WHY REFACTORINGNot only about aesthetics, but sharedunderstanding, bug-chase, performance.We work with the tools with which wework. We are users and creators.If I have a bias I choose "over-engineering". "Under-engineering" isrisky, expensive, and over-crowded.

Page 28: Simplifying Code: Monster to Elegant in 5 Steps

EL FIN

@tutec

QUESTIONS ABOUT ANYTHING?