Primitive Obsessions
Summary
The episode delves into the concept of ‘primitive obsession,’ a common code smell where developers overuse primitive data types (like strings or numbers) to represent complex concepts, forcing parsing and destructuring logic to be duplicated throughout the codebase. This creates implicit, unreliable protocols and increases maintenance burden.
Host Jonathan Cattrell explains that this smell is recognizable by repeated parsing methods (e.g., parseString), splitting operations, case statements based on ‘magic numbers,’ and the duplication of this logic in multiple places. The core issue is that a simple value carries additional meaning that isn’t encapsulated, leading to scattered implementation details.
The solution is to replace these primitive values with structured objects or class instances. By encapsulating the data and its related behavior into a single, passable entity, you create a clear, reliable protocol. Functions can then send messages to this structure to retrieve what they need, centralizing the logic and improving code clarity.
Cattrell extends the concept beyond coding, illustrating how abstraction reduces cognitive load in daily life. Using the analogy of a pre-packed gym bag, he shows how bundling related items (or data and behavior) into a single concept allows you to operate at a higher level of thinking without managing low-level details, both in software and personal routines.
Topic Timeline
- 00:00:00 — Introduction to good code and code smells — Jonathan Cattrell introduces the episode’s goal: to help developers write better code. He discusses the contextual nature of ‘good code,’ noting it depends on readability, constraints, and purpose. The episode will focus on improving code using the concept of a ‘code smell’—a pattern that works but doesn’t feel right—specifically ‘primitive obsession.’
- 00:02:13 — Defining primitive obsession with examples — Primitive obsession is defined as passing a primitive value (like a string or number) around your code, requiring parsing logic wherever it goes. Examples include ‘magic numbers’ representing statuses (0,1,2) and specially formatted strings (e.g., pipe-separated lists) that need splitting. This scattering of logic creates hidden, unreliable protocols.
- 00:04:55 — The problem: implicit protocols and duplication — When a primitive value carries extra meaning, you encode that meaning in multiple places through parsing and destructuring. This results in an imprecise, implicit protocol—the opposite of a reliable, agreed-upon standard. The problem escalates when you copy and paste this parsing logic, creating a maintenance nightmare as you must track all duplication sites.
- 00:06:10 — The solution: structured objects and encapsulation — The fix is to replace the primitive with a structured value—an object or class instance. This encapsulates both the data and the logic for accessing it. You pass this structure around and send it messages (call methods) to retrieve what you need. This creates a clear, centralized protocol and eliminates scattered parsing code.
- 00:07:44 — How to recognize primitive obsession in your code — Look for methods named like
parseString, string splitting, destructuring operations, and case statements based on magic values. The telltale sign is duplicating this same parsing or destructuring logic in multiple places. Recognizing these patterns is the first step to refactoring them into a proper structured concept. - 00:08:06 — Life analogy: reducing cognitive overhead with abstraction — Cattrell draws a parallel to human behavior: we also suffer from ‘primitive obsession’ when we try to manage many low-level details. The solution is abstraction, like a pre-packed gym bag. By encapsulating all gym necessities into one concept, you reduce the cognitive stress of remembering individual items, making the activity (going to the gym) more likely and less stressful.
Episode Info
- Podcast: Developer Tea
- Author: Jonathan Cutrell
- Category: Technology Business Careers Society & Culture
- Published: 2018-08-03T09:00:00Z
- Duration: 00:10:28
References
- URL PocketCasts: https://pocketcasts.com/podcast/developer-tea/cbe9b6c0-7da4-0132-e6ef-5f4c86fd3263/primitive-obsessions/820dca55-a39b-4332-8eab-220416382472
- Episode UUID: 820dca55-a39b-4332-8eab-220416382472
Podcast Info
- Name: Developer Tea
- Type: episodic
- Site: http://www.developertea.com
- UUID: cbe9b6c0-7da4-0132-e6ef-5f4c86fd3263
Transcript
[00:00:00] in today’s episode we’re going to jump in head first and talk about a code smell that might
[00:00:10] actually have implications outside of your code my name is jonathan cattrell and you’re listening
[00:00:14] to developer t my goal on the show is to help driven developers connect to their career purpose
[00:00:19] and do better work so they can have a positive influence on the people around them
[00:00:23] in today’s episode we’re talking about doing better work specifically we’re talking about
[00:00:27] writing better code as it turns out being a developer sometimes just comes down to writing
[00:00:32] good code but knowing what good code is is always the problem so we try to talk about this from a
[00:00:40] perspective that is more about discovery than it is definition in other words sometimes it’s a
[00:00:45] little bit difficult to answer that question what is good code well it kind of depends on a lot of
[00:00:49] things it depends on when that code came from it depends on who’s reading it depends on what the
[00:00:55] point of that code is what it’s accomplishing
[00:00:57] in what context you know what restraints what constraints are on this code whether those are
[00:01:03] human constraints or if they are actually machine constraints and the list goes on and on so we don’t
[00:01:10] want to presume that good code is easy to to understand but it is a little bit easier to
[00:01:18] compare two pieces of code and decide which one is arbitrarily better and we say arbitrarily because
[00:01:27] judging it based on a few simple kinds of metrics for example readability generally speaking
[00:01:34] readability if your code is equivalent in terms of function and in terms of execution time for
[00:01:40] example then the more readable code is going to be the better code but that’s a long way of saying
[00:01:45] that good code comes with a lot of caveats and you need to understand those caveats for the thing
[00:01:51] that you are doing for the place that you’re working for the job you are accomplishing okay so
[00:01:57] let’s assume that you understand those caveats you understand we aren’t trying to prescribe to you
[00:02:02] what exactly it means to write good code because there’s too many things to talk about but instead
[00:02:06] we’re talking about ways that we might improve code in some particular metric in today’s episode
[00:02:13] we’re talking about improving code using a concept called a code smell a code smell a code smell is
[00:02:19] essentially something that you keep on seeing happening in your code and even though your code
[00:02:26] is working it’s functional and it’s not going to work and it’s not going to work and it’s not going to
[00:02:27] be functional and it may even be readable there’s still something that doesn’t feel quite right
[00:02:32] and this specific code smell is called primitive obsession this is the one we’re going to talk
[00:02:38] about today primitive obsession happens when you are passing around a value to various parts of
[00:02:45] your code whether it’s functions or classes and you’re passing this this particular value around
[00:02:50] and it’s a let’s say it’s something like a string and when the string gets to wherever it’s going
[00:02:56] maybe inside of that function it’s going to be a string and when it gets to wherever it’s going
[00:02:57] you’re having to parse that string you’re having to break it open and try to figure something out
[00:03:02] about it one example of primitive obsession is magic numbers when you have numbers that represent
[00:03:10] some kind of status for example if you have zero representing a beginner status then one
[00:03:17] representing a middle status and two representing kind of the end status right and so what you see
[00:03:23] in your code is you’re checking to see what that number is
[00:03:27] maybe you even write some of this logic into that function or into that class to be able to know
[00:03:34] what to do with that number whenever it arrives another example of primitive obsession is using
[00:03:40] a specially formatted string something that is not necessarily a standard format like json but
[00:03:46] instead you know maybe it’s a pipe separated list of values and you’re trying to bring out those
[00:03:53] values by splitting that string on the pipe and you know you’re you’re trying to bring out those
[00:03:57] values and you’re just passing the string around and you’re having to do that splitting and all of
[00:04:01] that logic to figure out what those those values are everywhere that that string gets passed
[00:04:07] hopefully you can see how this might become a problem in your code of course you know if you’re
[00:04:13] doing one thing in one place and you want to do the same thing in another place well copy and
[00:04:21] paste this is a totally fine thing to do we’re not against copy and paste you know we’ve talked
[00:04:27] about dry on the show before and why dry needs to be taken in context but if you copy and paste
[00:04:33] enough times and if your code where you’re doing those things is changing in enough places where
[00:04:41] you’re having to go back and mentally account for all the places that you’ve copied and pasted that
[00:04:46] code well it seems like you’re creating an entire concept around a primitive value so this primitive
[00:04:55] value it means something
[00:04:57] more than whatever the primitive is on its own it carries with it some kind of meaning and so for
[00:05:04] you to be able to parse that meaning out inside of a function inside of a class you’re going to
[00:05:10] have to encode that meaning somewhere now we’ve talked about protocols on the show before the
[00:05:17] idea of a protocol is that we both agree on both ends that this is how we’re going to parse
[00:05:22] something when you have primitive obsession in your code
[00:05:27] creating many protocols they’re not standardized they’re most likely not even documented most of the
[00:05:34] time this happens kind of as code grows you find the need for this primitive obsession this ability
[00:05:41] to parse this you know whatever this value is and you don’t necessarily follow a standard in order
[00:05:47] to pass that value around and parse it what this results in is an imprecise protocol an implicit
[00:05:55] protocol a hidden protocol a hidden protocol a hidden protocol a hidden protocol a hidden protocol
[00:05:57] one that you can’t really rely on and that’s really the whole point of a protocol is to be
[00:06:02] reliable so how can we fix a primitive obsession how can we replace this with a better concept well
[00:06:10] instead of passing around this value that is a primitive value consider passing around a
[00:06:17] structured value something like an object or class instance depending on what language you’re using
[00:06:24] most of the time you can create some kind of
[00:06:27] structured object concept that you can pass around from a function to another function from
[00:06:35] a class instance to another class instance you can send that entire structure and then tell that
[00:06:42] structure what you want back from it you can send a message to that structure you can call a method
[00:06:49] that will retrieve the things you want and all of that information about how to retrieve and
[00:06:55] how to store that is encapsulated in a structure that you can pass around and then you can send a
[00:06:57] message to that structure and say hey this is your code and here’s mine this is your code and here’s
[00:07:00] your code so this is a very simple code smell to recognize you should be seeing this in your code
[00:07:05] you should be able to see methods like parse some value right parse string might be one of the
[00:07:12] methods that you’ve written you might see you know a splitting of a string some kind of manipulation
[00:07:17] of whatever that value is and then a destructuring typically occurs sometimes there’s case statements
[00:07:25] to try to draw out the value of the structure and then you can see that it’s a part of the
[00:07:27] value based on whatever that magic number, for example, whatever that particular value
[00:07:33] is, so that you can do something based on what the value is.
[00:07:37] And of course, the telltale sign is if you’re duplicating that same kind of destructuring
[00:07:44] or parsing in multiple places, well, that’s really kind of the driver of this problem.
[00:07:49] So take that structure and create out of that structure a non-primitive value.
[00:07:55] That non-primitive value might be an object.
[00:07:59] It might be a class or instance of a class that you can go and get that stuff from.
[00:08:04] So how does this play out in your day-to-day life?
[00:08:06] I mentioned that this may have implications outside of your code.
[00:08:10] Well, as it turns out, we do this as humans.
[00:08:12] This comes down to having to keep in mind all of the specific details.
[00:08:18] And what we can do to avoid this is to create concepts.
[00:08:22] These are abstracted concepts that wrap up.
[00:08:25] Multiple details for us.
[00:08:27] A very practical example of this for me is my gym bag.
[00:08:31] I know that as long as my gym bag is in the car, it has everything that I need to go to
[00:08:37] the gym.
[00:08:38] So instead of thinking of all of the individual things that I need to get each time I want
[00:08:43] to go to the gym, all I have to do is have my gym bag.
[00:08:47] And what this means is that I pack my gym bag as a separate activity, that I actually
[00:08:54] do that work.
[00:08:55] In a different, encapsulated environment.
[00:08:57] Of course, this is a completely nerdy way to talk about going to the gym, but it illustrates
[00:09:02] the point.
[00:09:03] When we separate these concerns out, I’m much more likely to effectively pack my gym bag
[00:09:09] when I’m not stressed, when I’m not rushing out the door to get to the gym, and I’m much
[00:09:14] more likely to go to the gym if I have my gym bag packed, if there’s not a lot of information
[00:09:20] that I need to figure out in order to make it to the gym.
[00:09:24] Having these abstractions.
[00:09:25] These encapsulations.
[00:09:27] These kind of lists.
[00:09:29] This is a very useful way to deload some of that cognitive stress that you have.
[00:09:36] That cognitive overhead certainly takes a toll when you are coding, and it can take
[00:09:40] a toll when you’re not coding.
[00:09:43] Thanks so much for listening to today’s episode of Developer Tea.
[00:09:46] I hope you’ve enjoyed this quick discussion on primitive obsession.
[00:09:50] This is a very interesting topic.
[00:09:52] All of these refactoring topics are very interesting to me.
[00:09:55] I’d love to hear your experiences with refactoring, some of the things that you’ve found that
[00:09:59] have been helpful to you.
[00:10:00] You can always reach out and ask questions at developertea at gmail.com.
[00:10:04] Thanks so much for listening to today’s episode.
[00:10:06] If you don’t want to miss out on future episodes, make sure you open up whatever app you’re
[00:10:11] listening to today’s episode in and click subscribe next to the show.
[00:10:15] This will make sure that you don’t miss out on future episodes.
[00:10:18] Thanks again for listening, and until next time, enjoy your tea.
[00:10:25] Bye-bye.