We just pushed the latest update to Ruby Science, including three new chapters. Previous purchasers and Prime subscribers can grab the update on Learn.
New chapters this week discuss:
The book is a work in progress, and currently contains around 158 pages of content. Your purchase gets you access to the current release of the book, all future updates, and the companion example application. In addition, purchasers can send thoughtbot their toughest Ruby, Rails, and refactoring questions.
Get your copy of Ruby Science today.
Earlier this week, we announced the launch of our subscription service: Learn Prime.
For just $99/month, you get ongoing access to everything we teach, including books like Ruby Science. You’ll even get access to all our in-person and online workshops. Get access to exclusive subscriber content, as well as access to our private Campfire room, where you can get live help from thoughtbot designers and developers.
We pushed another update to Ruby Science today which includes five brand new chapters. Current readers can grab the update on Learn.
This week’s updates dive into three important topics. New chapters:
The first two chapters discuss the importance of naming methods and classes. We discuss how to use class and method names to improve readability and discover classes and methods that need refactoring.
Another chapter demonstrates how to extract concerns in a repeatable, combinable way using the Decorator pattern.
The last two chapters provide tips for identifying and fixing mixin abuse.
The book is a work in progress, and currently contains around 145 pages of content. A $49 purchase gets you access to the current release of the book, all future updates, and the companion example application. In addition, purchasers can send thoughtbot their toughest Ruby, Rails, and refactoring questions.
Today’s release of Ruby Science includes three new chapters. If you’re already reading Ruby Science, make sure to grab the latest version.
This week’s updates include tips on safely extracting classes, as well as a specific example of extracting Value Objects. In addition, we discuss how you can use Ruby’s classes-as-objects attitude to eliminate the need for most abstract factory classes.
The book is a work in progress, and currently contains around 123 pages of content. A $49 purchase gets you access to the current release of the book, all future updates, and the companion example application. In addition, purchasers have the ability to send thoughtbot their toughest Ruby, Rails, and refactoring questions.
Todays’ release of Ruby Science includes two new chapters. If you’re already reading Ruby Science, make sure to log into GitHub and download the latest version.
In this week’s updates, we cover composition and inheritance. You’ll learn about the uses and drawbacks of Single Table Inheritance (STI), as well as how to convert an STI hierarchy to use composition through polymorphic associations.
The book is a work in progress, and currently contains around 104 pages of content. A $49 purchase gets you access to the current release of the book, all future updates, and the companion example application. In addition, purchasers have the ability to send thoughtbot their toughest Ruby, Rails, and refactoring questions.
This blog post is about refactoring, git, long-lived branches, and scope creep. It has a lot to say, so here is a summary:
There are three relevant kinds of refactorings: fixing large swaths of code to go from ugly to less ugly; the “refactor” step of “red, green, refactor”, where the thing you just wrote is improved, and; changing an existing architecture to better handle a new feature.
The first of these—improving code from ugly to elegant—is actually an example of a re-write, should probably be avoided, and definitely should live as its own entity. Working on this while working on another feature is an example of scope creep, and pretending that it is relevant to your feature is lying to yourself. This is not the blog post I want to write now, but stop doing this please.
The third step of “red, green, refactor” is an important one. The feature is not done if you skip this step. The whole point of “green” is to get to “refactor”. But it can be easy to lose sight while doing this step; it’s easy to start re-implementing irrelevant parts of the system. When going down this path it’s good to consider another option: back out the “green”—go back to the failing test—and make a change to the existing system in preparation for the implementation.
That brings us to the third kind of refactoring: re-architecting toward a goal. This is when you can use a classical best practice (as examples: composing instead of inheriting; replacing a global with an instance variable) to make your feature easier to implement. It’s the most fun kind of refactoring: you have a clear problem to solve with a secondary ideal of improving the codebase for all.
Don’t run an experiment without a control. Don’t conflate correlation with causation. Don’t whiz on the electric fence. Don’t refactor with broken tests. Sure sure, we’ve heard it all before, but sometimes things come up!
For serious, cut it out. Instead, use this workflow.
Gemfile
changes.)Let’s look at an example. In this example, we have a small gem that connects to a singleton database connection to fetch some data.
require 'sequel'
module Ikea
DB = Sequel.connect(ENV['DATABASE_URL'])
class Couch
def all
DB[:couches].all
end
end
end
The test is super chill:
require 'rspec'
require 'ikea/couch'
describe Ikea::Couch do
it 'produces all the couches' do
Ikea::DB[:couches].insert('BoConcept ripoff')
Ikea::Couch.new.all.should == ['BoConcept ripoff']
end
end
There is some setup involved, and the test is slow, but it passes and the code stays simple. Rocking. But now we need a new feature:
it 'produces the empty list if the DB is down'
We could mock the constant, but that’s annoying and problematic.
We could redefine the DB constant, but that’s dumb.
Alternatively, we could pass a database connection, just like the
TDD gods intended. We’ll do that.
First step: commit what we have:
git checkout -b db-is-down
git commit -am wip
Then make a new branch off master:
git checkout master
git checkout -b no-singleton-db
Make the change:
module Ikea
class Couch
def initialize(db)
@db = db
end
def all
@db[:couches].all
end
end
end
require 'rspec'
require 'ikea/couch'
describe Ikea::Couch do
it 'produces all the couches' do
fake_table = double('couch table', all: ['BoConcept ripoff'])
fake_db = double('db connection', :[] => fake_table)
Ikea::Couch.new(fake_db).all.should == ['BoConcept ripoff']
end
end
Submit for a code review:
git commit -am "Move from a singleton DB to a composed DB connection"
git push
hub pull-request
Go back to your feature, still in progress:
git checkout db-is-down
git rebase no-singleton-db
This tiny refactoring branch may seem like a waste, even confusing. Multiple short-lived branches just to implement a single feature, asking your coworkers for a five-line code review, branching off master instead of your feature branch, rebasing. Rebasing!
But think of the alternatives: a single long-lived branch that sits in isolation, asking your coworkers for a long code review, branching off a branch (and perhaps branching off that!). And rebasing makes you feel like a badass, admit it.
As a bonus, these branches help keep you focused and on-scope. Make a branch for a tiny change, and you’ll be sure to make the tiny change. That’s all you have to focus on. No distracting features or broken tests, just that one refactoring.
This will seem slow at first. That’s OK, let it be slow. It, like TDD, will become second nature if you try.
As a useful trick, pair with someone who already does this. They’ll set you straight.
Many shell or git aliases can be built atop this. Try it out and build your own. Tweet at us with your dotfiles if you’ve made some useful ones!