Refactoring Code

Best practices for refactoring your code and some useful 'smells' to look out for.

Scroll down...

Content

Resources

Comments

If following the Style Guide is about making your code more legible, refactoring is about taking "code smells" and removing them through justified rewriting. When you write code, you will inevitably write code that isn't great.

That's not actually a problem -- you often don't know exactly what you want to write ahead of time so have to get something out there first. That's why the last step of coding is always to refactor what you've written so it conforms better to principles like SOLID and DRY.

In this lesson, we'll briefly highlight some of the things to watch out for when you're going through and refactoring your old code. It's amazing what you can identify just by getting some distance and re-working what you've written! You'll learn to develop a eye for spotting anti-patterns and a nose for smelly code.

Principles

These will seem familiar from our earlier lessons, but now they apply to real code!

DRY it Up

Don't Repeat Yourself has been our motto for some time. Anywhere you see lines of code or processes duplicated, pull them out into helper methods. If your classes are duplicating significant functionality, should they inherit from a parent class? Should you refactor the shared methods into a module instead and include it?

YAGNI

You Ain't Gonna Need It. Don't design things more general than they need to be. It's often easier to refactor code to extend to a more general case than it is to remove speculative generality that you build in because you were being clever for the future.

If you truly embrace the Agile Development approach, you know that we don't know enough about where the code base is going right now to do this. We anticipate changes in the requirements but we cannot know what those changes will be so any speculation might actually take you down the wrong path.

Tell Don't Ask

Don't ask a question of an object and then use that output to decide if you want to do something else with it. Simply delegate the original task as well as its conditional logic to another method and forget about it.

# BAD
if current_user.admin?
    current_user.admin_welcome_message
else
    current_user.normal_welcome_message
end

# GOOD
current_user.welcome_message  # delegate the conditional logic to this

Code Smells

Long Methods

From the Style Guide, methods longer than 10 lines are smelly. Are you trying to do too much?

Too Many Parameters

If your method is taking a ton of parameters, that's a good indication that it's too closely coupled to another method or is doing too much. The same is true if you're passing around large clumps of data from one method to another to another.

Long Method Chains

If you are using dot-separated chains of methods that are more than two-or-three methods long, you're violating the Law of Demeter(the "D" in SOLID), which says basically "only talk to your neighbors". This is because you don't want to know too much about upstream methods in case they change later.

Keep it shallow.

# BAD
person.right_hand.raise

# Better
person.raise_right_hand

Too Broad of an Interface

Do your classes suffer from oversharing? Do they give everyone access to their internal methods and variables? Reduce the number of things that external parties can access through use of private and protected methods and instance variables with attr_accessor.

In the real world, people will use pretty much anything you give them, even if it's not meant to be used that way. So don't expose anything to other classes that you don't need to or you'll be stuck supporting it.

God Classes or Methods

You shouldn't have one object or script that knows everything about everyone in the system. That violates the principle of low coupling between objects and results in code that is too highly dependent on the knowledge of this single class or method.

Work to reduce how much each part of your program knows about the others!

Dead Code

Remove commented out code ASAP. You're not going to bring it back. If you do end up needing to find it again, there's always Git.

See the Resources tab for more helpful refactoring tips.



Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!

Next Lesson: Ruby Style Guide