median blog

Antipatterns in ORMs and Automatic Types

There is a pattern I see when adopting an ORM or an optional type system (like Typescript) and making use of 'Automatic' inference of types.

When it's the ORM this appears as passing data from the ORM response into the response for the endpoint. Something akin to SELECT * FROM table by way of very little filtering of fields.

When it's a type system it's automatically generating type definitions or heavy use of typeof X as the type definition for other variables.

Both of these shortcuts save time defining types. Keeping type definitions up to date, especially when they need to change can be a massive pain but that's kind of the point.

In many ways these strict and explicit definitions act the same way as good tests. When things change in a way that is incompatible, your compiler will complain long before it becomes a problem at runtime.

Where I see the most risk in this pattern is when these automatic types are part of the public return type. In this case the output of an API can change when someone adds a column to the database, whether we wanted it to or not.

Additionally it couples the shape of your public API to the formatting choices of your ORM or generated types. If you want to switch ORMs you might end up with a significant departure in API.

What we should do instead is pair any public API with a strict interface. Behind the scenes you can use an ORM, automatic types or any other tools so long as there is an final step of serializing data into the interface format.

Initially, this might feel like double handling. When I first started using django-rest-framework many years ago, I found the serialize step frustrating. I made everything a model serializer that exposed all fields other than ones I knew I wanted to remain private for security reasons. Fast forward twelve months and I was stuck. I wanted to change some fields because the data model changed behind the scenes but had no way to know if the fields I had exposed automatically were now a part of somebody's critical workflow.