Why Developer Experience Matters0:00
The overall performance of engineering teams relies heavily on developer experience. How easy it is for you to navigate through your code directly impacts how your team is going to perform. It affects the time that you would need to extend your code with additional functionality to maintain it on the long run. Unfortunately, way too often we have to deal with projects where it's harder to understand what the codebase does than it is to implement the actual functionality. You know the scenario of spending days reading through the code trying to implement a simple feature or fixing a bug in one place just to have it introduce several other bugs elsewhere in the code.
Example: Payment Details Feature0:35
feature or fixing a bug in one place just to have it introduce several other bugs elsewhere in the code. And, of course, the dreaded moment when you need to explain to stakeholders why it takes so long to add that simple button to the code. In this series, we'll discover techniques for organizing your code in a way that will make it easy for you to extend it and maintain it on the long run. To make it easy to follow, we'll look at a real-life example. This is Part4Mediva, a platform where developers can find consulting opportunities with companies worldwide. As you can see, under the account settings, every User is able to set their payment details.
worldwide. As you can see, under the account settings, every User is able to set their payment details and then select how they want to get paid, month over month. We have two options to choose from right now, Payoneer and Wire Transfer, and I have set Wire as my default over here. Now, what I want to look at with this example is how can we change this functionality and extend it with multiple other payment options to choose from without affecting our codebase too much, without complicating it. And at the same time, how does the current structure of our code connect with how fast we are able to do this and how easy it is for us to extend this with this functionality?
Clean Design with Interfaces1:39
And at the same time, how does the current structure of our code connect with how fast we are able to do this and how easy it is for us to extend this with this functionality? In terms of the code, this is what we want to look at. At first, we'll start with a clean slate scenario where we are able to organize our code the way we see fit and use all of the best practices we want to. As you can see over here, I have started by abstracting the payment details with an interface and outlining all of the methods that we'll need to implement later on. And then I have two concrete classes, PayoneerDetails and WireDetails, for both of the specific payment options that I want to offer. Now, this allows for a lot of flexibility on my end because I can easily extend this.
Legacy Controller Anti-Pattern2:22
specific payment options that I want to offer. Now, this allows for a lot of flexibility on my end because I can easily extend this functionality with as many payment options as I want to. The only thing I need to do here is add another class for the concrete payment option that I want to implement and then most of it will work out of the box without touching too much of the existing code. Now, as a contrasting scenario, I want to look at something more real life. As an example over here, I have a code that is likely inherited where everything is placed in a single controller or a single method to be more precise. And as you can see it over here, this is fairly simple and it's really simple to add an
Goal: Refactor for Extensibility2:57
in a single controller or a single method to be more precise. And as you can see it over here, this is fairly simple and it's really simple to add an additional payment option just by adding another condition here. The problem with this is that over time, this complicates your code too much and everything is so coupled together that it becomes very difficult to maintain it and to understand what the codebase does over time. So what we like to look at here is how to optimize this type of code, how to organize it in a way that we can rely on what is stable and not changed as often, but at the same time optimize the rest of it in a way that will allow us more flexibility and more ability to extend it easily with additional functionality in the future.
time optimize the rest of it in a way that will allow us more flexibility and more ability to extend it easily with additional functionality in the future. So, let's dive in!
