Dynamically typed languages and Tolerant Readers

I’ve been playing around with Node.js for the past few months, and I must admit that I’m pretty hooked on it. Having lived in a statically typed world for the past 20 years, it can be a bit alarming to not be able to rely on the type of object that I’m receiving over the wire or from the database. I spent quite a bit of time trying force these objects into the paradigm that I’m used to working with. I had, of course, heard of duck typing, in which one queries the object for the attributes that they are interested in regardless of type, but it wasn’t a part of my thought process. As with most things, once I stopped fighting it, it became much more natural and easy to work with. While I still, to a certain degree, pine away for my package of well-defined domain objects, I can’t deny the power and beauty of being able to inspect, and even modify, the structure of one’s objects.

Martin Fowler writes of the benefits of tolerant readers, which advocates fortifying client interactions through only using what is needed from the message, instead of statically linking to the definition of the entire message. It’s a concept that immediately gelled with me, even before my work with dynamically-types languages. Though it requires more initial work of the coder, it provides an unparalleled flexibility and robustness to the codebase. When working with a dynamically-typed language such as JavaScript, it just seems to be a perfect fit.

For instance take this admittedly contrived object stored in our NoSQL database:

{
    "name": "Project",
    "jenkinsUrl": "http://build.mikefeldmeier.com/lattice",
    "builds": [
        { 
            "number": 1120, 
            "timestamp": "20140131T013459Z", 
            "result": "SUCCESS"
        },
        { 
            "number": 1121, 
            "timestamp": "20140131T014623Z", 
            "result": "SUCCESS"
        },
    ]
}

It’s just a basic JSON object with the name of our project,the URL to it’s location in our Jenkins build server, and the builds that have been found to date.

Our clients are happy. They can display the name and location of the project, as well as the build details to date. We can also use this information to calculate the latest build number, status, and age.

After a while, and a number of projects and builds later, we discover that all this calculation of latest information for each request is taking it’s toll on our servers, so we decide to add a “rollup” section, that performs the “latest” calculation on update, allowing it to be simply retrieved with the rest of the project:

{
    "name": "Project",
    "jenkinsUrl": "http://build.mikefeldmeier.com/lattice",
    "rollup": {
        "latestNumber": 1121,
        "latestAgeInDays": 3,
        "latestResult": "SUCCESS"
    }
    "builds": [
        { 
            "number": 1120, 
            "timestamp": "20140131T013459Z", 
            "result": "SUCCESS"
        },
        { 
            "number": 1121, 
            "timestamp": "20140131T014623Z", 
            "result": "SUCCESS"
        },
    ]
}

None of this is groundbreaking stuff, granted. The important point here is that 99% of the services that I see in production today will now break. Most developers will have used a tool to generate a static class library against a WSDL or other type of descriptor for the original message type. Simply adding a new element will break these clients since the object no longer matches the expected type.

However, if the client is following a tolerant reader pattern, they simply ignore the new content. As long as they find the elements that they want, they can continue happily. This is the hallmark of robust code.

Note that I’m not saying that this is not possible with statically-typed languages. It is in many of the ones I’ve worked with, albeit with convoluted and rarely used options, which most developers are not aware of, or even aware of the need for. In this case, our go-to tools that are supposed to make our lives easier, are actually working against us.

In short, I have found that using a dynamically-typed language almost steers you into using a tolerant reader pattern with your objects and messages. Being aware of it helps one take advantage of it from the beginning of the process, leading to more robust services and clients.

 
25
Kudos
 
25
Kudos

Now read this

Yet Another Node.js Logger: femto-logger

Ok, so I don’t know if we really need another logging framework, but after looking at various ones available in the registry, I found that I was implementing my own repeatedly, so I figured I would just stick it out there. I had the... Continue →