TDD and the zone

I’ve been thinking recently about why I think TDD is so effective. I think I write better code when I develop using TDD, but I’m also happier when I do. Writing cleaner code probably has something to do with that, but I think it also has something to do with the fabled “zone”.

Tests != TDD

Writing tests does not mean TDD. TDD is when your design is guided by the tests. By following the red, green, refactor steps the design will emerge through writing the minimal amount of code to make your tests pass.

If you write all of your code first then go back to add tests, you are not using TDD.

Benefits of TDD

In my opinion, TDD is a massively helpful tool when trying to write clean and maintainable code. I’ll probably look at the benefits of TDD and the approaches to realise those benefits in other posts.

However, recently I’ve been starting to notice that by following TDD I’ve been noticing other benefits that aren’t immediately apparent from looking at my code. I’ve been noticing that I spend more time in the elusive “zone”.

What is the zone

People often refer to the “zone” as the productive state of mind where you write your best code, everything comes easily to you, and amazing applications shoot out of your finger tips. I might have exaggerated that last bit.

While I do think done people put too much faith in the zone, I do believe it can take time to get in to a productive state of mind.

How TDD can help with the zone

I’ve always seen a bit of a running theme with a lot of developers that interruptions are terrible.

I agree that it can take me time to get back up to speed after an interruption. But I don’t think my productivity is more important than anyone elses. If somebody needs to interrupt me, I want them to feel free to do so.

This is where I find following a TDD approach can help with productivity. One of the best pieces of development advice I was ever given was “go home on a failing test”. That way, when you come back in the next day is much easier to pick up where you left off.

Using the XP principle of turn up the good, I try and always leave my work on a failing test whenever I have to leave my work. Having that failing test is much easier to focus on rather than trying to remember exactly what I was doing before.

If anyone else has any good tips on trying to stay productive I’d love to hear them.

Decoding a JWT in Node

In an app I was working on, I wanted to decouple the UI from the other architectural resources by using a Node back-end with an Express API. Using the JSON Web Token provided by Cognito allowed me to authenticate AWS Cognito users in the back-end.

AWS does have great documentation, but I couldn’t find many code examples of how to decode the JWT in Node. So hopefully this post might be able to help somebody in a similar position.

Getting the token

The first step is to get the JWT for the Cognito user from the client. The JWT is accessible from the user session when you are using amazon-cognito-identity-js

cognitoUser.getSession((err, session) => {
    const token = session.getIdToken().getJwtToken()
})

Sending the token with fetch

Once you have your token, you can send that token to your back-end server. In my case I’m using an Express server, so I’ve set up some routes for my API.

Using the Fetch API I posted the token to the server in the headers.

fetch("/api/myEndPoint", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "token": token
    },
    body: JSON.stringify({
        something: "some data"
    })
})

Get the header

To get the token out of the header in Express, you can get it from the request.

router.post('/api/myEndPoint', function(req, res, next) {
    var token = req.get("token")

    // { decode and use the token here }

    res.send(200)
})

Decode and check the JWT

Once you have the token on the server, you can use jsonwebtoken to decode and verify the JWT token.

const decodedJwt = jwt.decode(token, { complete: true });

The audience on the token should match the app client ID for the Cognito user pool.

if (decodedJwt.payload.aud !== "{app client ID}") {
    throw new Error('Invalid audience: ' + decodedJwt.payload.aud);
}

The issuer on the token should match the Cognito issuer URL; which is made up by adding the region and the user pool ID in the URL below.

if (decodedJwt.payload.iss !== "https://cognito-idp.{region}.amazonaws.com/{user pool ID}") {
    throw new Error('Invalid issuer: ' + decodedJwt.payload.iss);
}

Get the JWK

The JSON Web Keys are available by calling the below URL;

https://cognito-idp.{region}.amazonaws.com/{user pool ID}/.well-known/jwks.json

I used request-promise to call AWS for the JWKs. However, AWS will return all the JWKs for your account, so you have to then extract the correct JWK by comparing Key ID of the decoded JWT.

const options = {
    method: 'GET',
    uri: 'https://cognito-idp.{region}.amazonaws.com/{user pool ID}/.well-known/jwks.json',
    json: true
}

rp(options)
    .then(jwk => {
        var key = jwk.keys.find(key => {
            return key.kid === decodedJwt.header.kid
        })

        // get the PEM from the JWK
        // verify the JWT
    })

Get the PEM

Using jwk-to-pem you can then convert the JWK to PEM format to be used to verify the JWT.

