I had the pleasure of appearing on the Ruby Rogues podcast this week talking about how Pivotal Labs does Extreme Programing (XP). Accompanying me was ex-pivot Josh Susser, James Edward Gray, Avdi Grimm, and Charles Max Wood. I had more fun recording it than I would have imagined and the pivots here have enjoyed listening to it, I hope you will too!
The passing of time, and all of its crimes.
Programmers are constantly implementing time-related features, and accidentally including time-related bugs. I’m one of those programmers, and I would like to reduce the number of time-related bugs that I write. Some of them are small mistakes: time zone issues arise when running a test suite on a machine in a different time zone. These bugs are often fixed with consistent use of the time zone feature of a given time library. Others are more sinister, and lurk deep within the design of a system. They manifest in places where it’s tricky to get the system into a certain state because it is so heavily dependent on the current time. I propose that designing for the ability to set the current time from the outside of the system reduces the prevalence of timing related bugs, and has the happy accident of making code more reusable and testable.
How testing exposes this problem
Testing has many forms in the world of software. There are automated acceptance tests, unit tests, functional tests, enemy tests and so on. There are also tests carried out by humans. Sometimes referred to as ‘click testing’ or Quality Assurance, this kind of testing is an essential part of the process of delivering working software. At Pivotal Labs, it’s usually the Product Manager who has the final say about whether a feature is complete, or a bug is fixed. In order to evaluate whether a feature is ready, the PM exercises the area of the application in question, using the interface that a customer or stakeholder has been provided with.
When testing software with a mouse and keyboard becomes difficult, however, it often doesn’t get done. When it doesn’t get done, bugs introduced by diligent programmers, who test-drive their code, are missed and end up making their way into production.
After a few cycles of missing bugs like this, a team will look for ways to ease the pain of click testing their app. The programmers on the team might come up with clever, easy-to-implement solutions to this problem:
- “We can manipulate the Time library to give us the time we want”
- “We can change all of the data for a given account to pretend that it was created in the past”
When these sorts of techniques dig in, new problems arise. In the former case, you can end up with code that works when the fake Time library is used, but not when the real one is used. In the latter, you are committed to a maintenance chore: when a timestamp field is added, it needs to change along with the rest, and when the code that changes those fields gets out of sync with how things really change over time, more bugs arise. It becomes difficult to tell which bugs are genuine and which are a consequence of artificially shifting time data.
It’s usually programmers who propose the above solutions. We often think in low-level terms like libraries and direct data manipulation. From a Product Manager’s perspective, however, what’s really needed is a design change. One could imagine the user story presented to the team like this:
As a Product Manager
I want to travel in time
So that I can test, for example, that an account gets billed each month
Time travel sounds like science fiction. How could a user of your system possibly travel in time? It turns out that there are low-level solutions to this. For example, Timecop, which many of us at Pivotal have contributed to. If depending on the passing of time is your addiction, then Timecop is enabling you. It lets you easily manipulate time, usually for automated testing purposes. For example:
Timecop.freeze(1.month.from_now) do
future_time = Time.now
sleep 10
future_time == Time.now # this is true
end
Here we’ve frozen time to pretend that it’s one month in the future. I can imagine some cases where this would be useful (not least in existing systems that are infected with code coupled to the current time), but in a lot of cases this is just wrong. Under what circumstance do you actually expect your code to be frozen in time? What are the consequences of testing code under these conditions?
Perhaps most importantly to the topic of this post, Timecop lets you forget about managing time at the unit level, and doesn’t encourage you to build time controls into your application.
I think there are better ways to get a grip on time that we should all consider before reaching for the magic wand. Let’s look at some real-world problems that can occur and then look at ways of building time control into an app’s design.
Examining the moment
Let’s think about the properties of the current time:
- There is only one current time, unless you’re modelling multiple realities e.g. storylines about time travel.
- Its value is always changing.
- Everything is potentially affected by it.
So, the current time is a global, constantly mutating singleton. We know that the presence of global singletons is undesirable, because they are polluting. We also know that mutation ought to be contained, because mutable state makes our programs less predictable and harder to reason about. If a function deals with mutable state, then it might have different results each time it is called, even when it apparently has the same inputs.
Let’s look at a timing bug that can result from the fact that the current time has these undesirable properties:
policy = Policy.find(1)
if policy.current_state == :active
notify_customer("You are still insured!")
end
# more code goes here
if policy.current_state == :inactive
notify_customer("You are not insured. Hope you weren't planning on driving anywhere today.")
end
Imagine that the above code is within a web request. The request comes in at a certain time, and the customer wants to know whether their insurance policy is current. The code above is deep in the guts of a model somewhere, and gets called after the customer has been authenticated, their request has been authorized, and their account record has been pulled out of the database. Now it’s time to see what the state of the policy is, so we use a method someone wrote (current_state) that fetches the current time and returns a state based on whether the policy’s end date was before or after that time.
The customer sees this on their screen:
You are still insured! You are not insured. Hope you weren't planning on driving anywhere today.
The policy could potentially be active on one line and inactive the next. This kind of bug gets worse when one line makes an external call if the object were in one state, and the next makes a conflicting call if it were in another.
I recently ran into a real bug similar to this on my current project, which was caught when an acceptance test I was writing would fail on one run and pass on the next. The temporary workaround was to memoize the method that checked the current state (current_state above). Unfortunately, this introduced even more mutable state, because memoization requires changing the state of an instance variable. The next programmer might wonder why fetching the current state works the first time he asks, but stays the same with consecutive calls.
current_nothing
The current_state method is guilty here. But what of? It has a hidden input, which is the current time. It’s not explicit, and that’s where the confusion lies. It wouldn’t make sense to have a method called current_something and have it take the time as an argument, because the prefix “current_” implies that it’s supposed to know what the current state is.
The internal functions of a program shouldn’t know this stuff. In most web apps, a request is made at a certain point in time, but it’s not important that the request takes some time. With most scheduled jobs, the job is run at a certain time, but it’s not important that the job takes some time (or if it is, it’s stored as metadata).
A name less prone to attracting this kind of bug might be state_as_of(time). If we force ourselves to pass the time as a parameter to all of our low-level functions, then we can:
- More easily unit test the basic correctness of the method without resorting to stubbing out the time with Timecop.
- Force out a decision to be made about what moment the lower-level methods should be operating on. Ideally the control would move as high as possible: to the controller level, or in the case of jobs, to the job itself, or to an environment variable.
A word about scheduling
Scheduled jobs are often concerned with when they think they’re being run, but a PM doesn’t want to wait for a month to see if, for example, the billing system is working. It’s important to give control over when a job thinks it’s being run to the PM or other person evaluating whether a system works. This might mean dropping your out-of-the-box scheduling interface for the purposes of feature acceptance.
Resque-scheduler has become very popular amongst developers as it’s easy to install and provides a cron-like syntax for declaring when jobs are run. It also provides a GUI for triggering scheduled jobs immediately. Unfortunately, there’s no way to set parameters for the jobs, so the time can’t be set. If you choose to heed the advice in this post and parameterize time, you’ll need to provide your own interface for passing the current time into the system. This is a good idea anyway. See GOOS for a good treatment of externalizing event sources, which goes even further than the suggestions in this post in many ways.
Making time a parameter to your jobs can often make the jobs more reusable. For example, I might want to invalidate all sessions in a particular time range because there was a system fault at those times.
A word about external dependencies
What happens if your external dependencies are dependent on the current time? Well, you’re going to have problems with that no matter how much control you build into your system. I would argue that the services should be wrapped, and the wrappers should allow the time to be passed in to fake responses if necessary. The acceptance (as in story acceptance in Pivotal Tracker) of your system doesn’t have to depend on the state of the other systems.
A word about customer-facing status pages
What if your customer needs to be shown what’s happening right now?
I think the trick here is to depend on the order of time, and not the passing of time. To move into the future, we should be reacting to events by adding data, not mutating it. A database can easily figure out what the latest order is, or what the latest billing cycle is. It doesn’t have to be a function of the current time.
If, however, it’s just too difficult to implement the functionality without checking the current time, it could be argued that the current time be a parameter passed in through the browser, available only in certain testing environments. I would resist this as far as possible, but think that it would be a preferable solution to mutating the state of the database.
Everything I know about Clojure after one week
This week I decided to clear out the cobwebs of my Ruby-trained brain and try a completely different language. Ruby and Rails have been my staples for over seven years, and I’m starting to tire of my patterns of thinking, and of the common problems found in large Rails applications. Specifically, I’m pretty bored of running into slow test suites and difficult-to-maintain apps. I suspect the primary cause of these problems is the entanglement of business logic with database and other stateful resource code. I get the feeling that it can’t be just coincidence that so many teams of competent developers fall into the same old traps.
I’d heard a bit about Clojure, so decided to explore the ecosystem and community. I’m attracted to the idea of learning a functional language, avoiding mutable state and re-evaluating the object oriented programming paradigm. Functional programmers are often accused of being “idealistic”, “academic” or a variety of other thinly-veiled primitive insults. If nothing else, I could learn to sympathise with these crackpot underdogs who claim to have the cure for most of the technical pain I suffer in my chosen occupation.
Hopefully this assortment of links and lessons learned will encourage you to try out the language, or inspire you to try something else that’s refreshingly new.
Clojure is easy to get started with
There are various tutorials online. However, they can be a little out of date. The quickest route to Clojure hacking is via leiningen, a sort of rake-meets-bundler utility. Assuming you’re on a Mac, have homebrew installed, a recent JDK and the usual code compilation dependencies:
brew install leiningen
lein repl
That’ll pull in Clojure for you. Once you’ve had a play in the REPL, use leiningen to generate an app:
lein new my-test-projectThe project.clj that the above command generates is the equivalent of a gemspec, and declares the dependencies of your app. Leiningen helpfully fetches dependencies lazily when you start a repl, server or run tests. No bundle install step!
Homebrew can also install Clojure for you, but this version will be independent of leiningen apps. When you install it, you’ll be recommended to use a REPL wrapper for rlwrap. I’ve found that the one from the wikibooks site works better (i.e. at all).
Rich Hickey is an entertaining figurehead
Rich Hickey, creator of Clojure and designer of Datomic, the FP-friendly database system everyone’s talking about, has some inspiring talks from the end of last year about Clojure and Datomic, and notably why everybody is doing programming wrong. There are some pretty strong views in the talks, but they’re a refreshing take on the sociological patterns in our industry, and how project pathologies can be treated.
There’s an active community
Many clojure developers are ex- or current-Rubyists. For example, Jay Fields maintains the expectations testing library (more on this below).
Clojure has artsy cred, too: there are several videos on the web showing Clojure being used for live music.
Syntax change requires healthy brain re-wiring and thought simplification
After spending so much time wrapping my head around object-oriented constructs and trying to work out how best to structure OO programs, it’s a refreshing change to work with a functional language. Not having a CS degree, I’d previously tinkered with Scheme following a workbook. I wasn’t put off by parentheses, but did have some fears that I’d be transported back to the bad old days of the top-level PHP namespace. I soon realised, however, that my beef with PHP was mainly the aforementioned comingling of state and logic, as well as the inconsistencies of method signatures and names.
Clojure philosophy is all about consistency and reuse. I’ve trained myself to believe that reuse is all about identifying concepts, naming them and adding an abstraction, often a named value object. I’m pretty attached to my explicitly named classes of values, like SubscriptionEvent or PersonName. This is largely in reaction to the recognisable OO smells like Primitive Obsession. The problems inherent in such smells generally melt away in the FP world, since you’re encouraged to use the built-in types to provide equality and the like, and to use the common functions like map, reduce and so forth to achieve what you would do in OO with a value object’s methods.
Web development is potentially full-stack
This is worth knowing if you don’t already: Clojure already compiles to JavaScript in the browser, as well as to Java on the server. So we potentially could be doing single-language full-stack development like node.js but without the oft-cited pitfalls of JavaScript. An excellent resource for newcomers to Clojure is this translation between JS and Clojure.
I’ve begun a project for playing around with the Compojure web routing library. Compojure forms the basis of many Clojure web apps, and I’m using that repository as a place to stick my learnings. I’m test-driving each new feature, so that it might serve as a reference for other newcomers on how to do TDD for Clojure web apps.
TDD is easy, fast and totally not banned.
Watching the Hickey talks, you might come away with the impression that the Clojure community is anti-TDD. However, there are some excellent developments going on in this area, such as the aforementioned Jay Fields’ expectations library, which provides an achingly simple way to express intent in tests. See my first attempts at testing a web app for an example of this. Structural whitespace optional.
Monads still a mystery
One week just wasn’t enough. See if you can figure it out and send me a postcard with a succinct summary.
Until next time!
Hash#fetch with confidence
Hash#fetch is stricter about key presence than Hash#[]
{}[:foo]
=> nil
{}.fetch(:foo)
KeyError: key not found: :foo
If you forget to set an ENV variable, would you rather your application fail late or immediately?
ENV['TWITTER_OAUTH_TOKEN']
=> nil
ENV.fetch('TWITTER_OAUTH_TOKEN')
KeyError: key not found
It’s especially interesting when a key with a truthy default is explicitly set to a falsy value.
options = {on: false}
@on = options[:on] || true
=> true # yikes, ever fallen into this trap?
@on = options.fetch(:on, true)
=> falseFailed attempt at trying to use refinements
I was pretty interested in refinements in Ruby 2.0, and after listening to the latest Ruby Rouges podcast where some serious doubts were raised about the viability of refinements I thought I’d build a little example of how I was thinking I could use it.
I failed first time out and I tried copying and pasting examples without success. After some time poking around I found a blog post about why this wasn’t working. Ultimately, refinements are sort of left in the language, but not fully supported and are marked as experimental.
Here’s what I wanted to achieve. Coming from Scala in my previous job, I thought I could use refinements as a proxy for implicit conversions. Here I refine the Fixnum class to allow it to respond to a to_currency message. When called it converts the Fixnum instance to a Currency instance.
class Currency
attr_reader :units
def initialize units
@units = units
end
end
module CurrencyExtensions
refine Fixnum do
def to_currency
Currency.new(self)
end
end
end
class App
using CurrencyExtensions
def initialize
puts 3.to_currency
end
end
App.new
Why is this interesting to me? Well, I think being able to write 3.to_currency can result in nicer to read code than the alternative Currency.new(3). Small difference perhaps.
There is a way to get this to work by having the using keyword in the global context, but it doesn’t deliver the full impact I was hoping for.
class Currency
attr_reader :units
def initialize units
@units = units
end
end
module CurrencyExtensions
refine Fixnum do
def to_currency
Currency.new(self)
end
end
end
using CurrencyExtensions
puts 3.to_currency
I’ve got other ideas to build upon this if it ever makes it into the full specification. I’ll keep watching for now.
NY Standup: Documentation interpolation and RVM, Brew and autolibs FTW
Interestings
Grant Hutchins / David Lee
If you wrap the opening name of a Ruby heredoc in single quotes, its insides will act like a single-quoted string.
If you wrap the opening name in backticks, the heredoc will be immediately executed through system()
<<-HEREDOC
1 + 2 = #{1 + 2}
HEREDOC
=> "1 + 2 = 3\n"
<<-'HEREDOC'
1 + 2 = #{1 + 2}
HEREDOC
=> "1 + 2 = #{1 + 2}\n"
<<-HEREDOC
uname
date
HEREDOC
=> "Darwin\nMon Apr 1 17:50:43 EDT 2013\n"
Found at http://jeff.dallien.net/posts/optional-behavior-for-ruby-heredocs
rvm autolibs
In the latest versions of RVM, you can have RVM build dependencies automatically for you. For instance, if you use Homebrew, you can run
$ rvm autolibs brew
and from then on, RVM will automatically build any packages it needs via Homebrew.
As always, read "brew doctor" to get more info about how to set up your particular system.
Start small and compose: A strategy for using FactoryGirl
While I’m still not entirely sold on FactoryGirl, I often see it being used in a particularly lazy way. Imagine your basic factory:
factory :projectBefore long you’re adding relations to projects, and the first thing people do is this:
factory :project do
association :user
endThis immediately means that every single time you instantiate a project, you’re getting a user as well. In most cases this is more than you want, and if you continue to follow down this path you end up with a huge slow test suite. I prefer a slightly different strategy: start small and compose.
factory :project do
...
end
trait :with_manager do
association :user, factory: :manager
end
This defines a very simple factory :project which gives you only a project and allows you to build a project with an associated user like so:
FactoryGirl.create(:project, :with_manager)The result is a couple more arguments when you use the factory, but the overall code is more intention revealing.
If this is too much, you could always create a more descriptive factory:
factory :managed_project, parent: :project, traits: [:with_manager]If you stick with this strategy, you’ll find that tests are more concise, factories are more useful and your test suite run time won’t grow as fast.
method_missing hazardous to your module?
We built an(other) object factory module for our current project and it looks a lot like all the others:
Building identical gems
We ran into a problem where we were running `gem build` on identical input files and the built gems had different checksums; that is to say, if you run `gem build` twice in a row, the resulting `foobar.gem` files will not be identical.
A .gem file is actually a tar file (not compressed) containing two gzipped files (manifest.gz and data.tar.gz). What’s happening, as far as we can tell, is that gzipping a file embeds a timestamp somewhere in the file — here’s a gist of a Bash session that demonstrates just this idea:
Apparently gzip on its own can exclude the timestamp, but that option doesn’t seem to be exposed through tar.
So how do you build identical gems from the same input? As far as we could discover, that is not supported through any `gem` commands. To normalize a gem, you would have to untar the .gem file and then decompress the files inside; then you can do a full comparison of those contents against another .gem file that went through the same process.
How to simultaneously display and capture the output of an external command in Ruby
There are many ways to run external commands in Ruby: surround with backticks, enclose in %x{}, call Kernel#system…
None of those approaches let you display the output of the command in real time while simultaneously capturing the output. Here’s a gist showing how to use IO.popen to capture output, display output, and check exit status: