Part 6: Refactor
This is the 6th part of the series about writing an serverless Azure Function in TypeScript. Since we now have and end-to-end test up and running we will refactor the code, cleaning it up a bit.
“Make it work, make it right, make it fast.”
– Kent Beck
We have the first part, a working endpoint. Now we make it right.
Turn On Strict Mode
The first thing we do is turn on TypeScript’s strict mode, enabling a range of compile-time checks. You should always strive to enable this when using TypeScript, and when starting from scratch there really shouldn’t be any excuse for not enabling this.
noImplicitAny is one of those checks, requiring that we specify the types of our parameters. For now we settle for simply adding
Return the HTTP Response
Return the HTTP response from the function instead of setting
context.res to have a functional style instead of a side effect. This change simplifies out test code a bit.
I don’t know why the demo function app defaults to using a side effect, and this changes seems like such an obvious improvement to the code, that I wonder, if there is some drawback to using the functional approach that I haven’t yet realized.
Use Strong Types
We satisfied the compiler by setting the types to
any, but we can do better and install type definitions for Azure Functions, available in the
@azure/functions package. The package doesn’t include a type for the HTTP response, so here we still use any,
Using strong types in out tests requires that we mock the arguments we pass in. The best package I could find was @fluffy-spoon/substitute. That package doesn’t support
strictNullChecks, so now we unfortunately have to cast a few objects to
any in our test. As the author of the package suggests, we could turn off strictNullChecks for our tests, but that approach probably requires that the test files are located in a separate folder.
Rename to greet
Avoid having a lot of methods named
index and avoid having a lots of
Delete the destination folder before building to make sure that delete and renamed source files are also deleted in the
The packages are installed with the
--frozen-lockfile modifier, so that installation fails, if
yarn.lock has to be updated. This is how we want our continuous integration to behave, since we want to make sure that the packages installed are the ones specified by
rimraf is simply a cross platform version of
rm -rf, the Unix command for deleting a folder including all subfolders.
Format the Code
“Nobody likes what Prettier does to their own code, but everybody loves what Pretties does to everybody else’s code.”.
- Source unknown – drop me a line if you recognize this line
Prettier is a source code formatter that seems to be getting a lot of traction. I don’t agree with all their choices (operators at the beginning of lines, please) but consistently and well formatted is just easier to read.
Lint the Code
Use TSLint to verify that the code follow best practices. Since Prettier handles all of the cosmetic rules, these are turned off by extending the
The world seems to be switching to ESLint even for TypeScript, but I haven’t investigated that yet.
Don’t Abbreviate ‘request’
I generally try to avoid using abbreviations because I think the code becomes more readable without them.
Remove Unnecessary Log
Azure logs all incoming requests so there is no need to log a custom message too.
Remove Unnecessary Comment
Remove the commit since it isn’t really necessary. This information should arguably be part of the documentation included with the type definitions.
Simplify the code nesting by extracting to a function. We can now avoid the
if to reduce nesting. This also have the nice effect of putting the special case - no name defined - into the if clause, and letting the happy flow flow be the least indented one.
Use String Interpolation
+ with string interpolations making the code more readable. This also have the effect of making it more obvious that we need to terminate our sentence with a full stop.