Nothing Undone

A weblog, by Peter Jaros.

Another Whac-a-mole Strategy.

If you write software and you’re not watching Gary Bernhardt’s Destroy All Software, do yourself a favor and subscribe. It’s not expensive, it’s fun, and it’s good for you.

A couple of weeks ago, he posted episode #69, Conditional Whac-A-Mole, which describes several ways of removing a conditional.

In the example, a user needs to be followed in a different way if they’re marked “private” than if they’re not. (Think of Twitter users who have “private” accounts. The user needs to approve any new followers.) One of Gary’s solutions was to have two different types of users, PublicUser and PrivateUser. Each implements #follow differently. Gary says he doesn’t like this version because fundamentally they aren’t different things: they’re both Users.

I agree, but I think we can tighten up the polymorphism to something more flexible:

And the test, slightly modified from Gary’s original to use the followabilities:

Now, I wouldn’t go this far for something this simple in a real app. Also, it’s not likely we’ll need a new kind of “followability” any time soon. Public and private are pretty much our options. So for this example, I’d agree with Gary.

But I think this illustrates the Strategy pattern well. It’s not the User itself that’s polymorphic, it’s its followability. And, by telling the follow, not asking the user if it’s private, the User class gets to make that implementation decision. It does break up the following logic among various classes, but they’re built to be small, and could easily go in the same file.

Meanwhile, if you need a new kind of followability (say, you can only be followed by people with 100 or more followers of their own), you can write a new followability anywhere, and use it:

class PopularFollowability
  def follow(user)
    Follow.actually_follow(user) if popular_enough

user ="pickyguy",

And notice that we did that by extending the user without modifying it.