Most of the time, gems in Ruby Just Work. But there’s a big problem with Ruby magic: when things go wrong, it’s hard to find out why.
You won’t often run into problems with your gems. But when you do, Google is surprisingly unhelpful. The error messages are generic, so they could have one of many different causes. And if you don’t understand how gems actually work with Ruby, you’re going to have a tough time debugging these problems on your own.
Gems might seem magical. But with a little investigation, they’re pretty easy to understand.
gem install do?
A Ruby gem is just some code zipped up with a little extra data. You can see the code inside a gem with
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
gem install, in its simplest form, does something kind of like this. It grabs the gem and puts its files into a special directory on your system. You can see where
gem install will install your gems if you run
gem environment (look for the
INSTALLATION DIRECTORY: line):
1 2 3 4 5 6
1 2 3
All of your installed gem code will be there, under the
These paths vary from system to system, and they also depend on how you installed Ruby (rvm is different from Homebrew, which is different from rbenv, and so on). So
gem environment will be helpful when you want to know where your gems’ code lives.
How does gem code get required?
To help you use the code inside of your gems, RubyGems overrides Ruby’s
require method. (It does this in core_ext/kernel_require.rb). The comment is pretty clear:
1 2 3 4 5 6 7 8 9 10 11
For example, say you wanted to load
active_support. RubyGems will try to require it using Ruby’s
require method. That gives you this error:
1 2 3 4
RubyGems looks at that error message, and sees that it needs to find
active_support.rb inside of a gem, instead. To do that, it’ll scan through its gems’ metadata, looking for a gem that contains
Then, it activates the gem, which adds the code inside the gem to Ruby’s load path (the directories you can
require files from):
1 2 3 4 5 6
active_support is on the load path, you can
require the files in the gem just like any other piece of Ruby code. You can even use the original version of
require, the one that was overwritten by RubyGems:
A little knowledge goes a long way
RubyGems might seem complicated. But at its most basic level, it’s just managing Ruby’s load path for you. That’s not to say it’s all easy. I didn’t cover how RubyGems manages version conflics between gems, gem binaries (like
rake), C extensions, and lots of other stuff.
But knowing RubyGems even at this surface level will help out a lot. With a little code reading and playing in
irb, you’ll be able to dive into the source of your gems. You can understand where your gems live, so you can make sure that RubyGems knows about them. And once you know how gems are loaded, you can dig into some crazy-looking loading problems.
Can you learn Rails before learning Ruby? You can, for a little while. But as your app grows past the REST, generated-scaffold, twitter-clone stage, you’re going to run into some walls. Sure, you’ll learn some Ruby through osmosis. But that’ll take forever.
If you want to learn enough Ruby to master Rails, study Ruby on its own. But there are tons of Ruby books out there. I counted four shelves the last time I was in a bookstore. A lot of them are good. But there are a few that are in a class of their own. And they’ll help you through the entire process of learning Ruby.
From the beginning
Rails might be your first framework, and Ruby your first language. If you’re new to programming in general, you’ll want to start with Learn to Program. It’ll teach you to write your own programs in Ruby, even if you’ve never written code before. It’ll start you off with good habits. And I know lots of people that had a lot of fun with this as their first-ever programming book.
Next, Eloquent Ruby will teach you to write Ruby that looks like Ruby. (Which is really important to Rubyists). You’ll learn how to define classes, how to create methods on the fly, and why you’d choose one way of writing Ruby code over another.
After reading Eloquent Ruby, you’ll know idiomatic Ruby. And you’ll have an easier time reading and understanding the code you encounter.
When things get tougher
Once you read those books, you’ll know how to write Ruby code, but you’ll still have trouble organizing it. When does a method go into one class instead of another? When are classes too big? What should you do when you wrote a method so complicated that you can’t understand it?
Confident Ruby will teach you to write readable Ruby code by following some simple, general patterns. It’s about writing code that’s clear about what it does. Code that pushes decisions, duplication, and edge cases away from itself, so you don’t have to think about the complicated parts when you don’t need to. Code that Just Works.
Practical Object-Oriented Design in Ruby is about applying good design to your code. You’ll learn how to structure your objects, methods, and communication between them, so your code is easier to use and test. It’s about making your code flexible, without applying too much structure. And writing tests that you won’t hate fixing when your code changes.
Next, you’ll learn more by seeking out lots of ideas, and learning more about the ones that seem interesting. Blogs are good, but there’s been an explosion of other great resources, released regularly, on a variety of Ruby topics.
Some of my favorites are:
RubyTapas and Ruby Steps are both paid services. But they each have some episodes / newsletters available for free, so you can see if they’re your style before you sign up.
I’ve learned a ton about Ruby from years of random articles and screencasts. It’s not the most organized way to get information, but it works.
Bringing it back to Rails
Rails is Ruby. The time you spend learning Ruby will teach you about Rails, and vice versa.
So learning Ruby first isn’t a requirement for using Rails. You can do a lot with Rails even if you have to muddle through the Ruby.
But it’s not the best way to do it. You’ll have to learn Ruby eventually. And when you do, you can use these books to build a solid foundation.
I ran into a weird situation the other day with one of my apps.
Say you have an
Article model, and these articles are first created as drafts. These drafts should be lightweight. You want to be able to create and edit them right away, without needing a body, or even a title.
But when you publish these articles, you need to have some extra validation. They should have a title, a body, and all the rest of that stuff.
You could write up a bunch of
if statements to do the checking yourself. But you wouldn’t have all the nice form handling you get from Rails. And I’ve found that going with Rails for the things Rails handles well will save you a lot of headache later on. Is there still a way to use validations for this?
:unless parameters, but this isn’t always so clean:
1 2 3 4 5 6 7 8 9
Besides, this isn’t the way I want to publish an article. I want to think about publishing an article as an action, not a state the article is in, so setting and checking an attribute isn’t the right answer.
A little-known, lightly documented Rails feature
This problem is a perfect fit for Rails’ validation contexts. I first learned about custom validation contexts from a gist DHH wrote. But it was hard to find a good explanation of what these were, and how to use them.
The documentation for custom contexts is pretty thin. The only mention of it I could find in the API docs was here. And the API docs for these validations don’t mention custom contexts at all! This makes it especially hard — if you don’t know what something’s called, how do you find more documentation on it?
I finally found a good overview here: http://blog.arkency.com/2014/04/mastering-rails-validations-contexts/. It’s worth a read. Let’s see what it looks like for our example:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Not too bad! The only weird thing is having to use
save instead of
update in the publish method. That happens because
update can’t take a validation context as a parameter. (Maybe that’s an opportunity for a pull request?)
Custom validation contexts are useful for more than just saving a record in different ways. Contexts work with
so you can use validation contexts anywhere you want to answer the question: “Does this object have this property? And if not, why not?”
DHH creates a method ending in
-able? that delegates to
valid?(:context)). I really like the look of that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
This way, when you check it, you get more information than just
1 2 3
Is the article viewable? Well, why not?
Just lightweight enough
There are a few other ways you could get this kind of validation behavior. You could build custom
ActiveModel service objects with their own validations. You could use
:unless on your validations. But like a lot of the stuff in Rails, custom validation contexts are a good compromise between readability and flexibility.
The Rails 4.2 announcement had some interesting news about the upcoming Rails 5: It’s probably going to require Ruby 2.2. Which will make it the first Rails version to take advantage of all the good stuff from Ruby 2.
The good (and bad) of
When I first learned Rails,
alias_method_chain totally blew my mind. It really showed off how flexible Ruby could be.
With just a single line of code, you could completely change the way a method worked. You no longer needed to hack around libraries to add the code you wanted, you could just add it on the fly.
alias_method_chain led to my first patches to gems, which led to my first pull requests, which led to my first open source contributions.
But just like monkey patching,
alias_method_chain got overused, and its problems started to become obvious:
- The method names it generates are confusing, which makes errors hard to find and debug. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
If you had an error in
Person#greeting, the backtrace would tell you that an error actually happened in
Person#greeting_without_excitement. But where is that method even defined? I don’t see it anywhere. How do you know which
greeting method is the one with the bug in it? And the method names get even more confusing the more you chain.
If you call
alias_method_chaintwice with the same parameters on the same class, you could cause a stack overflow. (Can you see why?) This doesn’t normally happen, as long as your
requirestatements are consistent about which paths they use. But it’s super annoying if you frequently paste code into a Rails console.
And the rest of the things described by Yehuda Katz’s blog post. This post convinced a lot of Rails devs to start abandoning
alias_method_chainin favor of module inheritance.
So, why is it still used?
You can replace most
alias_method_chains by overriding those methods in a module, and including those modules into your child classes. But that only works if you want to override your superclass, not your class itself. That is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
If you ran
ChildClass.new.log, you’d see:
1 2 3
if you tried to use modules instead of
alias_method_chain, you could get the output to be:
1 2 3
But you cannot match the original output without changing the
log method in
ChildClass. Ruby inheritance doesn’t work that way. Well, it didn’t.
What changed in Ruby 2.0?
Until Ruby 2.0, there was no way to add code below a class, only above it. But with
prepend, you can override a method in a class with a method from a module, and still access the class’s implementation with
super. So, using our last example, we could get the original output with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3
prepend is still hard to wrap your head around, think of it as doing something like this:
1 2 3 4 5
Except it won’t mess with your class names, and it affects objects that already exist.
(Yes, you can reassign class names in Ruby. No, it’s probably not a great idea.)
What does this mean for Rails?
So, the last excuse for using
alias_method_chain is gone in Ruby 2.0. We could take one of the few remaining examples of
alias_method_chain in Rails:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
and replace it with a module, instead:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Range#each doesn’t get renamed, and
ensure_iteration_allowed isn’t monkey-patched in.
Use inheritance, not patches
Ruby gives you a ton of flexibility, and that’s one of the reasons I love it. But it also has a powerful object model. So when you want to inject your own code, try leaning on modules and inheritance before you hack it in. Your code will be much easier to understand and debug, and you’ll avoid some of the harder-to-detect side effects of something like
alias_method_chain was one of the coolest methods I was introduced to in Rails. But its days are numbered. We’ve outgrown it. And I’m not going to miss it when it’s gone.
No app survives first contact with actual users. Once people start to use it, they’re going to run into errors.
But soon, you’ll see the same few exceptions over and over. Maybe a web service you depend on isn’t totally stable. Or the people using your site typo’d their email, so none of your messages are going through. Exceptions should be exceptional, they should be unexpected. But how unexpected can an error be if you see it thirty times a day?
There are better ways of solving these problems than reporting and ignoring. Most noisy exceptions fall into a few basic categories. And for each of these categories, you can use patterns to cut down the noise and make your users happier at the same time.
The network is down!
Few apps work alone. Most communicate with other apps. But when your geolocation API goes down or ec2 has a hiccup, you don’t want to get spammed with thousands of exceptions that you can’t do anything about.
The basic idea behind the circuit breaker is very simple. You wrap a protected function call in a circuit breaker object, which monitors for failures. Once the failures reach a certain threshold, the circuit breaker trips, and all further calls to the circuit breaker return with an error, without the protected call being made at all.
So, when a service goes down, you’ll automatically stop trying to connect to it. You’ll just go on without that functionality. You can even make it self-healing, so your app will automatically check the service again after a certain amount of time.
The circuit breaker pattern is designed to prevent cascading failures, but you can also use it to limit exception notifications. With this pattern, you really only need to get notified when it trips and when it fails to recover. It can turn thousands of exceptions into a few. If that’s still too many, you can tell the breaker to only report after it’s failed a few retries in a row. (Or find a different, more reliable service!)
Using this pattern takes work, but it also makes the experience better for your users. Instead of a hard error page, they’ll see a message saying that this feature isn’t working right now, and they should try again later. It’s better information for them, delivered at the right time.
Turns out gmaaaail.com isn’t what you meant
Another kind of exception I see a lot comes from bad user data.
For example, say someone typo’d their email when they signed up. They said, “firstname.lastname@example.org”, but meant “email@example.com”. The first could theoretically be a valid email address, but all the emails you send bounce. And you get notified about those bounces by your email provider.
These notifications are just noise.
Instead, take a two-sided approach. Prevent the bad data up-front, and disable the feature and notify the user if it fails later on.
For email, I’ve used the mailcheck-js gem to spellcheck things like “gmail.com” and “yahoo.com” when new users register:
Then, if an email still bounces later on, turn off email to that user.
Once you turn the feature off for someone, you also need to tell them that it’s disabled and how to fix it. A banner on the top of the site is usually a good answer. Something like “We weren’t able to send your last few emails, so we’ve turned off sending emails to you. Click here to update your email address, and we’ll turn them right back on.”
You’ll get better data, and the user’s emails won’t just go into the void. Way better than those errors you’ve just been ignoring.
404s and RoutingErrors
You probably want to know about broken links or assets on your site. But those things don’t belong in your exception tracker.
For these, and other “half-expected errors”, batch them up and handle them all at once. You don’t need to get notified about them as they happen. You want pull, not push.
Things like RoutingErrors and 404s can be handled with something like Google Webmaster Tools, which will show you the pages Google knows about that are throwing 404s. Or you could run something like link-checker to check the links on your site as part of your pre-release process.
Exceptions should be actionable
It should be rare to get an exception email. Too much noise in your error tracker will keep you from seeing and fixing real problems right away.
If you’re more annoyed than embarrassed about the exceptions you see, you have a noise problem. Use the patterns here to cut down on that noise and give your users a better experience at the same time.
I’ve talked about a few of the noisy exception categories I’ve seen most often. But I’m sure I haven’t seen them all. Which exceptions annoy you the most in your apps? Do they fit into any of these categories, or do they define a new one? How do you keep them from bothering you a few hundred times a day?
The first beta of Rails 4.2 was announced last week, and it already looks amazing. I’m really excited to use ActiveJob, Web Console, Adequate Record, and Foreign Key support in my own apps.
But the beauty of Rails is in the details. And if you do a little digging, you’ll find some less advertised features that will totally improve your daily work with Rails.
Easily load config files
OK, I might be biased. But having a built-in way to load config files is going to be awesome.
config_for, new in Rails 4.2, works exactly like you’d expect:
1 2 3 4 5 6 7 8 9
That is, if you call
config_for(:redis), it’ll look for
config/redis.yml in your Rails app, parse it, and returns the right configuration for your
It even lets you put ERB in your yaml:
1 2 3 4 5 6 7 8 9
1 2 3 4
If you configure lots of services in your app, this’ll make your initializers much easier to read.
Bootstrapping your apps
Most Rails apps need you to run some commands before you can try them out. Even mostly-empty Rails apps still need the database to be set up before they’ll boot.
So, Rails, once again going with convention over configuration, created a place specifically for your setup code:
The default is good. But
bin/setup is also the place to put any other code you need to get your app started up.
So now that this is the convention, if you’ve already written a bootstrap script for your app, rename it to
bin/setup, so people using your apps can get started easily.
bin/setup gives you one less decision to make when you generate new Rails apps. And once you get in the habit of running
bin/setup after you
git pull, you’ll never have to remember to run
rake db:setup when you generate a new app again.
Transform your hash values
This is another thing I need often enough that I wish it was built-in to Ruby. When you call
transform_values on a hash, it acts like calling
map on the hash values, and returns a new hash with the original keys associated with the replaced values:
1 2 3
Simple enough. But you’d be surprised how often it comes in handy.
Bonus: More configuration!
Rails 4.2 offers a simple way to set your own global configuration:
1 2 3 4
This works especially well when you combine it with
And there’s more!
It looks like Rails 4.2 is set up to be an amazing release. But it’s the little refinements that make it so great to work in Rails every day. So, if you haven’t yet, take a quick look through the 4.2 Release Notes and see which other helpful improvements you can find.
(And if you do find some cool stuff, don’t keep it to yourself. Share it here, so we can all learn something new!)
Rails’ i18n library is more powerful than it looks. You don’t need to only use it for translation. The i18n library is useful anywhere you want to decouple the text you display from the place you display it.
While I’ve been at Avvo, we’ve used i18n to do some really cool stuff. I’m going to share a few of the things that we learned that have come in handy, along with a crazy abuse of the library that ended up working out incredibly well for us.
Automatic HTML escaping
Do you have lines that look like:
in your views? You don’t need that
raw, because if your translation key ends with
_html, you get escaping for free:
Simple, and more consistent with your other
Accessing locales more conveniently
When you build your locale files, you’ll probably have some of your keys grouped under the same parent:
1 2 3 4 5 6
To reference a bunch of these all together, you could reference them by their full key:
That’s pretty annoying and repetitive. But
t() helpfully takes a scope, so you can reference keys more conveniently:
If you name your partials well, you don’t even need to specify the scope:
bugs.index.edit_label, because you’re in
Sometimes, static translations in a yaml file just won’t work for your project. If you use the ActiveRecord i18n backend instead:
you can look up translations in a
translations table in your database. This way, you don’t have to define all your translations up-front. Instead, you can add new translations on the fly.
Setting up the
translations table requires a specific migration. The README on the i18n-active_record repo has all the information you need to get it working.
Sharing partials between object types
At Avvo, we have a lawyer directory, attorney reviews, and legal advice. But a few years ago, we didn’t just have lawyers on our site. We had doctors and dentists, too!
A lot of our UI was the same between these professions. But enough was different (for example, what lawyers call “practice areas”, doctors call “specialties”), that it would be hard to share the same views or partials without some pretty ugly code.
Eventually, we thought about trying to lean on the i18n system for this. After all, English lawyerese is kind of a dialect of English, and doctorese is the same way. We didn’t want to block ourselves from eventually using other languages, so we decided to create two new locales:
This turned out to be easy to set up as a custom i18n backend:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
And defining translations was just as easy:
1 2 3 4 5
It worked great for translating entire partials, too (note the filename):
And it even fell back to the
en locale, for shared translations:
1 2 3
When you were in the “Doctors” section of the site, we changed the default locale to
:en_md, and vice versa:
And everything just worked!
I’m not sure I’d recommend this. It’s a little nuts, thinking of different professions having different languages. But it worked amazingly well while we did it. And it reveals just how much power simple tools like i18n can have.
Where do you pick up this stuff?
Last week, I talked about taking deep dives into specific technologies as a way to move from a beginner to an expert. This is another example of that: most of what we learned about i18n we learned from reading the Rails guides and API docs.
So, take that extra step. Learn the tools you rely on well. You’ll find that you’ll run into conveniences and tricks that will not only make you more productive, but might unlock brand new categories of solutions you’d never even have thought of otherwise.
So, you’ve finished a few Rails tutorials. You might have taken a class or two or watched some screencasts. You’ve followed along and built a copy of some tutorial apps. It’s pretty clear that it’s time to move to the next level in your Rails development.
Somehow, though, you’re stuck. There are tons of books, classes, and videos for people just starting out. But where are all the tutorials for intermediate Rails devs?
It’s not like it was before
Once you pass the beginner, “building baseline knowledge” stage of being a Rails developer, the resources dry up. Why is that?
Becoming an intermediate Rails developer is nothing like being a beginner. It might seem like it’s just a little different, with some more complicated stuff to learn. But passing through the intermediate stage of learning is a totally separate process.
Don’t think of it as, “A beginner knows this stuff. An intermediate developer knows all that stuff a little better, plus some extra things off to the sides.” For an intermediate developer, learning is more focused. Instead of knowing a little about a lot, you’ll learn a lot about a little.
Find a few areas to focus on. Learn more details about testing and TDD. Learn a few of the design patterns that Rails encourages, in depth. Learn about how you should design a great data model. But don’t learn it all at once. Learn one thing at a time, and learn it really well.
Once you understand the Rails basics, you’ll know enough to read API documentation, even if you don’t understand all of it yet. You could read the best books on TDD, even if they’re not written specifically for Rails. After you’ve seen enough examples of Ruby code, you can go source-diving and understand parts of Rails at a level that few others do.
When you concentrate on learning one thing well, there are many more resources to learn from. And each thing you learn will make every other thing easier to learn.
(If it seems easy for people to pick up their third or fourth language, this is one reason for it. A lot of the core concepts stay the same, which means there’s a lot less you have to learn to travel through the intermediate stage in a new language).
How do you choose what to play with next?
If you’re going to learn one thing at a time, you have to choose what to focus on first. But how do you pick, when there’s so much to learn?
Doesn’t it always seem easier to learn something when you’re interested in it? It definitely does for me. So, what’s the best way to force yourself to be interested in learning something new?
Write your own apps! Lots and lots of apps. Write apps, modify apps, add features to existing apps.
When you write an app, you will get stuck. You’ll get stuck a lot. But that’s a great thing! You should learn to love the stuckness, because it means you’re about to learn something new. Being stuck is awesome, and the more you can enjoy it, and even seek it out, the faster you’ll become an expert.
Once you research, learn, and write a solution, try to do it again in another app. Try to write it without looking at the documentation. Really learn it. Then, continue building your app, and watch for the next place you get stuck.
I love learning this way, because you get to focus on the stuff you’re going to run into most often. You’ll learn faster, because you’re not just studying to study. You’re trying to figure out how to solve a problem. And isn’t that why you fell in love with software development to begin with?
But you can’t get them all this way
After you understand the basics of Rails, you can learn serendipitously. If you understand what intermediate and expert Rails devs are talking about, you can accidentally run into conversations that will take your studying down really interesting paths.
You don’t have to read it all. You shouldn’t read it all. But let good stuff hit your radar, and try to read and follow the things that seem interesting. I’ve learned some really great tips this way, and they’ve led me into some useful topics I might not have encountered until much later.
So, what are you going to learn next?
If you’re feeling stuck because you can’t find great intermediate resources, take control of your learning. Start building an app, and pay attention to how you build it. Try something you’re only halfway sure will actually work, and seek out places you can get stuck. Use that stuckness, and find API docs, guides, or tutorials on just that small part. Go source-diving if you need to. (It might feel weird at first, but the more you look at Rails code, the more comfortable you’ll feel with it).
Really understand a small part, become an expert in it. And then, move on to the next thing.
You want to test-drive some code, but you’re stuck. Maybe you’re not totally sure what your object’s interface should look like. Maybe you’re distracted by another sunny summer day. You might not be sure you can test what you’re thinking of building. Or you could be procrastinating, because you just don’t feel like writing tests right now. How do you get the benefits of TDD when you don’t feel like TDDing?
Prototyping, or building one to throw away
“Where a new system concept or new technology is used, one has to build a system to throw away, for even the best planning is not so omniscient as to get it right the first time. Hence plan to throw one away; you will, anyhow.” — Fred Brooks
Sometimes, when I start a new feature, I’ll feel paralyzed when I think about writing my first tests. There are so many decisions to make about how the API should look, which patterns and practices will be most appropriate, and how it should all fit together.
I have a few ways I get started when I’m stuck like that. Building a prototype is another.
When you write a prototype, you should think of it like a sketch. Brainstorm and try things out. Don’t bother with tests or TDD yet. Instead, explore the decisions you’re having a hard time making, with code. Try out a few patterns, and see which of them fit the feature you’re trying to design. Figure out where the shaky parts of your app are, what needs more thought, and what you were worrying about for no real reason.
Then, throw it away and rebuild it. This time, using TDD and your newfound knowledge about how you can best build the feature.
You know when you accidentally run
git checkout -f after you wrote something, and you get that feeling like you just got kicked in the stomach? But then you figure, this has to be built, so I guess I’ll do it again, and it turns out much better than it did the first time? This is also true with rebuilding prototypes. Now that you have some solid ideas of how the feature could look, TDDing that feature will go a lot more easily.
Have you ever run into a situation where you know how to build something, but you don’t know how to write the tests for it first? Or maybe it’s a one-line change to a method, but it might need some tweaking, so you don’t want to lock it down with a test before you know what the change will actually look like?
There’s a simple process that helps a lot with these situations:
- Write the code, without tests.
- Write a test for the code. Make sure it passes.
- Comment out the code you wrote, or revert the file you made the code change in.
- Run the test again. Make sure it fails.
- Write the code again. Run your tests. Make sure they pass.
- Refactor the code, taking advantage of your new tests.
I think of this as Reverse TDD or Green-Red-Green-Refactor. You won’t get the “test-driven design” part of TDD, but you’ll still get to see your tests fail when your code is broken. That’s important, because you can’t trust tests that don’t fail at least once.
Reverse TDD usually works best with tiny changes that don’t need much design. Think bugfixes, or changes that are localized to a single line, method, or class. But I use this technique a lot, especially for small changes that I’m still playing with.
The Pairing Game
The Pairing Game is a great way to break out of your Red-Green-Refactor routine when you have another developer around. It works like this:
- Find a partner.
- You write a test that will break.
- Your partner tries to fix that test with the simplest code possible.
- You write another test that will fail on that code.
- Your partner writes code that will pass that test.
- At some point when the tests are green, you can choose to refactor some code instead of writing a test.
- After refactoring, swap tester and coder positions.
I’ll let you in on a secret: playing the Pairing Game on a bowling score calculator is how I originally learned TDD. It’ll help you practice writing simple code based on failing tests, and writing those tests to begin with. Both developers will learn a lot about each other’s coding style and favorite techniques. And you’ll hit flow almost immediately, which means you’ll feel great when you finish.
You might not produce code as quickly, but it’s a lot of fun, and a great learning experience.
Stay playful and experiment
TDD shouldn’t be dogma. There are ways you can play with the core TDD concepts that can lead you to some really interesting places. And you might end up with even better code.
So experiment. Try new approaches to writing code and TDD. See how they make you feel, and what kind of code you end up with. And keep rediscovering the fun and the flow in the work you do each day.