var pem = jwkToPem(key);

Verify the JWT

Then by using jsonwebtoken again, you can verify the original token against the PEM key.

jwt.verify(token, pem, function (err, decoded) {
    if (err) {
        throw new Error('error: ', err)
    }
    
    // verified token!
});

Conclusion

Hopefully this example will save some time for people who are looking to verify AWS Cognito JWT tokens on their server side back end code.

Is consistency a bad thing?

Like most developers I’ve met, I’ve always believed consistency in code to be a good thing.

Recently though I’ve been starting to question if consistency is always a good thing.

What do I mean by consistency?

Consistency can be applied to many areas within a codebase. You can have consistent naming strategies, formatting rules, and code design patterns to name just a few.

When it comes to formatting, people can often have very strongly held views. Tabs Vs spaces, do braces for a function start with a new line, should you end a line with a semicolon, and so on.

If you are spending time thinking about formatting consistencies you are a very lucky developer. If those are your biggest issues, you’ve done a great job, go ahead and take the rest of the day off. Unless these formatting inconsistencies are stopping the code from compiling or causing massive readability issues, I wouldn’t really worry about them. Or better yet, have the conversation once and stick a linter in your project.

The other main area I’ve seen discussed when it comes to consistency is the patterns within the application logic. For example, how the data access objects are structured or how a request is parsed into the application domain.

Good points for consistency

Now don’t get me wrong, consistency can be very helpful.

One of the main aims I hear for consistency is making it easier for other developers to understand how the code works across the application. This is a strong point for consistency. It’s rare a single developer will be working on an application, so making things easy for your teammates is pretty important.

“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write” (Robert c Martin, Clean Code)

Keeping a codebase readable should be one of the main aims of a developer. One of the worst things a developer can do is to reduce the readability of code. By giving patterns to recognise, code readability can be another benefit of sticking to consistent patterns.

Bad points for consistency

It’s clear that consistency can be very helpful, but recently I’ve been thinking it might be a bit of a code smell. So rather than just sticking with consistency for consistency’s sake, maybe think about some of the following points as well.

Inertia

I’ve seen consistency become a real blocker when it comes to refactoring. When you have the same pattern in many places throughout a codebase, when you see a refactoring you want to implement, having to do that refactoring in many places can be time consuming. Sometimes to the point where the benefits of the refactoring are outweighed by the time to implement it.

Communication can help here. Maybe you don’t need to refactor every single instance of a pattern. Try refactoring the one instance you originally wanted to, but make sure you communicate with the team that you have done this.

Big refactorings scare me. It’s too easy for them to turn in to a thread that just won’t stop unraveling. I think the boy scout role is much more effective. Every time you touch code, leave it in a better state than you found it. Even if that’s just renaming one variable, the codebase will quickly start to look great. But I find the need for consistency at odds with this approach. It’s easy to feel, “I can’t just update this, it won’t be consistent with the rest of the application”. This can lead to just keeping the status quo.

The inertia of trying to make big changes is much greater than if you are making many small ones.

Highlighting duplication

If the consistency you are trying to protect is something like a design pattern, then maybe this is a sign of duplication of logic. The fact that there are multiple things done in a consistent way may mean there is a possibility for a cleaner more general implementation that you could be using.

Unit testing

If your unit tests are a mirror of your code then consistency can mean you have to update all your tests every time you refactor your code. However, your tests shouldn’t be a mirror of your code. The test suite should be a collection of the units of work. If you have to update all your tests every time you refactor, these are likely to be implementation tests rather than unit tests.

Making it easier for others

I’ve seen “making it easier for new team members to navigate around the codebase” be a reason why consistency is important. However, if consistency is the enabling factor for navigation, perhaps that is a signal that the code could be cleaner anyway.

By following Uncle Bob’s techniques for clean code, such as naming things clearly and many small functions that do one thing, the code could be easier to navigate. I would rather find my way around a code base that “reads like well written prose” (Grady Booch) rather than relying on spotting a duplicated pattern.

Conclusion

I’m not saying consistency is a bad thing or that it should be avoided. But if you are ever tempted not to refactor code to preserve consistency, I would be on the lookout for other code smells such as duplication, code that could be cleaner, or unit tests that are too closely coupled to the implementation.

VS Code - Code Spell Checker

I was looking for a spell check extension for VS Code to make writing this blog easier. After finding Code Spell Checker, I recommend it as a must have extension.

