My talk at Conj 2015, enjoy! Teaching Clojure
(All these great ideas, but no one is listening? Check out my book: Convincing Coworkers)
One day, I went into an interview, and I was humiliated.
I used to think very highly of myself. This was early on in the Test Driven Development (TDD) craze, and I was one of the best I knew at it. I knew interfaces, classes, mocking frameworks, and best practices. I’d been taught all the tricks from some very smart people, and my confidence was high. Not only that, but I’d just finished at work the restoration of an abandoned legacy codebase to a bug-free, fully tested state completely on my own.
I’d shipped Java, PHP, Perl, C#, and VB.NET, and I hadn’t been programming more than a couple years. My first job, they’d made me a team lead over some very senior developers within a year of my hire date. I was learning Clojure and Common Lisp, and had just shipped an Android game I made entirely alone (including the 2D physics engine).
I thought I was incredible. Yet, due to an overwhelming sense of Imposter Syndrome, I keenly knew that there were things I didn’t know. I’m mostly self taught, so a lot of common CS concepts felt alien. I was waking up before work and teaching myself algorithms, lisps, and math.
Enter Company A.
I flew through the phone screen “this is the best phone screen we’ve seen!” Of course it is. “Your resume is very impressive.” Oh, I know!
I get to the on-site interview.
I hadn’t been thoughtful enough to ask what to wear, so I wore a suit. I was asked to present a project I’d worked on, and I picked my recently shipped physics game that was up on Google Play. I walked into the reception area a few minutes early.
"You are 25 minutes late."
What?! I explain that I have the email saying 9:30! No matter, “hurry, they are waiting!” Maybe I can salvage this. I walk into a conference room with a dozen people sitting around a table looking bored and pissed.
"Let's see your presentation."
I start to open up my laptop. Meanwhile they start to joke around to each other:
"Oh, wow, Linux, what is this, 2003? I'd hoped I'd never have to see the grub boot screen again! Can't you afford a real machine?"
I try to joke back while multitasking with my laptop. They only have the Mac projector cable. No adapter. I’d thought ahead, and handed one of the developers a thumb drive with the presentation and code. Meanwhile the interviewers are joking and laughing to each other at my choice of clothes.
"A suit, classic, where are you interviewing after this, a sales job?"
I roll with it, make some joke about “styling”. I start presenting about the 2D physics engine I’d written as a learning project for my game. One of the most interesting parts to me was how I’d first written it without any unit testing, following just Clean Code practices. I then re-wrote it using heavy TDD. The design turned out very different both times, which I thought was interesting to see how TDD had influenced the design.
About five minutes in, I am cut off:
"This presentation is bullshit. You have no evidence, nothing valuable to show, just spurious subjective opinions. You've put up a straw man and now are trying to knock it down assuming we are idiots. I've seen enough."
At this point, it has been barely 15 minutes since I walked in. I remain calm and professional, and start to address the raised concerns. I play the meta-game, wondering if perhaps this is a test to see how I’ll react when questioned and embarrassed. Even if this wasn’t a test, I was determined to be at my most professional and finish with my head held high.
Five developers walk out before I can finish my first sentence. One of the remaining six interviewers looks embarrassed and asks if I could live code them a web scraper in any language instead of the presentation. I turn my laptop around (still no projector) and ask if PHP is acceptable. They are a Python shop, and PHP is the closest to what they use that I am comfortable using when this nervous.
"PHP? Gross. I suppose if it is all you know..."
Unfortunately, I’ve got so much adrenaline in me that it takes me a few tries to log in. I get on a roll after five minutes, and write the scraper. They throw me a few more requirements, and within a half hour I’ve written stories for and completed them all. At least two of the interviewers seem quite impressed. Someone looks at their watch, “well, that’s all the stories we have, I guess let’s break for lunch.”
Lunch is a 35 minute walk up a hill in humid 93F weather, and I am wearing a suit and dress shoes. When we get back from lunch I am hot, tired, and foot-sore. I distinctly remember my feet blistering inside my sweat-soaked patent leather shoes. I am called into the conference room again. At this point, I am genuinely curious if this is some sort of extreme patience/calmness test, or if I am being filmed for a reality show. No such luck.
At the head of the table is the developer who “called me out” for my presentation. Apparently my lunch mates were supposed to only take an hour, we took almost 90 minutes. He looks at me, rolls his eyes, and asks in the most sarcastic tone I have ever heard:
"So, got any questions for me?"
I ask a few normal questions, meanwhile he is constantly checking his watch and rolling his eyes. He answers briefly and rudely. I thank him for his time, and ask him if there is more. He laughs.
"Oh, we are done here."
I am shown to the door.
I sit in the car for a half hour, wondering what just happened. I look over to the passenger seat piled high with text books I have been studying, books on language design, compilers, algorithms, physics engines, TDD, and productivity.
I was asked none of it. I threw up from stress out the car door into their parking lot.
I found out later their recruiter had given me and many other candidates the wrong time. She was fired shortly after.
I never found out if I had done something to make everyone so angry. I now suspect that they were massively turned off by a host of things. Polyglot programming, practicing TDD, the suit, the not Mac, the late arrival, and a bad presentation probably all contributed to an immediate disqualification. I rationally realize they were terrible and treated me terribly, but the embarrassment is still there. I suspect my presentation was terrible from the get go: that they were expecting some rock-star and instead got me.
A number of times I have woken up in a cold sweat having dreamt about that interview. In the large scheme of things, a bad interview is such a small thing, but fear is fear. I still to this day wonder what I did wrong. Was I arrogant, cocky, insufferable? Did my ego cause them to treat me that way, or was it all them? What could I have done differently? I was only in there for a few minutes!
Few events in my professional life have shaped me as much as that interview. I have turned it into a forge for my talent, the anvil on which I beat my pride. When I don’t know something, I am more willing to shrug and laugh it off, all while learning as fast as I can. When I am humiliated professionally, I know I’ve come through worse and thrived.
Break The Cycle
This story fills me with an overwhelming desire to never continue the cycle of abuse. I strive every interview to try to respectfully work with the candidate, and never humiliate them. I want every person I interview to leave feeling loved as a human and respected, even if they are completely incapable to perform the duties of the job.
When I ask a question, if they struggle, we work it out together. When I ask for code, we write it together, even if that means I have to do all the work. I can make myself their servant, while still assessing their skill with accuracy and dispassion. Those with the skill will show it, and those without will not feel humiliated. I let them interview me, and if that means they want me to go up to the whiteboard and struggle through a merge sort, so be it. In this way, I push back against the interview culture that normalizes degradation and humiliation.
If you are interviewing others, take a serious look at your practices. Would a failed candidate feel humiliated and disrespected? What will they tell their coworkers and friends at meetups about your company? Will they talk about feeling respected, and how they hope to get the chance to work with you one day? Or will they talk of a group of self-righteous jerks who abuse their power to make others feel small? You can break the cycle.
(All these great ideas, but no one is listening? Check out my book: Convincing Coworkers)
If you are considering using F#, you might be curious how to handle unit test mocking, especially if you want to use both modules and classes. In a language like C# or Java, the common method is to a DI container or handmade constructor injection on a class. These “entry points” allow for a unit test to replace a real dependency with a test-only replacement.
I previously posted an example that shows a much simpler way to inject dependencies called the SimpleMock pattern. The SimpleMock pattern can also be used in F#, even if you are only using modules.
SimpleMock in F# Modules
We will assume you are mocking inside a module and not a class. Mocking inside an F# class would look much the same as it does in C#, which we showed in the SimpleMock post. Here is a sample program that does some work and persists the results.
1 2 3 4
To apply the SimpleMock pattern, we can use argument currying by adding a simple function wrapper.
1 2 3 4 5 6 7 8 9 10 11 12
We started by renaming the
addAndSave function with a trailing
created a new
addAndSave that calls
addAndSave' with the correct
dependency for the first argument, leaving the rest of the arguments to be
called later. Currying is what allows this ability. The new
function only needs the
y parameters. At test time, we called
addAndSave', passing in the needed dependency, but using a lambda as the
“fake”. The injection is as close to the dependency use as possible!
Bonus: SimpleMock Fake Helper
The earlier replacement for DBModule.saveSum is a bit complex, and it does not show us how many times the fake was called. We can easily make a helper that takes parameters and returns them when called, along withe count of times it was called.
1 2 3 4 5 6 7 8 9 10 11
The above code might be hard to comprehend at first! We have made a generic
helper that can create any single argument fake we need. We return a tuple,
containing the fake lambda and an instance of
TestFakeResults. The fake
lambda will populate the
TestFakeResults, which we can access in the test
via the second arg of the tuple.
We can now re-write the previous test using
1 2 3 4 5 6 7
The TestFakeResults can return information about the way it was called, including the list of all arguments. If we felt we needed the extra expressiveness, we could also use a mocking library like RhinoMocks or Moq. The TestFakeResults and its constructor are not essential to the pattern. The most important part is learning to unit test in F# with confidence.
Double Bonus: When to Use a Class Instead of a Record
When I first wrote this post, I used a record instead of a class for the
TestFakeResults type. If you have been bitten by the functional programming bug,
you might have wondered at my usage of a mutable class. Here are two alternates
makeFake_OneArg which use records. You can probably see why I switched to a class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
The only way to use a record is to delay its construction via a lambda which must be executed by the test code. Both are complex: what we need is a mutable data structure which we can access via a reference. A record is not that. We can approximate it using tricks, but ultimately I find both alternatives to be too complex to justify their use. Sometimes a mutable data structure is the best choice to solve your problem efficiently. The power of F# is that it gives us the ability to choose the best tool for the job: records for immutability, classes for mutability.
SimpleMock is a pattern for reducing TDD damage. You can use the pattern to organize your testing code without mocking or complicated dependency injection.
SimpleMock works in any language with closures that can be passed around by reference, so off the top of my head: C#, Java, F#, Scala, PHP, C++, Ruby, and Python. I’m sure you can think of others.
Here is a brief (if a bit silly) example of the final pattern:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
- Reduced boilerplate
- Saves interfaces for real polymorphism
- Simplifies test code
- Reduces testing concerns in production code
- Removes need for fragile IoC containers
- Encourages better abstraction design
- Can convert one class at a time!
The SimpleMock pattern promotes a better design of your abstractions and simpler tests. The pattern also reduces boilerplate and the pollution of your production code with testing concerns.
If you aren’t familiar with the normal pattern of unit test mocking using interfaces, dependency injection, and mock libraries, scroll down to “The Non-SimpleMock Way” at the end of the post.
The SimpleMock pattern is aptly named.
- Replace Test-Only Interfaces With Functions
- Define Dependencies Inline
- Write Better Abstractions
Step One: Replace Test-Only Interfaces With Functions
My examples are in C# because that is what I got paid to write today - it is freshest in memory. C# has an incredible ability to create and pass around lambdas and function references. Here is an example of using functions instead of interfaces.
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 26 27 28 29 30
The test code is quite simple! No longer do we need the dependency on third party mocking libraries, or the relatively complicated setup logic. Instead we can simply inject the lambda at runtime, replacing that pointer. We didn’t need the whole interface, really we just needed the simple signature of the function.
Step 2: Define Dependencies Inline
We can take it even a step further. Why use constructor injection at all? Since all we really want is a single mutable dispatch table row, why not just make it that way?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
We’ve cleaned up our nasty multi-line indirection into a single dispatch line. “Go to definition” now takes me to the actual line with the actual called function. We’ve replaced a dependency on a class based interface with a function signature. The function signature is the interface!
You probably noticed we have lost something with this final version. We have lost the ability to inject polymorphic behavior through the constructor. If you need it, simply go back to injecting the interface in the constructor or by passing it into the function itself. In practice, I have found this is needed very rarely, making the SimpleMock pattern a better tool to reach for first.
Step 3: Write Better Abstractions
Lastly, SimpleMock actually promotes better designs. For example, a coworker was writing some tests today and ran into a complicated situation. Take the following sanitized code:
1 2 3 4 5 6 7 8 9 10 11
How would you check that each section was called? Our naive solution was a complicated lambda with a “timesCalled” counter and an if statement to assert against each argument, but it turns nasty quickly:
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 26 27 28 29 30 31
Yuck! The test is an absolute catastrophe. I see a mess of mixed concerns. Conditionals?! In a test?! Unconscionable.
In situations like this, we have two easy options. Option one is to just use a third party mocking library, replacing the functions from inside the test code. This gives us access to all the sophisticated mocking tools available.
My preferred option is seeking to decomplect the production code by using better abstractions.
I have found that strong reliance of mocking libraries enables worse designs. Consider the code, what makes it so hard to test? Not knowing which element is called when, doing the same work on two parameters, and reference mutation all make this a poor abstraction. Why not simplify?
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 26 27
Much better! Yes, we had to change a few signatures. We get the same work done, but now the code is actually a lot more useful. Our test code is comparable with anything you’d find using a mocking library. I am absolutely okay with using a mocking library when needed, but I always carefully consider my abstractions and design first.
If mocking libraries and IoC containers are the chainsaws of the testing world, then SimpleMock is the garden shears. Sometimes the chainsaw is the only tool for the job, and that is fine. But for most work around the yard, you can leave the chainsaw in the shed.
I’ve shown how you can really simplify your code with SimpleMock. The dispatch row is clear and easy to read. We have removed some third party mocking dependencies. You can remove a lot of the boilerplate “for making it more testable” from your code. The test code is greatly simplified, and injection a breeze. The result: much simpler code, just as easy to test.
Thanks to Shuwei Chen for helping me put this together!
The Non-SimpleMock Way
If you are familiar with unit test mocking with interfaces, this part is probably boring. Feel free to skip.
The traditional way of performing C# unit test mocking involves dependency injection and interface mocking using a mocking library. For dependency injection, it is common to use a tool like Ninject or hand-rolled constructor injection. For mocking, a library like Moq or Rhino Mocks is standard. Here is an example of a class and its testing code without any business logic.
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 26 27 28 29 30 31 32 33 34 35 36 37 38
If you’ve done much C# unit testing, this should look familiar. We want to inject some code that is potentially long-running or dynamic. We put that code into a class, add an interface, then inject that interface into the class we want to test. To test it, we mock the interface, creating a different concrete class at test runtime which implements that interface. We can setup that mock to respond with anything, which we use for assertions.
What’s Wrong with the Non-SimpleMock Way?
The first problem is we have created a whole interface just for testing. Interfaces are for polymorphism, but we don’t really need polymorphism for this class. We simply want to mock it. The constructor injection is also test code polluting our business logic.
What we have done is create a very small and primitive dispatch table. The
table has one row: something that has a function with the signature of
() -> DateTime or, as it is known in C#:
Func<DateTime>. We will need to make
this primitive dispatch table for every single mock in every single class we
wish to test. That’s a lot of boilerplate!