Developer Tea

Primitive Obsessions

Episode Summary

Today, we're talking about doing good work and writing better code, and this episode will ask you to question what good code is. We'll be exploring that through the lens of the code smell called Primitive Obsession.

Episode Notes

Today, we're talking about doing good work and writing better code, and this episode will ask you to question what good code is. We'll be exploring that through the lens of the code smell called Primitive Obsession.

Get in touch

If you have questions about today's episode, want to start a conversation about today's topic or just want to let us know if you found this episode valuable I encourage you to join the conversation or start your own on our community platform Spectrum.chat/specfm/developer-tea

🧡 Leave a Review

If you're enjoying the show and want to support the content head over to iTunes and leave a review! It helps other developers discover the show and keep us focused on what matters to you.

Episode Transcription

And today's episode we're going to jump in head first and talk about a code smell that might actually have implications outside of your code. My name is Jonathan Cutrell and you're listening to Developer Tea, my goal on the show is to help driven developers connect to their career purpose and do better work so they can have a positive influence on the people around them. In today's episode we're talking about doing better work, specifically we're talking about writing better code. As it turns out, being a developer sometimes just comes down to writing good code. But knowing what good code is is always the problem. So we try to talk about this from a perspective that is more about discovery than it is definition. In other words, sometimes it's a little bit difficult to answer that question. What is good code? Well, it kind of depends on a lot of things. It depends on when that code came from. It depends on who's reading it. It depends on what the point of that code is, what it's accomplishing in what context. You know what restraints, what constraints are on this code, whether those are human constraints or if they are actually machine constraints. And the list goes on and on. So we don't want to presume that good code is easy to understand. But it is a little bit easier to compare two pieces of code and decide which one is arbitrarily better. We say arbitrarily because really we're judging it based on a few simple kinds of metrics. For example, readability. Generally speaking, readability, if your code is equivalent in terms of function and in terms of execution time, for example, then the more readable code is going to be the better code. But that's a long way of saying that good code comes with a lot of caveats. And you need to understand those caveats for the thing that you are doing for the place that you're working for the job you are accomplishing. OK, so let's assume that you understand those caveats. You understand we aren't trying to prescribe to you what exactly it means to write good code because there's too many things to talk about. But instead, we're talking about ways that we might improve code in some particular metric. In today's episode, we're talking about improving code using a concept called a code smell. A code smell. A code smell is essentially something that you keep on seeing happening in your code. And even though your code is working, it's functional and it may even be readable, there's still something that doesn't feel quite right. And this specific code smell is called primitive obsession. This is the one we're going to talk about today. Primitive obsession happens when you are passing around a value to various parts of your code, whether it's functions or classes, and you're passing this particular value around, and it's a, let's say it's something like a string. And when the string gets to wherever it's going, maybe inside of that function, you're having to parse that string, you're having to break it open and try to figure something out about it. One example of primitive obsession is magic numbers. When you have numbers that represent some kind of status, for example, if you have zero representing a beginner status, then one representing a middle status and two representing kind of the end status, right? And so what you see in your code is you're checking to see what that number is. Maybe you even write some of this logic into that function or into that class to be able to know what to do with that number whenever it arrives. Another example of primitive obsession is using a specially formatted string, something that is not necessarily a standard format like JSON, but instead, maybe it's a pipe-separated list of values. And you're trying to bring out those values by splitting that string on the pipe and you're just passing the string around and you're having to do that splitting and all of that logic to figure out what those values are everywhere that that string gets passed. Hopefully, you can see how this might become a problem in your code. Of course, if you're doing one thing in one place and you want to do the same thing in another place, well, copy and paste. This is a totally fine thing to do or not against copy and paste. We've talked about dry on the show before and why dry needs to be taken in context. But if you copy and paste enough times and if your code where you're doing those things is changing in enough places where you're having to go back and mentally account for all of the places that you've copied and pasted that code, well, it seems like you're creating an entire concept around a primitive value. So this primitive value, it means something more than whatever the primitive is on its own. It carries with it some kind of meaning. So for you to be able to parse that meaning out inside of function, inside of a class, you're going to have to encode that meaning somewhere. We've talked about protocols on the show before. The idea of a protocol is that we both agree on both ends that this is how we're going to parse something. When you have primitive obsession in your code, you're creating many protocols. They're not standardized. They're most likely not even documented. Most of the time this happens kind of as code grows. You find the need for this primitive obsession, this ability to parse this, you know, whatever this value is. And you don't necessarily follow a standard in order to pass that value around and parse it. What this results in is an imprecise protocol, an implicit protocol, a hidden protocol. And that you can't really rely on. And that's really the whole point of a protocol is to be reliable. So how can we fix a primitive obsession? How can we replace this with a better concept? Well, instead of passing around this value that is a primitive value, consider passing around a structured value, something like an object or class instance. Depending on what language you're using, most of the time you can create some kind of structured object concept that you can pass around from a function to another function, from a class instance to another class instance. You can send that entire structure and then tell that structure what you want back from it. You can send a message to that structure. You can call a method that will retrieve the things that you want and all of that information about how to retrieve and how to store that is encapsulated with that structure. So this is a very simple code smell to recognize. You should be seeing this in your code. You should be able to see methods like parse some value, right? parse string might be one of the methods that you've written. You might see a splitting of a string. Some kind of manipulation of whatever that value is. And then a destructuring typically occurs. Sometimes there's case statements that try to draw out the value based on whatever that magic number, for example, whatever that particular value is so that you can do something based on what the value is. And of course, the tail tail sign is if you're duplicating that same kind of destructuring or parsing in multiple places, well, that's really kind of the driver of this problem. So take that structure and create out of that structure a non-primitive value that non-primitive value might be an object. It might be a class or an instance of a class that you can go and get that stuff from. So how does this play out in your day-to-day life? I mentioned that this may have implications outside of your code. Well, as it turns out, we do this as humans. This comes down to having to keep in mind all of the specific details. And what we can do to avoid this is to create concepts, these are abstracted concepts that wrap up multiple details for us. A very practical example of this for me is my gym bag. I know that as long as my gym bag is in the car, it has everything that I need to go to the gym. So instead of thinking of all of the individual things that I need to get, each time I want to go to the gym, all I have to do is have my gym bag. Now what this means is that I pack my gym bag as a separate activity that I actually do that work in a different encapsulated environment. Of course, this is a completely nerdy way to talk about going to the gym, but it illustrates the point. When we separate these concerns out, I'm much more likely to effectively pack my gym bag when I'm not stressed, when I'm not rushing out the door to get to the gym, and I'm much more likely to go to the gym if I have my gym bag packed, if there's not a lot of information that I need to figure out in order to make it to the gym. Having these abstractions, these encapsulations, these kind of lists, this is a very useful way to de-load some of that cognitive stress that you have. That cognitive overhead certainly takes a toll when you are coding, and it can take a toll when you're not coding. Thanks so much for listening to today's episode of Developer Tea. I hope you've enjoyed this quick discussion on primitive obsession. This is a very interesting topic. All of these refactoring topics are very interesting to me. I'd love to hear your experiences with refactoring some of the things that you've found that have been helpful to you. You can always reach out and ask questions at Developer Tea at gmail.com. Thanks so much for listening to today's episode. If you don't want to miss out on future episodes, make sure you open up whatever app you're listening to today's episode in, and click subscribe next to the show. This will make sure you don't miss out on future episodes. Thanks again for listening, and until next time, enjoy your tea.