Interesting And Unexpected Benefit Of Pattern Matching

So recently I’ve been working on automating some interactions with a website.  Elixir’s Hound library is a great help, of course.  But I also ran across an interesting and unexpected benefit to pattern matching that greatly simplified some code.

I was trying to dynamically build a URL to pass parameters. The URL would be in the form:

http://www.exampledomain.com?param1=p&param2=q&param3=r

Whenever I see code like this, it’s always a little tricky because you want to add the & at the end of each parameter except the last.  This always used to entail writing a special case in the loop to test if the index of the current element was the maximum index.  But with pattern matching and recursion there’s a much simpler and cleaner solution.  Like this:

defp add_params_to_url(url,[%{:name => name, :value => value}]) when is_binary(url) do     #1
 "#{url}#{name}=#{value}"
end
defp add_params_to_url(url,[%{:name => name, :value => value} | t]) when is_binary(url) do   #2
 url = "#{url}#{name}=#{value}&"
 add_params_to_url(url,t)
end
defp add_params_to_url(url,[]) when is_binary(url), do: url   #3

This is Elixir for those unfamiliar with it.  Basically it’s three function clauses.  The first clause (#1) is hit if only one element is in the list passed into the function. The second clause (#2) is hit if multiple elements are present in the list and the third clause (#3) is hit if the list is empty.

So this is how this works.  When I call add_params_to_url, Elixir will automatically try to match the correct function call dependent on which list I pass.  It will also stop at the first function clause which matches so that other function clauses will not be evaluated.

If I pass a list of URL params which has only one element, clause 1 is matched and the parameter and value are appended and I’m done.  The URL already has the ? on the end, of course.  If I pass a list of URL params with mutliple elements, clause 1 doesn’t match so Elixir jumps down to clause 2 and that matches.  Clause 2 takes the first element from the list tacks it on to the list of parameters with a & at the end and then recursively calls itself with the tail of the list.  If the tail of the list contains more than one parameter, clause  1 will once again fail to match and clause 2 will match again.  If it contains only one parameter, clause 1 is matched.  Because clause 1 doesn’t call itself recursively, clause 3 should never be matched; it’s actually more of a guard case in case someone calls the function with an empty parameter list by mistake.

This, to me, is a small bit of genius.  Much simpler to get exactly the effect I want, that is not having an extraneous character tacked to the end of the string, and it’s nice and simple.

By the way, it occurs to me that I might be able to use a reduce or a fold function to achieve this same effect.  The issue there is that it’s less apparent what it is that I’m trying to do and I also run into the same problem–that is, how do I deal with that last element in the list so I don’t get my separator appended?

The Most Important Quality Of A Unit Test

I assist with the face to face interview of software engineers at our firm.  One of my favorite questions to ask a candidate is “What is the most important quality a unit test should have?”  I’m surprised at how many times I get a blank stare; I mean I would at least expect something along the lines of “It should test all the code in a given unit” or “It needs to be isolated to only a single unit of code” or some sort of response. 

To me though, the right answer is “The most important quality of a unit test is that it has to be easy to run.” If you ever interview with me at my firm, bonus points for you if you quote my answer back to me. 

Why “easy to run”?  Any thing that takes any sort of effort beyond the ordinary will rapidly become something that the developers don’t do.  We all have impossible deadlines and if we have to wait a half-hour after we make a change while our unit tests run, we’ll quickly figure out some way to avoid running them.  It doesn’t matter if you have the most brilliantly written unit tests in the world and they execute all of the code in the unit in a way that would have made Edsger Dijkstra weep with joy at its elegance; if it’s not run by the developers it’s not doing you any good.  If you’ve mastered dependency injection and all of your unit tests are very flexible so that they can be changed without any effort whatever, it will do you no good if the developers don’t run them because they report lots of false positives that no one has ever troubled to fix.

This is the point—make the unit tests dead simple to execute, make them fast and fix bogus tests.  Anything else you do with your unit tests is wasting your time unless you address these fundamental concerns.