05 Aug 2017
RTD - Read the Docs. That phrase cuts across industries - I have heard it just as much as a programmer as I did as an investment banker. And while when said verbally, RTD (sometimes RTFD) usually lands with a hint of annoyance, I really believe it’s some of the most important career advice I have ever received.
I recently was writing some unit tests to check that a small wrapper around the AWS.SES API was invoked correctly and logging error messages as expected. Using
sinon and the
aws-sdk-mock library, I had some code that looked like the below to check error handling:
aws-sdk-mock takes three arguments, the third of which is a function that, in the case of mocking sendEmail, takes the email params and a callback. The callback itself takes two arguments - an error message and data from the response.
stub.callsArgWith(index, arg1, arg2, …)
Like callsArg, but with arguments to pass to the callback.
Causes the stub to call the argument at the provided index as a callback function. stub.callsArg(0); causes the stub to call the first argument as a callback.
It made sense - my only goal was to fake invoking the callback
sendEmail takes following resolution of the email
Promise. Giving it an error didn’t require passing in a new function to
sinon already offers this functionality:
sendEmailStub = sandbox.stub().callsArgWith(1, new Error());
And because you’re always one click a way in your IDE from seeing the source in
after which there’s an easy path to cloning the source repo and after some investigation finding your way to
lib/sinon/behavior.js, which gets the callback using
callArgAt set in the source we looked at, which then takes the
callbackArguments sans the
position arguments passed in
callsArgWith (note the function signature in the docs differs from what is the source - this is because
addBehavior will always add functions to the stub prototype with the first argument being the stub itself).
Finally, here’s the test in
sinon, clearly demonstrating that a callback passed as the second argument to a stub should be able to be passed any argument with
In looking at the
sinon docs and then the Amazon SES docs, I realized there was probably an ocean of API functionality I was not taking advantage of. And the only way to find out would be to study and experiment. Which is the fun of being an engineer.
I bring up this example because I think it illustrates the importance of reading documentation (and even better, source code). I was familiar with
callsFake, so every testing situation looked like a nail to its hammer. This is what happens when API docs are read quickly and with the intent of completing a task. The cost is that robust APIs are used incorrectly, and code that should be short and sweet becomes long and ugly.
I know this seems obvious, but I wanted to write about it because I know there are different gradients of RTD. In banking, you might read the earnings call transcript but not the 10-Q; only the part of the S-1 with the risks to the business; the first tab of the huge Excel model.
In programming, there’s cherry-picking documentation; reading the documentation without the source code; starting a project with “getting started” documentation and never revisiting the docs again, and so much more.
A lot of this can be argued against with allusions to time management principles. How am I supposed to get anything done if I’m reading forty thousands pages of documentation and source code? Obviously, reading all the documentation - especially for something like the AWS SDK - is impossible. But transferring a 3 hour chunk of time from 70 / 30 writing code / reading docs to 65 / 35 writing code / reading docs?
You might end up improving your code and reading some interesting source code from a great library