Backend Engineer Intern
Datare
Getting to work on a bleeding edge tech stack
November 2023 — February 2024
Summary
My first experience working in the back-end. It was certainly an enriching experience because I got exposed to the latest and greatest tech stack with a lot of abstractions and impeccable developer tooling.
Developer Diaries
Full of Abstraction
Now, my time here was only 3 months and to be completely frank, I unfortunately didn't get to do a lot during that 3 months. But what I definitely experienced working on the software was how many abstractions were already in the codebase, despite it being relatively young at the point of my employment.
What I meant by "abstraction" here is best described by an example. Let's say that a front-end developer would like to listen to an event from the back-end transmitted through websocket. There is already a class with a method to do exactly that. What is needed for the front-end developer is to call that method with the event name to listen to and the callback function to run on the event. One more thing, this class also exist on the back-end, where it's used to define the websocket event that exists and, correspondingly, the type of data sent by each event. This means that when the front-end developer is writing a call to listen to a websocket event, not only that the event name is already typed with Typescript union type (so it's impossible to listen to non-existent event) but also the data that the callback function is going to receive during the event.
Doing things like this is certainly great for the developer, absolutely no question from me in that regards. It prevents one from making stupid mistake that blow things up in production (which I have experienced, see the entry on Paper.id). It's also in tandem with the overall aim of end-to-end type safety (the reason why the tech stack used tRPC).
But after working on the codebase and pondering about what could have happened in the future, I think it should always be noted that increasing the complexity of a codebase like this, will always carry with it some adverse side effects for the developer. There are two that I thought of:
Harder debugging/RCA. When there are layers upon layers of abstraction, it will take more time to navigate through all of the methods that are being called and all of the classes being inherited.
Harder refactoring and higher cost of change. For many people, this is less obvious than the first one. There is a great video describing this problem. In essence, introducing abstractions for whatever benefits it may bring (in this case better developer experience, in another case it could be to reduce code duplication) will also introduce tighter coupling into a codebase. In a big codebase, high coupling could hinder or even cripple the development process by making it hard to change existing code because any changes to one part of the codebase is likely to trigger a regression on an entirely different part of the codebase. The creator of the video did a far better job conveying this point and I highly recommend watching the video for yourself.
The above note is not a criticism directed specifically at Datare's codebase nor are they particularly novel (any software engineers worth their salt should already understand this). But they're a stark reminder that excellence developer experience is not free.