Once a spelling mistake is identified, you get the classic green squiggle, then Ctrl + . will bring up the spelling suggestions menu.

Expo device testing
Spell checking in VS Code!

The extension has made writing in VS Code an awful lot easier. I didn’t look for a spell checker to make coding easier, but it has had that bonus side effect.

I’ve never really thought about spelling mistakes in code before. Obviously if I spot a spelling mistake I’ll fix it, but I’ve never really thought about the impact on speed of development. However, recently I’ve been doing a lot more work with Javascript. A couple of times already, Code Spell Checker has caught a misspelled variable name. Code Spell Checker will even catch spelling mistakes in camel cased names. With JS being dynamic, these spelling mistakes would have only been caught at run time and I would have had to track down the bug.

AWS Cognito - Higher Order Component

I’ve been building a React app recently that uses AWS Cognito for its authentication. Several of the components were using the same Auth logic to check if they should render or not.

To remove the duplication and keep my authentication logic in one place I created a Higher Order Component.

Signing in with AWS Cognito Javascript SDK

I wanted certain pages of my React application to be only reachable by authenticated users. For authentication I’m using Cognito from AWS along with the Amazon Cognito Identity SDK for JavaScript.

The AWS JS SDK makes it really easy to interact with Cognito from your JS application. Signing up users, verifying users’ emails, and signing in users are pretty straightforward but those are for blog posts for another day.

To check if a user is signed in, you create a user pool to get the current user. Then if there is a current user, get their current session.

var poolData = {
    UserPoolId: '', // your user pool id here
    ClientId: '' // your app client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var cognitoUser = userPool.getCurrentUser();

if (cognitoUser != null) {
    cognitoUser.getSession((err, session) => {
        if (err) {
            console.log('error:', err.message || JSON.stringify(err));
            // redirect to sign in page
        }
        // handle authenticated user
    })
} else {
    // redirect to sign in page
}

This is pretty straightforward but you don’t want to be duplicating this code on every page that you want to check if a user is authentication on though. This is where Higher Order Components for React can help out.

Cross cutting concerns

Application requirements that are needed throughout an application but aren’t necessarily part of the main application are sometimes referred to as cross cutting concerns. Logging and security are good examples of cross cutting concerns.

Using the decorator pattern is a good way of dealing with cross cutting concerns. This allows you to keep your actual application logic clean while adding, potentially multiple, decorating pieces of functionality around it.

Higher Order Components

A Higher Order Component is like a higher order function in Javascript. It is a function that takes a component and returns a new component.

Acting just like the decorator pattern, a Higher Order Component can be used to add logic or cross cutting concerns to components while keeping the original component clean.

Creating a Higher Order Component

For my needs, a Higher Order Component will allow me to add my Cognito authentication logic to multiple page components cleanly. In the example below, the Cognito user check is in the componentDidMount function. If the user and session is valid, a boolean check in the state of the component is set to true. If the user check or the session doesn’t return successfully the component will redirect to the sign in page.

In the render function, it checks the loggedIn boolean in the state, then if true, it returns the component that was passed to the Higher Order Component.

import * as React from 'react'
import * as AmazonCognitoIdentity from 'amazon-cognito-identity-js'
import { withRouter } from 'react-router-dom'

const withAuth = Component => {
    class WithAuthUser extends React.Component {
        constructor(props) {
            super(props);

            this.state = {
                loggedIn: false,
            }

            this.onSession = this.onSession.bind(this)
        }

        onSession(err, session) {
            if (err) {
                console.log('error:', err.message || JSON.stringify(err));
                this.props.history.push('/signin')
            }
            this.setState({ loggedIn: true })
        }

        componentDidMount() {
            var poolData = {
                UserPoolId: '', // your user pool id here
                ClientId: '' // your app client id here
            };
            var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
            var cognitoUser = userPool.getCurrentUser();

            if (cognitoUser != null) {
                cognitoUser.getSession(this.onSession)
            } else {
                this.props.history.push('/signin')
            }
        }

        render() {
            if (this.state.loggedIn) {
                return (
                    <Component {...this.props} />
                );
            } else {
                return null
            }
        }
    }

    return withRouter(WithAuthUser)
}

export default withAuth

To use a Higher Order Component

To use a Higher Order Component you import the component like any other component;

import withAuth from './withAuth'

Then wrap it around the component you want to apply the decorating logic to;

const ExampleComponent = () => {
    <p>My component!</p>
}

export default withAuth(ExampleComponent)

For some more examples of Higher Order Components in React, you can check out the documentation for them here.