Crafting Code Podcast
$ cd episodes/009-coupling-and-cohesion
~/podcast/episodes/009-coupling-and-cohesion $ ls -1a ~/podcast/episodes/009-coupling-and-cohesion $ cat episode-summary.txtCoupling and cohesion are fundamental concepts in software systems. From types of coupling to Conway's Law, Matt and Allan (sans Dave) discuss how these two ideas can affect your day to day work beyond just the formal definitions.
~/podcast/episodes/009-coupling-and-cohesion $ cat themes.txt ~/podcast/episodes/009-coupling-and-cohesion$ cat transcript.txt
[00:00:00] Allan Stewart: Welcome to Episode 9 of the Crafting Code Podcast, where we discuss the importance of doing the right thing at the right time with the right tools. I'm Allan Stewart, a software architect, and lately I've been thinking about using anti-patterns as a way to help people understand what can go wrong in my software system.
[00:00:17] Matt Baker: Hey, my name is Matt Baker, software architect. Lately I've been thinking about where the software industry is headed.
[00:00:23] Allan Stewart: Today we are sans our usual co-host, Dave Adsit, but we're going to solder on anyway and talk about coupling and cohesion. So coupling and cohesion is an interesting topic that gets brought up a lot in software projects. I first learned about it in a very academic way. And the academic definitions of these start with coupling is the degree of interdependence between software modules. So we're measuring how closely connected two resources. Routines or modules or functions are. And cohesion is the degree to which the elements inside a module belong together. And those are great definitions that oftentimes don't tell us anything about like what it actually means to us, right? So it's like, you know, telling me all the elements that make up my car. What do I do with that? Matt, what do you think? What does coupling and cohesion actually mean to the average software developer in their day?
[00:01:24] Matt Baker: That's a great question. You know, for me, coupling, the way this shows up for me day to day, oftentimes it's when things fail, when something goes wrong in my system. How many things go down with it? So at runtime, the service goes down that I maybe I'm hosting a service on my team. How many other parts of my system does it take down with it? How many dependent services are going down? And there's also a design time consideration here. You know, when I change my. Or let's say I'm dependent on a vendor's API and I need it. I need to upgrade the version of their API that I'm using to maybe fix a security hole or something. I'm pretty tightly coupled to that API. And let's say that the upgrade path or in order to make the upgrade, I also have to change the way I've implemented against their interface. I could be a design time coupling that will impact me. And that happens quite a bit. So for me, it's when things fail or when things are changed or let's stick with when things fail. How many things are impacted or how many things go down? That would be coupling. Cohesion is a bit more of a slippery one. It's one of those that I feel like I understand inside my brain. But when I try and explain it outside, it's clear I don't. But generally speaking, cohesion for me is how many places do I have to go in order to make a change? So depending on how you decompose the system or if you're working in whatever a single code base, how many files do I have to open up in order to implement a new feature or maybe change the way I'm doing? Like. Some state persistence. And the more the more thing, the more places I have to go in order to change something, generally the less cohesion I feel. Right. And the flip side of that is if I want to add a feature to a particular piece of a product and I only have to change code in one area, that to me would indicate there's a high sense of cohesion in this feature.
[00:03:16] Allan Stewart: Yeah, I agree with that. Another thought that comes to me for cohesion is could you take something away from this? That. If you're taking something away is difficult. So, for example, a class. If you take out a private member variable or a function. If that class can't operate correctly, then there's a good chance that that had high cohesion. They belonged together. But if you can easily take something out, it's like, oh, this doesn't belong here. It shouldn't be in the same file or the same class or module or whatever. I've thought about it in the past to use just a really simple example. Sesame Street. I grew up watching Sesame Street. Sesame Street and they used to sing the song that one of these things is not like the other. To me, that's kind of the essence of cohesion. This thing doesn't, it's not the same. Don't put
[00:04:04] Matt Baker: things that aren't the same together. Yeah, I really like that on a very micro level. Like I'm thinking of a class and I like the litmus test you just gave or, you know, you take a variable out. If one of the functions breaks, that's a degree of cohesion, but if seven break, that's a greater degree of cohesion. That's a cool model. I like that. Yeah. And there's a bunch of different
[00:04:25] Allan Stewart: axes by which things can be alike or different, you know? So like with physical objects, we would think about them in terms of like different classifications, right? Are these all the same color or are all these the same size or shape? There's similar things in software that we can look to and see like, oh, do these, are they the same? Are they similar? Do they go together? Or if they, sometimes they're dissimilar, but they obviously go together. Coupling can be, easy to tell a lot of times in code. I referenced something and now I'm dependent on it. There, there you go. That's coupling. But I kind of often imagine that kind of like those molecular models students will get to learn like chemistry or something like that. Or if you're old enough to remember Tinker Toys, that you've got these different elements that you can connect together with like rods, essentially. When you take these two things and you connect them together with a rod, now they're coupled. And you might have different lengths of rods and maybe some are flexible or, or springy or something else, but there's these different ways you can connect things together. And that's the, that's the degree of your coupling. It affects software projects in a similar way, because when you connect up these things, depending on how you connect them up can really change the structure. So if you connect them up in like triangle and like pyramid kinds of shapes, they become very rigid and they don't move. Which can be great if you're trying to, you know, support a structure, right? Like a physical structure. If you're laying them all out in like a chain, then it might still be, you know, very bendable. You might be able to bend and twist and flex. And I feel like software needs to have some of those same kinds of principles. How you connect the pieces matters. Some parts should not be able to move around a lot. And it's okay to have perhaps a tighter coupling between things that are supposed to be together. Right. Right. Right. And then there's other things you want to be able to have some flexibility. You want to be able to bend. And if you just keep connecting rods between all of the pieces, then eventually, and especially if it's haphazard and it's just like, oh, well, I can connect these two pieces, so I will. Then pretty soon you've got like this interconnected ball of mud, right? It becomes the ball of mud that we often refer to in the software industry. And then you're stuck and have a hard time moving your software. Right. Progress from there.
[00:06:53] Matt Baker: Yeah. The Tinker Toys example is interesting to me. And I could imagine a, like you said, a haphazardly connected blob that definitely maybe has a high degree of cohesion. Everything's in one place. I don't know. But the coupling could be interesting. What's another example of coupling and cohesion that sticks out to you, Allan?
[00:07:15] Allan Stewart: So another one that I've thought about is Swiss Army Knife. With a Swiss Army Knife, there's a degree of coupling and cohesion that you don't get on like a basic knife. So like if you just have a pocket knife that only has one blade on it, that's really high cohesion. This belongs together. You've got some blade on it and some handle so that you can hold it and manipulate it, right? And it's all connected. And that's great. High cohesion, low coupling. But it only does one thing. It's a knife. And so you get these other. Gadgets like a Swiss Army Knife. And now you've got a higher degree of coupling. There's multiple blades or tools that are all interconnected. And usually they open up on one side or maybe on two sides. But depending on how they're attached to each other, one tool might not be usable unless you close the other tool. They're coupled together. The cohesion goes down. When there was just one single blade and that was all you had, then that's really high cohesion. It's sort of like the identity function of cohesion, right? It's the one thing. If you've got several different kinds of blades, then that might still be really good cohesion, right? So like you might have like a straight blade and you've got a serrated blade and you've got like a sawtooth blade. All for kind of very similar types of usage. You can go in and cut materials, right? And depending on the kind of material, you choose a different blade. And that's perfect because you don't need two blades. Right? Same time. But the cohesion drops quite a bit as you add all these different other types of tools. Online, you see like all kinds of weird, funny things, you know, memes online about like a tongue depressor or a magnifying glass or a flamethrower or something attached to your Swiss Army knife. And these things are not similar. Like the corkscrew. A corkscrew is one that I've often seen. And, you know, it's there so that people can quickly open up bottles. But does it really belong with the other ones?
[00:09:22] Matt Baker: Yeah. Like how often are you using a corkscrew and a tongue depressor like in the same hour?
[00:09:28] Allan Stewart: Right. And your saw blade. Yeah. So the context for a Swiss Army knife is very different. Right. So like even if we throw out something like the silly ones where, you know, you open it up and there's a penguin attached to it or something ridiculous. The context for a Swiss Army knife is like you're going to go camping and you've got one tool that fits in your pocket. And it can do a bunch. Maybe not very well. Each individually. It's not like the best tool. But it's a nice well-rounded tool because you can't carry your entire shop with you. But you just have the one thing. Or maybe you like to carry a pocket knife just around the house with you. And so you can instead of going and finding the thing that you want, you know, you can just pull out your pocket knife and choose the appropriate tool and use it. That's great in the context of Swiss Army knife. But in the context of writing code, you almost certainly do not. You do not want to try to fulfill a whole bunch of different purposes in a really mediocre way. I don't know. There may be some cases where it could make sense. But most of the time, that high degree of coupling where you have all these different kinds of things and they're all connected and they force interactions with each other is something that you don't want. It limits your ability to change the software. It limits the usefulness of the software product. And that's one of those places where cohesion and coupling get to you. You're trying to build something. And for the sake of understanding, for the sake of usability, refactoring, et cetera, you want to have things have a much narrower focus and be intentional about how you couple the different components of your software project together.
[00:11:11] Matt Baker: Yeah, it's interesting thinking about a knife or like a Swiss Army knife. I'm sure I've done this myself. You pick up a multi-tool or a knife and you open it up and see what's inside there. And it's kind of like a Cracker Jack box, almost all the things you're going to find. And I'm sure I've said something along the lines of, oh, that's pretty cool. You know, like just not for any purpose other than like, oh, this thing has a knife, a sanding board and clippers. Neat. And I feel like in a similar way, sometimes when we talk about code or maybe more specifically when we're writing code, you might hear someone say, wouldn't it be cool if. Right. And like, usually it's a bad idea that follows that. Like, wouldn't it be cool if I combine these two things? And like, I could see someone potentially saying, wouldn't it be cool if I had a knife that just had all this stuff in it? Like, the thing that I'm trying to point out is there's no like real specific goal in that statement other than like, it'd be cool. Right. It'd be neat if I could do this. And maybe there's even a knife maker out there that thought it would be neat to show off how well they could combine a bunch of things together for no other reason. Then to show that they could do it. And I know that I've done that myself in code. I know other people that do that in code. Right. Where it's like, wouldn't it be cool if, and they throw out coupling cohesion. And really the goal now is like, how can I glue these things together in a cool way that maybe like reduces the code count or things like that. But like all the while introducing maybe some pretty nasty, you know, coupling and staying with this, this knife thing, this multi-tool theme. I was working out in my yard the other day, taking off some chicken wire fence. right not the right tool for the job but then all of a sudden I had a multi-tool without a knife and as time went on like I kept the multi-tool because there's so many other useful tools in it but every time I need a knife I have to go get something else and what the point I'm driving towards here is that sometimes like the way you should be combining things or the cohesion that you're working in emerges like you you learn about it over time so in this case when I broke my knife and then I you know went forward using the tool every time I needed a knife and didn't have it in that tool that was something telling me that there's a sense of cohesion here like whatever you're doing like you probably want a knife in here not maybe disregarding all this stuff in that tool for a second like you want a knife and you don't have a knife so like and now I find myself with a multi-tool and then a knife and and and either hand and these things are definitely coupled together right and both of these properties more so cohesion like in anecdotally cohesion forming more than coupling but I think both of these properties emerge and what I mean by that is it's almost a fool's errand to try and predict these things up front sometimes you have to like if you're joining large disparate systems and maybe a substantial distributed system you should take some time and really make sure you're doing things right if it's a change that's going to be really hard to unwind but oftentimes I think you can benefit from like the changeability of software and just try something and see what it tells you so in my case with my knife breaking and then always needing a knife or needing a knife a lot of the times when I have that tool that's an emergent property for me saying you want a blade in here and I think in code we get a really similar thing like if you're always reaching for you know I'm struggling to find an example right now but if you're always using one piece of code or if you're always reaching for let's say a library when you're using one piece of code in your system or an additional library maybe like there's something work but if you're always reaching for that code that you're using in the library you always reach for they go together I don't know how but they go together so the reason I think the emergent property is interesting and worth talking about is it allows you to exploit the changeability of software so instead of trying to predict all that stuff up front like how should I couple this system together does this class have like the right degree of cohesion those are like thought tracks you can get on that if you're not careful you can lose a lot of time and often you can short circuit that stuff by just putting something out building it doing it kind of maybe in the easiest way possible a lot of time to worry about the coupling more than, you know, what you feel is responsible. And then just let it tell you over time. Like if you notice that every time, you know, a product manager maybe asked for a feature change on something and you're changing two or three different places every single time, that's, that's a property telling you that these things are related in some way. And similar with coupling, if you find that when one part of your system goes down three or four disparate parts also go down every single time in a kind of a nonsensical way, like if your login goes down and then like your ability to make an espresso also goes down, like that's a weird coupling. An emergent property has said, hey, these things are coupled. And then it's up to you, you know, as the observer to decide whether or not you'd like that.
[00:16:25] Allan Stewart: It reminds me that we often talk about the desirable state to have high cohesion and low coupling. If coupling is kind of an emergent property, there's, there's some times where it's just obvious, right? It's like, these things just do not go together. Don't stick with it. Don't stick with it. Just because you can, right? Don't start off saying, well, the entire monolith is going to be in one file. That's going to, it's going to make you sad real quick, but I guess in a way that's emergent too, right? Like after a few minutes, you realize I do not want to keep scrolling up and down in this file. That's the emergent property of cohesion telling you, nope, this all doesn't belong together. But what it's going to say is that kind of the inverse then I think is true with coupling. Sometimes coupling does emerge. You just find it. It's like almost growing in your code base and coupling things together that ought not to be if you're not careful. And so you got to watch out for that because you have to have some sort of coupling or else you can't get anything done. Zero coupling means that these things are not connected in any way. They don't do anything together and that's not very useful.
[00:17:39] Matt Baker: Yeah. Yeah. I think all your code would just exist in these little silos, not doing anything with one another. And I think this is a good point to call out. Either of these properties taken to the extreme kind of result in a lack of usefulness. So really what you're playing is a balancing game here. You know that I think what we've observed, at least what I've learned in my career, that these things matter. Sometimes they're abstract. Sometimes they're squishy, but they do matter. You don't want to optimize for them at the expense of everything else for sure. But just be sure you're asking yourself things like, hey, when I couple these things together, I'm going to get a lot of things done. When I put these two things together, does that make sense? Is this the same coupling? Allan, you've mentioned a few times like this. It's almost like entropy or entropic coupling, let's say, where you're just as your system's building, you just connect things together, maybe without a lot of forethought and intention. And why not? That's why you do it. But at some point, you might become aware that, whoa, these things are too coupled. In order to release this small 20 line module, I have to also release 4 million lines of code in these other libraries. If that's a problem for you, and if that's taking a release cycle from minutes to days or weeks, coupling is a property that you should be paying attention to. Because if you reduce the coupling in that case, you'll potentially ship a lot faster.
[00:18:54] Allan Stewart: Yeah. It's a hard thing with software sometimes. You just kind of have to say, it depends all the time. I can't think of a single thing in software where you can just say, always do this. Take it to 11. Die on this sword. Because it's always true and there's never any exceptions. But rather, it's all like these optimization functions. How can I find a nice balancing point between all of these disparate things that are happening? And balance is important because it affects your ability to deliver software. Coupling and cohesion are two very raw, very basic principles that can make or break a software delivery cycle. High coupling can make it so that... Your release process is much longer, much more complicated. There's a lot more to test. Low Cohesion Consult Consult
[00:19:59] Matt Baker: Quip Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult Consult You can really get lost on this topic, but for me, it's things that change together stay together. And oftentimes, that's something, again, that emerges. You just have to be working in a system for a while and start noticing what things are changing together. And I'm not proposing, like, you keep a journal, like, when I changed this, A, B, and C had to be changed. Like, not at all. Like, it's more of an intuitive thing I'm saying. You're going to get a feel over time. Once you have an instinct that tells you, oh, if I change that file, I have to change that file, that's what I'm talking about. Well, that's when something has emerged and you're learning, you know, things that change together stay together. And all of this kind of is underscored by this, I want to talk about scope for a minute or, like, degree of impact. Like you were saying, Allan, if you maximize for these things in isolation, you're not going to get anywhere. And anyone listening is probably picking up on Allan's experience because he has a lot of it because he's able to tease apart here that, like, you don't want to maximize for these things at the expense of anything else. It's always a balancing act. It's always a big it depends. There's always nuance. There's going to be times where you want to do, like, an obscene amount of coupling and there's going to be time where you don't want to do any of it. There's going to be time where you abandon all cohesion. There's going to be times where you maximize for it. And it's a big it depends. So don't get stuck in, like, the I try to remind myself anyway, don't get stuck in, like, the good, bad, best, worst with this topic because it's a very nuanced one. And like Allan was saying, again, I think it's a tributary experience that it always depends. Everyone laughs at us. When we say that. But it's because it's true. Anyway, I want to talk about scope. So impact. When you talk about coupling cohesion, if you're in a small little code base, if you're writing the next little, like, Twitter bot or some little thing, coupling cohesion don't really matter. They will to a degree, sure. But that degree compared to a big distributed system is less. And so when I'm going and writing code, if I'm in a newer system or if I'm, like, in a new file, a new module I'm working on. The first thing I'm not thinking about is coupling cohesion. But as that system grows, your choices of coupling cohesion are going, the results of your choices, rather, are going to present themselves. And I believe it's your job to pay attention to those things and start responding to them. I think the great example for me here is monolith to microservices. Like, that transition is a lot of things. And one of the things it is is a decoupling exercise. Right? You're saying, like, I can't have this monolith as one thing because there's lots of reasons. It's not to have a monolith. What I'm going to pick is when a piece of the monolith goes down, the whole monolith goes down at run time. Right? So if a piece of your website goes down, the whole thing is gone. That's not great for your customers. So you might, that's coupling. Right? And that might not matter when you only have two pages. Like, if you have a login page and then a profile page for something, maybe it's okay that it all goes down. But when you have 50 pages and, you know, 50 times as many customers, it becomes less okay. So there is a concept of scope here and of impact. And the thing I think that's important, or the reason I think it's important to highlight that is don't get lost trying to maximize coupling and cohesion in these small code bases or looking for, like, oh, that's incorrectly coupled or if that's perfectly coupled when it doesn't matter. Because when they're really small, it really doesn't matter. But as your code starts to grow, the choices you made, the results will kind of start to present themselves. Listen to those and respond to them. And often it really helps to frame what you're experiencing in terms of coupling and cohesion.
[00:23:36] Allan Stewart: Yeah, I like that. And it also reminds me that you can have really good coupling and cohesion in a monolith. It might be a big code base. It's like a single code base. But how you divide up things inside that monolith can be done really well. In the same way, you can't just assume that if you go to a microservices architecture, you know, let's pull apart the monolith and make everything separate. Like, that doesn't automatically improve your coupling and cohesion. Instead of having a big ball of mud, you have now a whole, it's like a mobile.
[00:24:12] Matt Baker: I've heard it, spaghetti with meatballs.
[00:24:14] Allan Stewart: Spaghetti with meatballs, yeah. Where it's just, okay, now it's just everywhere. And there's lots of little balls of mud in orbit around each other, you know, in a really complicated mess. So looking at those things that you were just talking about, right? What kinds of effects are you seeing? How is it impacting your system? I like that a lot. One of the things I find interesting, I don't hear a lot about different types of cohesion. But you do hear about types of coupling. So a lot of the normal or general use coupling is when it's like, okay, this thing depends on that. Right? So class A references class B. Or, you know, it depends on it because it takes an instance of class B or it news one up or something like that. And so... You know, you've got coupling. And the degree of coupling depends on how much they have to know about each other. Right? So if you're newing up a class B, you have to know about all the constructor parameters that it takes. But if you dependency inject class B, then you don't care about how it gets made. Just, I just need one of those. And that's kind of the typical way that we often talk about coupling. But there are a number of different kinds of coupling depending on where you look. More different types than I feel like I could imagine. If you stop me on the street and ask me about like a random type of coupling, I might not know. Just because people have identified so many of them. But a couple that I think are interesting. One is temporal coupling. Temporal coupling is literally about time. Like how are these things connected through time? One of the examples that is often cited for temporal coupling is in your code. If you new up a class. Can you immediately use all the functions on that class? Or is there a prescribed order of things? And so that's easy to understand at the class level. But systems start to be that way too. Right? Like can you operate this function before the user account is created? Or does it require a user account first? Are there discrete steps in a process that have to be followed in a particular order? Those are temporal couplings. Or anything, really anything else that involves time. And so you have to make API calls. And you have to wait. Right? It takes time for something to happen. There's usually other things going on in your system. And so you're waiting for this temporal coupling to resolve itself. And you have to be aware that that is one of the ways you are connected to something else. Right? It wasn't that straight rod that was easy to understand. This is like, you know, connected through like a network. It's a magnetic force that is almost invisible. And it only activates in certain times.
[00:27:09] Matt Baker: The example, the service level example you're talking about is where temporal coupling really crystallized for me. And it was in an architecture that was an event-driven architecture that also had some API calls as a means of integration. And the model I saw that helped me understand it was when one service makes an HTTP call to another, there's, that's a pretty high degree of accuracy. And that's true because in order for service A to work, it needs to be able to call service B. So they have to exist and be available in the same temporal space. Right? And so if B is down, A is down. At least for the function that I'm talking about where A, you know, A means B. But you can really reduce that temporal coupling by introducing an event. It depends wildly on your use case here. But if you can, let's do an example. So if your service wants, if I have a service that's responsible for signing up users, and part of that is charging their credit card, that's probably going to mean I connect the user creation service to the credit card service over HTTP. So they're going to have a high degree of temporal coupling. Right? I'm not, when the user tries to say, sign me up, sell me an account, I'm going to charge their card right then. And if I can't charge their card, I'm not going to give them an account. Now, the reverse of that would maybe a different situation. Let's say when a user is watching a video, I just want to log it. So when there's a service that says, okay, user's watching video, and I want to also drop a log onto a disk somewhere. That could be an event-driven thing, right? I could just publish an event that says, hey, this user watched this video, and at some time from that point forward into the future, I don't care when, something else is going to pick that up and write a log to disk that says that user watched the video. So that's a low degree of temporal coupling, right? Another way of saying that is I don't need my logging service running in order to watch a video. If it's down, when the logging service comes back online, it'll process its queue of messages, it'll process its events, maybe off of like a log like Kafka, and we're all caught up, right? And you can kind of see how that stands in contrast to where one service needs another in a temporal frame. And that model, that's where it really clicked for me, this idea of temporal coupling and the ways to think about it or watch for it.
[00:29:25] Allan Stewart: Yeah, thinking about those things that are synchronous and asynchronous can help us understand, where temporal coupling is appearing in the system. And I think it's worth noting that like almost anything can be done either way. You can take almost anything that's synchronous and turn it asynchronous. But there's a cost involved and there's like difference of expectations, right? So like in your example, sometimes, yeah, you won't create the account unless you can charge it. But maybe it's okay to create the account and you put like a charge pending on their account. And they can't do anything. There's an additional cost there. Now you have to have different layer of access control. It's like, yes, you can be logged in, but you can't do anything because we're waiting for this payment to happen. But it also means that your flaky payment processor doesn't hurt you as badly if it's not up.
[00:30:19] Matt Baker: What an interesting like way for coupling and cohesion to impact the user experience, right? Like sometimes this stuff might fly under their user experience radar. But the example is this. The email you gave was really good. Like if I'm a user and I sign up and you don't charge my card and you limit my ability to use the site until my card is charged, that's a particular user experience. Or like what if you come back and eventually say, sorry, I had to revoke your account. Your card was declined. That's arguably a poor user experience. So it's interesting that we're seeing in this conversation impact to the user from the way we've connected our systems together.
[00:30:59] Allan Stewart: Another form of coupling that I've encountered that is one I didn't really think about for a long time is data coupling. If you're sharing data or using the same data, that's a form of coupling, which may not like it may appear in your code because you're sharing the same class and this class is holding the data that you care about. But other times not, especially if you add something like HTTP call or a message system. And now all of a sudden everybody cares about the same data, but it's getting serialized and deserialized. And so you're putting it back together. And the shape of that data, like the structure of how it's nested or even how it's stored can make a huge difference. So there's a project that I've worked in where the shape of the data persists all the way through. And it's caused a lot of problems because it persists all the way from the user interface through the business logic. And so if you make any kind of change to that system, like you want to add something in the database, then it pops up and appears in the user interface. Or if you want to change some business logic, then now you have to rewrite the database and the user interface because all these things are coupled together. They had to change together. And it wasn't that they're all sharing the same code, right? The front end is, you know, some JavaScript front end and the database. The database is, you know, your favorite flavor of SQL or whatever. And in the middle is, you know, your favorite back end code. And maybe they're even all three different teams. And yet they were coupled together based on the structure of this data. What I found to be more and more important in software systems is that you should protect the structure that you care about that helps you behave in the way that you want to behave. And when you interact with other parts of, you know, the same system or when you're interacting with separate systems or in a distributed system, you're going to be able to do that. And in the case of, say, a distributed system, there's kind of this translation layer in domain driven design circles. You know, this is called, like, the bounded context. And at the edges of your bounded context, you want to have these anti-corruption layers, which basically do this translation. I don't speak the same language as you. You know, you give me some data, and I'm going to reshape it. I'm going to throw away the parts that I don't care about. I'm going to attach it to other parts of my own data that I do care about to make it easy for me to use. And then when I pass data on to something else, I know how to access it. I'm not going to expose everything I know, but only the things that are important for somebody else, lest they get highly coupled to my data, and now I can't change the structure.
[00:33:37] Matt Baker: Agreed. This point really resonates with me right now, due to some conversations I've been having lately. I found that on this point, I diverge with what I'll call, let's say, like data professionals, at least the ones that I've been having some conversations with. When you couple data together, I'm thinking about like data from different domains. So when you take data, like a user in one context, or one domain, and try and make it work in another domain, like let's say specifically, you want to use the same user model throughout your entire system, let's say. There's a coupling happening there, right? And even if it's just a conceptual one, or in this case, let's say it's a schema, that model is, everything is beholden to that particular model. And so when you change that model, a lot of stuff has to be done. And what often happens in practice with data coupling, I found, is that the model, the more places it's used, the more it's diluted, the more it's diluted, the less effective it becomes. So over time, you kind of get like a, your pure user object will start to grow some warts, right? All of a sudden, it's going to have a little field that's only relevant to one of the 10 people that depend on it, one of the 10 systems. And then that problem will just repeat, repeat, repeat. And eventually, you get to a place where you have this one. It's a massive object that doesn't make any sense anymore. And you need a whole nother layer of definition in order to even work with the thing. So this idea of like data coupling, this one's part, it just sticks out to me right now as kind of a powerful one and one to avoid. And one that for one reason or another, there seems to be a divide. I'm not going to say all software engineers think one way and all data professionals think another. And I'm not even going to call those distinct roles in every case. But what I've found is that if you've erred more on the side of building, you're going to have a lot of data coupling. And if you've erred more on the side of building software systems, you tend to take on this idea that I think, Allan, you and I are in favor of, which is don't try and use the user model everywhere. Like create models for their pockets where they make sense. And then I found with data professionals, they're more like, I need everything to adhere to this one model. And it makes sense, you know, depending on how you're using the data. If you're a data professional, you might be consuming a lot and trying to tell stories about a whole system. And it sucks when you have to go translate a bunch of times. But there's a reason you have to do that. And it's because on the software side. We really get into a lot of trouble when we try to use the same data models everywhere. Again, going back to our earlier comment, doesn't matter if it's a simple little system. Really will start to matter if you're talking, you know, hundreds of thousands or millions of lines of code across 10, 20 teams. Your data coupling can really bite you if you're not careful.
[00:36:14] Allan Stewart: So with all these different types of coupling, and we only touched on a couple, is there value in measuring coupling? Coupling was the one that is inherently. Easier to measure because cohesion kind of requires like almost a judgment call. Right. I don't know. Maybe there's some like great machine learning algorithm that can help us detect cohesion. But coupling is pretty easy. Does this reference that? Yes. Okay, great. They're coupled. Even some of the temporal coupling can be detected. Whether something is initialized properly, or if you're making an HTTP call, then we can say, yep, there's temporal coupling right there. I know that there are some static code analysis tools that will help you to. See the coupling in a system. How useful is that?
[00:36:58] Matt Baker: Yeah. Uh, I'll lead with like my own personal purely anecdotal position that I don't know how well I could defend. I don't like these static tools, uh, static analysis tools. I think that they can often like send you down bad paths where, you know, if you measure a system that has high coupling, you'll immediately go try and reduce it. Maybe you didn't need to, it might not matter. Um, so generally speaking, should you always reach for static? Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Yeah. Those are all indicators that you should potentially have a conversation about something. In that sense, I think they're really valuable. Like all things, this can be taken too far. If you have someone who's kind of the coupling cop or the static analysis cop that's running code and coming around and saying, change this purely because they want to reduce the score or a number, less useful. I don't buy into that as much. But as a means of just a way of getting signals out of a system, I think they're valuable. I'd agree with that assessment.
[00:38:18] Allan Stewart: One of the areas I think is really interesting is code visualizations. And oftentimes coupling can show up there. So you see some interesting code diagrams and it can help you understand the way that your system is connected. Or you can have discussions about like a Netflix Death Star microservices kind of thing. But in the day to day, I'm not sure how often that that has really helped me very much. For me personally, I've usually gone to different tools. At different times and more often than not, it's a whiteboard where I'm just describing something because it's almost like you're taking these cross sections with these kinds of tools and measuring coupling is a cross section of your system. And it might be really interesting to look at and you might learn some really powerful things, but you have to take it in context. If you turned things in a different way, you get a different cross section. And so you have to be really careful. How you interpret those results.
[00:39:21] Matt Baker: I've never heard that term cross section. And I'm going to start saying that all the time now. What a great way to put it. You know, you take a slice of it and it tells a particular story, given the way you cut it. And you know, the term coming to my mind right now is vanity metric. Like, uh, I definitely seen some coupling measurement results yielded effectively in a boardroom. No doubt, you know, on a PowerPoint slide, they make a point. And if you need funding, if you want to get a funding. Project funded, or you're, you're, you're an architect trying to get someone to pay attention to the risk in your system, you know, um, they can make a point similar to the way security people like have their security risk scores. And they're like, it went up by 20 units this month. And like, no one stops to be like, well, what the hell is a unit? Like, what does that even mean? You know, they're just, they're making a point that like, there's been an increase in something bad. And, uh, in those ways, you know, it could be useful.
[00:40:14] Allan Stewart: Yeah. Measuring coupling can be useful, but you have to. Be careful with it. And I think where you use it really does apply at these different scales. Like you were talking about, what are you trying to accomplish by it? Right. Are you in a board meeting or are you in a small little code base where it doesn't really matter very much because the maximum degree of coupling and cohesion, you know, can't escape the small ball of, you know, your five file toy problem. And so it makes me think about how coupling and cohesion affects architectures. As we move up the stack from talking about individual lines of code, individual classes. Now we're talking about deployables and distributed systems and things, then coupling and cohesion start mattering a lot. We've talked about monolith a little bit before and microservices. Those are kind of like the in vogue architectures that everybody talks about and the coupling and cohesion can matter a lot. And like we said before, you can get it wrong either way. Choosing microservices isn't a panacea. Neither. There is a monolith. You can also start applying some of these other areas of how we think about systems like domain driven design. Uh, in domain driven design, you've got this concept of the bounded context and the bounded context becomes like a container of cohesion. All the stuff that belongs together, go together in this thing. Everything that's related to X is going to be part of this bounded context. And we have a, this ubiquitous language that. It means that we're talking about the same thing here in this space. And then the coupling comes, you've got some internal coupling of how that microservices put together or how this bounded context is put together. And then how does it connect with other things that represents at a system level? Your coupling. If you're in more of like a monolith style system, then, or, or even within like a single bounded context, if you're in D. D. Or a single microservice, then inside there, you can look at the coupling and cohesion as a way of how you architect that piece. And there, I really like the idea of hexonical or sometimes called like onion architectures, where you're putting your business logic in the middle and kind of this like protected space in the middle where you're saying all the logic that really matters for my business. I'm like, what are we actually trying to accomplish? Is in one place. And it's cohesive. And these other things that are incidental to your business, like having a database, nobody pays you to have a database. But you, but they don't want you to forget their data unless they send you a GDPR request. Then they want you to forget all the data that you've ever had, but they don't pay you to have a database or not. They pay you for, to accomplish some kind of service. Right. That's, that's your business logic. And so you don't want to couple those things too tightly together. Right. So that the database is, is directly tied up with delivering that service.
[00:43:22] Matt Baker: One point there, Allan, you used a word that was super telling for me. You said you put your business logic in the middle and you protect it. What an interesting word to use when we're talking about coupling, right? Because I'm fairly certain that what you meant there is you protect it from being connected to things that are incidental, like writing to a database or you protect it from infrastructure, you know? And so when we talk about coupling, all of a sudden we're talking about defense. Like you want to defend. Certain parts of your code from, from being polluted from other parts of your code where you can, and it definitely doesn't make sense to interleave a bunch of infrastructure code in your business logic. And just as an aside, this hexagonal architecture, the onion architecture, right? I really hope this kind of architecture gets, gets back into the limelight a little bit. I feel like it's maybe falling away a little bit, but it's such a powerful architecture.
[00:44:11] Allan Stewart: One thing that I think is often overlooked is that whenever. Anything affects your software architecture, it also affects your people and vice versa. And we often refer to this as Conway's law, which basically says that any system that you build will inevitably mirror the communication structures of the people who build it. So if you have a company that has particular org chart, essentially, you can oftentimes look at the software and see the org chart. By the way. You know, if, if you know a few things about like, okay, which, which teams own, which parts of a system. In that way, I think coupling can also be observed and measured across the people. How is your organization structured? Do you have individual silos of work? Right? So like, oh, we've got the dev team and the product team and the testing team and the security team and the operations team. If you have all of these. Individual teams and their silo, then you'll see that your overall software system will also have these similar kinds of couplings. The way that you communicate between team members can also be reflected inside of your software and these, these lines of communication. That's one of the areas I think is really interesting as far as like system failures go. It's not uncommon to hear about people adopting something like agile. They had a consultant come in and teach them all about. Scrum. So they try to start doing scrum, but they don't really change the organization. They just try to change the behavior of the people involved in software or sometimes just only like one narrow band. It's like, well, we're not going to change your product team and your testing team. We're only going to change the developers and they're going to be agile and nobody else is going to be agile. And then we wonder why it fails.
[00:46:05] Matt Baker: Some of us, some of us wonder why it fails.
[00:46:09] Allan Stewart: We wonder how it could have ever succeeded. And the same thing happens with this company. Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our Our
[00:46:45] Matt Baker: the org structure. Yeah, I'm kind of clapping and crying over here all at once. Both ways, you know, from an org trying to change its structure, being ignorant of the code that needs to change, and then people changing code structure, being ignorant of the people that'll be impacted. Both of those have been razors that have cut me really deep. You know, so I'm glad we're talking about this point. What I want to say is that people that write code all day, they develop an intuition for coupling and cohesion. They understand this really well. A lot more than people that don't write code, I think, because they're just steeped in it all the time. They're dealing with the trade-offs, the cons and effects of coupling and cohesion. That type of modeling that works in code can also work in designing people orgs, right? You can look at the people org and kind of think, okay, these components have to couple together this way, and that means that when I change that group, I also have to change this group, or like I can't put that group under a new leadership structure without also taking this one, or I have to solve for how to decouple those. Like these are all things that... If I start changing the terms like people and orgs to like code and libraries that engineers are dealing with all the time. So one thing that I would hope happens in our industry is more and more people that are designing orgs that haven't written code, I hope that they don't make those changes in isolation. I hope that someone designing an org doesn't just say, all right, change all this stuff, all these teams, go. And just not be thinking about the code that's underneath that's going to have to change. All like the new communication channels, that they just set up that are fresh, that are going to take some time to like, either person on the end of those comm channels is going to have to get used to the other people. And so what I would say is if you're a person designing an org and you're not a coder, maybe go get a coder and just spend some time talking with them about how should I think about this in terms of coupling and cohesion? And you can talk about things that change together, stay together. That's true for code and that's true for people too. Go get the teams that you're going to impact, specifically engineers, talk about coupling and cohesion and make an informed decision. Where you account for both the people in the system, to Allan's point, that coupling and cohesion affect both the code architecture and the people architecture. And the reverse cuts back the other way. If you think you're going to design a brand new system or implement a brand new architecture, and you're not talking about how your teams talk to one another, how you move products through like ideation to delivery. If you're not considering that when you're designing a new architecture for a company, especially if it's a bigger one, you're doing the same thing. You're designing with one eye closed, and when you try to implement one of the casualties, it's going to be a lot of the people's way of working around you. You're changing the way that they talk, the way they interact, the way they deliver, and those are substantial. And if you don't consider both of these things when changing org structures, coupling and cohesion will step up and get you.
[00:49:33] Allan Stewart: And I think it's an interesting way to look at organizations along these different axes. Once again, coupling is the one that is easy to measure, right? What does the org chart look like? Who do Who are they talking to all the time? But then cohesion is an interesting one because sometimes in an organization we say, oh, well, we're going to do cohesion by organizing everybody by the kind of work that they do. Say, oh, ta-da, we've got high cohesion by putting all the UX people into the UX group and all the product managers and the product manager group and all the testers into the tester group. And that definitely has high cohesion, but the cohesion matters depending on what you want to accomplish in your system. And that's the first step. And then the second step all time all time all the things at the same time , all the things at all all all all all all all all all all all all all all all all all all then that can turn the system on its head, sort of refactoring your people structure into a format that allows you to get value done. So if the change that you want to make is deliver a release of a software package or a feature, then you want to have cohesion with all the people who can do that effectively.
[00:51:07] Matt Baker: Yeah, it's interesting. I liked your idea of if you put all the UX together, if you put all the DBAs together, the security together in their little silos, you have a high cohesion. But as soon as you try and run a delivery through that model, you're going to find that, okay, first I have to go to UX. Okay, now they're done. I've got to go to security. Okay, now they're done. I've got to go to the database. Now someone screwed up in UX, got to go back to UX, then you got to go back through it again. And so, yes, you have high cohesion and there's a degree of coupling there, but you're seeing that it kind of sucks. I have to go to all these stops along the way to deliver something where if your cohesion, or like the axis by which you were measuring your cohesion change to how many, let's put everyone together that's necessary to get this feature out the door. Same degree of cohesion. Well, I don't know, but same concept of cohesion, but you're interpreting it differently going back to what you were saying, your cross-section, right? That's just a different way to look at it. And hey, you might be in a domain where you want those things separate and you want all the throws over the fence from UX to DBAs. You might be in a domain where it's more valuable to put everyone that's necessary to ship something into prod on one team. And that's a degree of cohesion and away it goes.
[00:52:28] Allan Stewart: I think it depends on your domain, but then also what are you trying to achieve at any given time, right? So like maybe you do want a really cross-functional team to deliver software, but for training, you're going to bore the UX people to tears And so maybe you should get all your software people together to do training. And your UX people can train with each other and talk with each other about the design system and how do you make a unified look for your branding or for your distributed system or whatever it is. So the purpose for what you're trying to accomplish at any given time also affects the cohesion that is in play.
[00:53:11] Matt Baker: As we're winding down this conversation, Two thoughts that I'd like to share on coupling and cohesion in no particular order here. My career has taught me that you should couple slowly and with intention. Oftentimes I'll avoid coupling and instead duplicate. And what that might look like, practically speaking, I'll write the same piece of code in two places instead of when I notice that I need a piece of code that I've written somewhere else and where I'm currently working, I could couple those together or I could just duplicate the code. As always, it depends, And oftentimes I've found that I'll duplicate first and that's because I appreciate coupling slow because there's always going to be effects and impact from coupling. Sometimes you're not ready to deal with those or sometimes you don't want to deal with those. So don't deal with them until you have to. So I avoid coupling and I'll duplicate. I have a rule of thumb, usually three times. I'll duplicate something three times and after the fourth time, I'll say, wait a minute, there's something that's happening here. I should pay attention to it. Along the lines of duplicating code, oftentimes I hear people, when I give that line, people will say, well, it's not DRY. And like, I've come to resent this. The DRY thing, DRY is an acronym that stands for don't repeat yourself. And it's similar to the S, the single responsibility principle in the SOLID acronym. And my response to that has now become sometimes something is so DRY that it chafes. DRY in and of itself is not something to just optimize for all the time. And so it's okay to duplicate a little bit. For me, at least, I've decided it's okay to duplicate if it means I can avoid coupling or even kick coupling down the road a little bit, you know, to make the choice of how I'm going to couple things when I have as much information as I can. If I can delay that, oftentimes I will. So couple with intention slowly and don't be afraid of duplicating on your road to eventually coupling. Last thing I would say, don't get stuck trying to find the perfect decoupling. Or the most appropriate cohesion. Don't get stuck thinking, oh, my architecture is not right. These things shouldn't be coupled. I'm going to change them when the only reason you're saying that is because you read the latest microservices book and it said you were doing it wrong. Don't get in that trap. You can really get into this mode of like what's right and what's wrong, ignorant of the context, and try and achieve this like perfect technical polish. In this case, with either coupling or cohesion. Don't do that. My advice is just don't do that. Just pick what makes sense in the moment based on what you know. Avoid making choices like coupling choices that are hard to undo if you don't have to make them. Just take your time. Maybe most important for me lately when I've been in design discussions with people is, especially when you get to kind of like a choice that could go either way, I say just pick one. Just pick one and go. Pay attention to the effects. Like I don't think that we as an industry spend enough time really appreciating how quickly software can change and how you can use it. And then use that to make a decision and then revert that decision later. So don't get stuck. There's no perfect decoupling or there's no perfect cohesion. Make a choice and see how it goes. Like we've been talking about, if you decouple a system a certain way and then you find out that every time you need to change one component, you have to change all of them, consider putting those things back together. Similarly, if you find that at runtime when part A of a 20-part system goes down and it takes 15 other parts with it, think about like disparate parts, think about whether or not that makes sense. And if it doesn't, decouple those things. But you can do that after spending some time living with the results of your actions instead of trying to get it right the first time or trying to like lead with the perfect thing. And I'm saying all this because these are all things that I've struggled with. I've struggled with coupling too early because I thought it was the right thing to do or because it was the perfect design. I've struggled with spending a lot of time like analyzing cohesion to see if like it's right without realizing that right is such like a contextual and subjective word. And then for me, just being okay with getting it wrong and fixing it when I find out the way I got it wrong. That was a hard fought, hard won battle for me personally. And so those are maybe the points of guidance I would give as we wrap up here.
[00:57:28] Allan Stewart: High cohesion, low coupling. It's a good guideline. The definitions sometimes are very academic, but the implications of them really are going to really impact us in our day to day. As always, we recommend that you, our listeners, join up with a community of professionals by attending a Software Crafters group or meet up near you or any other community group where you can discuss things like coupling and cohesion. Here in Utah, the Utah SC group at utahsc.org meets the first Wednesday of each month in Draper. Maybe we will talk about coupling and cohesion with you there.
Copyright © 2026 - Crafting Code Podcast