The Bike Shed
353: Mental Models
Mental models are metaphors that help us understand complex problems we work on. They can be a simplified roadmap over an infinite area of complexity.
How does one come up with mental models? How are they useful? Are they primarily a solo thing, or can they be used to communicate with the team? What happens when your model is inaccurate? Today, Joël is joined by Eebs Kobeissi, a Developer and Dev Manager at You Need a Budget, to discuss.
This episode is brought to you by Airbrake. Visit Frictionless error monitoring and performance insight for your app stack.
Eebs on Twitter
You Need a Budget
Skill floors and skill ceilings
Transcript:
JOËL: Hello and welcome to another episode of The Bike Shed, a weekly podcast from your friends at thoughtbot about developing great software. I'm Joël Quenneville. And today, I'm joined by Eebs Kobeissi, a Developer and Dev Manager at You Need a Budget.
EEBS: Hi, Joël. It's really good to be here.
JOËL: And together, we're here to share a little bit about what we've learned along the way. So, Eebs, what's new in your world?
EEBS: Oh, a whole lot. I'm a new dad, so I'm getting to experience all those things. But in the developer world, I've recently picked up programming on an ESP32, which controls LED lights. And so I'm having fun lighting up my office.
JOËL: Is that like one of those little microboards, kind of like a Raspberry Pi?
EEBS: Yeah, exactly. It's a little board that's compatible with the Arduino IDE. And I literally only played with it last weekend, so it's still very new to me.
JOËL: Nice. Have you done any Arduino development or Raspberry Pi or anything like that before?
EEBS: No, I have a Raspberry Pi that I run like a DNS server on, but I haven't done any actual programming. I did make an LED blink, which is pretty cool.
JOËL: What kind of programming is required for a board like that?
EEBS: From my understanding, it's either in Python or C. Those are, I think, the two languages that you can program on it. I definitely do not know C. And so I'm just going through a bunch of tutorials and reading some sample code. But I think if I ever end up trying to implement something more complex, I'll probably switch over to Python because that's a little more familiar.
JOËL: So the coding feels fairly high level even though you're writing controller code for LEDs.
EEBS: I hope so. I'd love to be able to take advantage of whatever abstractions I can.
JOËL: Do you have any fun goals you're trying to do with this? Or is this just for the fun of trying a completely different environment than web development?
EEBS: No, it's actually rooted in something visual. So I have these shelves behind me that are in my webcam when I'm in meetings or whatever. And so I want to be able to put a light strip across these shelves and have some sort of visual thing in the background.
JOËL: Like LED mood ring?
EEBS: Yeah, kind of. My eventual goal would be that as I'm talking, a little equalizer display pops up behind me. I thought that would be pretty neat.
JOËL: That is amazing. That will give you all of the cred in the meetings.
EEBS: Right? I thought that'd be pretty cool. What have you been thinking about recently, Joël?
JOËL: I've been submitting to the RubyConf call for proposals which, as of the recording of this episode, has just closed this week. And like many people, I submitted on the last day.
EEBS: [laughs]
JOËL: And it was really fun trying to take some ideas that I'm excited about and then turn them into a proposal that is accessible to other people.
EEBS: Nice. Do you want to share a little bit about what the talk is, or is it under wraps for now?
JOËL: I don't know if anyone on the committee will listen to this before the review goes out. This might break the anonymity of the proposal.
EEBS: Oh, right, right.
JOËL: One thing I will share that's interesting is that there are topics that I'm excited about. It's like, oh, here are a bunch of cool things about something, some technical topic. But talks that are just ten cool things about X are not that great. And so I needed to find some sort of unifying idea that I could use to share that. And that generally is in the form of trying to find a story that I can tell. What unifies all of these things together? What tells a compelling story? Is there some metaphor I can lean into?
EEBS: Nice. I think that's a really powerful way of communicating something deeper is through telling something that people can relate to.
JOËL: One way that thinking about metaphors has been really impactful for me recently is the idea of mental models and how those can help us in development. I'm curious; we've thrown around the phrase a little bit you and I in past conversations; what does a mental model mean to you?
EEBS: I tend to be a visual thinker. And from talking to others, I've heard similar statements. So for me, a mental model is how I think about a particular domain or how I think about code flow or structure. And for me, it's usually either as two-dimensional objects or occasionally three-dimensional objects that I have floating in my visual space.
So, for example, if we had two classes that are collaborators in some way, I often think of them maybe as two rectangles that are side by side. And when they interact, there's some little amorphous blob from one of those rectangles that reaches out into the other one or passes a message from one to the other.
And I sort of have this idea of how many connections are there between these two physical things. Or, if I'm thinking about code flow and the path of execution that code might take, sometimes I visualize it as maybe a tree or potentially loops if there are such cases.
JOËL: So when you think of these concepts, just in general, you're seeing in your mind's eye squares and rectangles floating in the air.
EEBS: Yeah, pretty often. Sometimes it takes those shapes, and as I build up a mental model of some code, I'm usually adding new shapes into that picture I have in my mind. I tend to view things sort of top-down. So like, the start of code or the start of execution is usually at the top or maybe the far left or far right.
And as execution happens, I usually view that as moving in towards the middle and potentially going back out when a response is returned. If it's a web request, something like that, I view it as this sort of outside in. And there's a bunch of pieces in there that are all talking to each other.
JOËL: That's really cool. So not only is there a geometric aspect to it, but there's a spatial aspect to it as well.
EEBS: Yeah. And it's interesting, like, I haven't actually thought about it [laughs] in this level of detail before. But yeah, there certainly is a spatial aspect to it. And I have this idea in my mind of like things and domain objects kind of belong at the bottom, and they should have well-defined boundaries. But the pieces that are a little bit towards the outer edges may be a little more fuzzy and may have less definition around them.
JOËL: That's really interesting because I also have this sort of in my mind's eye see these things when I'm thinking about concepts like that. But I've talked to other people, and some people don't even have much of a mind's eye at all. They don't tend to visualize things in their mind in that way.
EEBS: Yeah, it's really interesting how different people approach this thinking about code. A lot of people write things down. And I write things down, too, and draw little arrows that don't really make any sense. But it helps me do something physically sometimes as well as just thinking about it.
JOËL: Have you ever tried to convert these pictures you see in your mind and actually draw them on paper?
EEBS: Occasionally. And for the most part, that usually takes the form of some kind of domain modeling, whether it's based on database tables or just domain objects. And sometimes I will try and draw them out and then specify the relationships between them like, oh, you know, this one model talks to this other model in this particular way. And I'll define a relationship between them, which helps me think about them and how they interact.
JOËL: I've found that even though for some things I can see it very vividly in my mind's eye, I struggle to then concretely translate that onto paper or digital paper if you will. It's almost like trying to, say, translate an emotion into words and that even though I feel like I see a visual picture, I can't reproduce it by drawing necessarily.
EEBS: It's interesting you brought up feeling because a lot of the times, I have this gut feeling about a mental model, like whether I think it is correct or not. And sometimes I have this uneasy feeling of, like, that doesn't feel right to me, but it's hard to articulate why. And I think sometimes that's when I have to pull out something physical, start making those relations, start connecting things.
And that's when I might uncover, like, oh, this feels odd because I have a circle here or a cycle or something. Or I've sort of represented the truth of something in two different places. Do you have any techniques for getting it out of your head and into something physical that you could share with someone else, maybe it's text or a picture?
JOËL: I think I do struggle with that conversion sometimes. Practice definitely helps. I think maybe there is a metaphor here between converting these, let's call them, pictures that I see in my mind's eye and then drawing diagrams with trying to take feelings and expressing them in words. In the same way that, maybe I might have some feelings, and then I want to journal how I feel, and I struggle to express that.
But finding a way to express that gives me a certain amount of precision and a more concrete thing. In the same way, these things that flash in front of my mind's eye, if I can take the time to put them on paper, they're now more real. They're more concrete. I think you can probe the edges, the ways that it kind of falls apart more easily.
EEBS: Yeah, that makes a lot of sense. There's a lot of value in writing that down and going through those details in a methodical way because oftentimes, you'll catch inconsistencies, or you'll find better ways to describe it. And being able to share your mental model with someone else is often...well, it can be really tricky.
And I think that's why it's important to go through and maybe find a common medium that you can share because I can't see into your brain. You can't see into mine. But if we can share our mental models, then hopefully, we have a better chance of agreeing on the solution or finding inconsistencies.
JOËL: Exactly. I think, in many ways, there are almost multiple layers of mental models and that you might have an abstraction or a metaphor for a concept that you're working with separate from the diagram. And then the diagram is yet another metaphor, but now we're going geometric to represent a broader idea.
EEBS: Yeah. Are there any other ways that you take that picture from your mind's eye besides written documents or conversations? Do you use any diagramming tools that specifically help with that? Or is it just kind of free-form?
JOËL: I do a mix. I am a big fan of draw.io, which allows you to just free-hand or pull shapes together, things like that. There are some more structured tools that I will use. I'll use Mermaid.js.
EEBS: Yeah, I've been using that a lot too.
JOËL: Yeah, that's great. I've been digging into more structured diagrams recently, particularly the idea of graphs, directed graphs. And those have interesting properties.
EEBS: Can you share a little more detail about what you mean?
JOËL: So a graph in the computer science sense is a bunch of nodes. They are typically represented as circles and then edges which are the connections between them. A directed graph is now there's an arrow pointing in a particular direction. A really interesting property that you can have with directed graphs is whether or not they include cycles. So can you only by following the arrows effectively create a loop? Or will the arrows always lead you to some kind of terminal node?
EEBS: Gotcha. Is that a directed acyclic graph?
JOËL: If there are no cycles, yes, it is a directed acyclic graph or DAG, as you'll often see it abbreviated.
EEBS: [laughs] How do you relate that graph to code? And what benefits do you get from expressing it that way?
JOËL: So this shows up in a lot of places. And I'd even say that thinking of certain aspects of my code as a graph and a potentially directed acyclic graph is itself a mental model or a metaphor that helps bring clarity to the way I think about things. So, for example, code, you know, you invoke some main function at some point to call the code, and then that's going to call out some other functions, which call out some other functions, and so on. You may have heard that referred to as a call graph. But that is a graph of calls.
There might be cycles in there for co-recursive functions and things like that. But that is one way you can then sift through and analyze how control flow or how logic flows through your application is through a function graph. You mentioned earlier the idea of objects and how they're connected to each other. That's an object graph.
EEBS: Right. Recently, I had to work through a state transition problem where a customer has some billing, and they can go through many different states, whether it's active, or canceled, or past due, those sorts of things. And so actually, I reached for Mermaid.js and built a graph of, okay, they start here in this empty state. And then they subscribe, which then they become active. They might cancel their subscription, which moves them to a different state.
And by listing out all the states and the transitions between them, it helped me to understand what methods I might need to define on which objects in order to allow those transitions to happen and what checks I might need to make before allowing those transitions depending on the state of the system.
JOËL: I'm hearing the keywords states and transitions. And that's making me think of finite-state machines. Are you drawing a finite-state machine graph or something a bit more free-handed?
EEBS: It's a bit more of free-handed. I don't think I've actually drawn out a state machine since college but just representing the different states as different boxes and the transitions that are possible from those states. I mean, I guess that kind of is a state machine in some way. So graphs are great visual approaches. Are there any non-visual approaches that you take?
JOËL: That's a great question because not all mental models have to be visual. I think the power of a mental model exists in a metaphor. And one that's kind of broad but that I've applied to a lot of different areas is the general idea of something being parallel or in series. I think I first came across this concept talking about electric circuits. And are we talking about two little light bulbs that are in parallel, and if the electricity to one is cut, the other one still lights up? Or are they chained together in series?
EEBS: Yeah, like my LEDs.
JOËL: Exactly, going back to Arduino, but it can also be applied to a bunch of other things. We can talk about code being in parallel or in series. We can talk about work being in parallel or in series. Interestingly, I took that mental model as a sort of quick shortcut when I was digging into some functional programming ideas. Monads and applicatives are the fancy terms here.
EEBS: Oh boy, I'm ready.
JOËL: In general, and there's a hefty asterisk here, I think of monads as being serial, so you're chaining something; one thing happens, then another. So you can think of, for example, chaining promises in JavaScript, promise one, then promise two, as opposed to applicatives which are parallel. So you might think of maybe zipping two lists or two arrays in Ruby. The two arrays, there are no dependencies between the two of them. They get processed side by side as you're traversing both of them together.
EEBS: Interesting. I've heard the term monad a lot, but I haven't heard the term applicative. Are there any other details you can share about them and what makes them different or how they might be seen in our code?
JOËL: I think that the key difference is that distinction in how they're processed. Applicatives are a way of combining two independent, let's call them data sources, and then you find a way to combine them together. So it could be two independent arrays, and you're zipping through them. It might be two independent HTTP requests, and they can both fire in parallel. But then you want to combine their outputs. So you say wait until both are successful and then combine their output.
EEBS: Oh, okay, gotcha.
JOËL: It could even be nullable values. So you say do this thing if both values are present. But you're not...the value of one or the fact that one is null or not is not dependent on whether the other one is null or not. They're independently null or not as opposed to something...Monads are, again, a different way of combining. You might call them data sources or operations. But in this case, there is a clear dependency one, and then its output influences the next one.
You might say check the value is null or present or not. And then, if it is present, take that value and then put it as the input of my next operation. And then, if it is null or not, do another thing. See, now you have a sort of chain.
EEBS: Where do you see these chains happening in code? Or is it everywhere?
JOËL: Once you know that pattern which, again, could be thought of as another mental model, you start seeing it everywhere. So promises in JavaScript chaining together that's effectively monads. Don't @ me, all the functional programming people.
EEBS: [laughs]
JOËL: I know that's not quite true. Anything dealing with multiple operations that could succeed or fail depending on, again, whether you're treating them as dependent or independent, that's probably going to look very similar to either monad or applicative.
EEBS: So the first thing that actually comes to mind here is things like background jobs. Using Sidekiq or Resque or other job processors, you can have a queue of jobs that need to be executed, and they might need to run in serial, or potentially you have multiple workers pulling from a single queue, and thus the work is happening in parallel. Is that a reasonable analogy?
JOËL: I think it's good for the serial versus parallel, but it's not necessarily a good analogy for understanding monads and applicatives.
EEBS: Gotcha.
JOËL: So with two workers, you can process a queue in parallel, and a bunch of things happen.
EEBS: But there's not necessarily anything that is bringing those two workers together to produce a single output.
JOËL: Yes. And there's no dependency between the tasks in the queue.
EEBS: Right, right, gotcha.
JOËL: So if you have a task that says execute this task and then only if this task succeeds, then do the second task, now you've created a dependency. And you couldn't process that in parallel because if task one, which has to be executed first, is executed by worker one, task two should not get processed unless task one is successful. You can't just say, oh, I've got another worker free. I haven't processed task two because it's waiting to know does task one succeed.
EEBS: Right. So an example in code would be a user creates a new order. And when they create a new order, we send them a confirmation email. That would be an example of that happening in serial or a monad-like thing. [chuckle]
JOËL: Yes, I found that thinking of things as serial or parallel is a good shortcut for thinking about monads and applicatives. I don't know that the reverse is necessarily true. They don't necessarily transfer one-to-one with each other. And maybe that's a danger of mental models, right? You find a mental model that describes a situation, and then you try to reverse it, and then you make false assumptions about the world.
MID-ROLL AD:
Debugging errors can be a developer’s worst nightmare...but it doesn’t have to be. Airbrake is an award-winning error monitoring, performance, and deployment tracking tool created by developers for developers that can actually help cut your debugging time in half.
So why do developers love Airbrake? It has all of the information that web developers need to monitor their application - including error management, performance insights, and deploy tracking!
Airbrake’s debugging tool catches all of your project errors, intelligently groups them, and points you to the issue in the code so you can quickly fix the bug before customers are impacted.
In addition to stellar error monitoring, Airbrake’s lightweight APM helps developers to track the performance and availability of their application through metrics like HTTP requests, response times, error occurrences, and user satisfaction.
Finally, Airbrake Deploy Tracking helps developers track trends, fix bad deploys, and improve code quality.
Since 2008, Airbrake has been a staple in the Ruby community and has grown to cover all major programming languages. Airbrake seamlessly integrates with your favorite apps to include modern features like single sign-on and SDK-based installation. From testing to production, Airbrake notifiers have your back.
Your time is valuable, so why waste it combing through logs, waiting for user reports, or retrofitting other tools to monitor your application? You literally have nothing to lose. Head on over to airbrake.io/try/bikeshed to create your FREE developer account today!
JOËL: Another mental model that is not necessarily visual that I like actually comes from the video game community, and that's thinking of skill ceilings and skill floors. So in, I think, particularly the MOBA Community, that's a Multiplayer Online Battle Arena, they'll talk about characters as having a high skill floor or a low skill ceiling.
And generally, what that means, and again, the meaning varies a little bit by community, is that a character with a low-skill floor is an easily accessible character. They might not have a lot of skill shots, like, you press a button, and things happen around your character. You don't need to aim, things like that. A high skill ceiling means that there's a lot of room for you to grow, and as you get more skilled, you can get significantly better with that character.
EEBS: Gotcha. So the opportunity is greater with a higher skill ceiling.
JOËL: Correct. And depending on how the character is set up, you might have a very narrow range that could be in the low range where it has a low skill floor and a low skill ceiling, which means that the character is easy to learn. But once you've learned it, there's not really a lot you can do with it. It's a fairly basic character. So getting better at the game is not necessarily going to make you that much more impactful.
And then you could have one that's the opposite that is high both skill floor and skill ceiling where a character is very hard to learn. But once you learn it, that's kind of all there is to it. And then you might have one that has a large range somewhere; maybe it's easy to learn, but it's hard to master, or there's a lot of room for growth.
And so, taking this framework for analyzing characters and video games, I think we can apply that to technology in general. This could be language design. This could be just API design. And you might say, well, I want this to be very accessible. People can jump in very easily. You might say I want this to be very powerful and have a lot of high-end features that make your power users very happy and very productive.
EEBS: That's interesting. When you first were talking about it, I was actually less thinking about it from a user's perspective of what maybe they could do in the application but potentially from the standpoint of a developer writing the system itself.
One of the pieces I always come back to in software development is that change is inevitable. And so, making something easy to change often pays great benefits down the road. And so I wonder how that fits into this idea of a low skill ceiling or a high skill ceiling in terms of perhaps flexibility or being decoupled such that you can take one idea and easily extend it or easily get more from it than you originally set out to build.
JOËL: There's often a trade-off. So you make something easy to change. It's highly decoupled. But you maybe introduce more indirection to the system. So while it's easier to change one single piece, it's harder to understand the system as a whole.
EEBS: Yeah, that's true. And sometimes, you bake in assumptions that you make about the future, which turn out not to be true.
JOËL: [laughs] Yes, that is definitely something I'm guilty of.
EEBS: I think we all are.
JOËL: One thing that I find interesting is as you evolve the design of an architecture pattern, a system, a whole language, you might want to move one of those if I think of them like two independent sliders on a one-dimensional scale. So maybe you want to move the upper boundary a little bit and say I want a higher skill ceiling for this, but they don't actually move completely independently.
So introducing some advanced features might inadvertently also raise the skill floor. And conversely, making the language super accessible so that it has a low-skill floor, you might have to decide I will not introduce certain features.
EEBS: One thing I wanted to ask you about is, do you view different languages as having different skill floors and ceilings? And, you know, I love Ruby. I know you love Element. I've played with Element. It's been a great learning tool for me. How do you view those two languages in terms of skill ceilings and skill floors in terms of, I guess, what you can do with them?
JOËL: That's a great question. And I think you can definitely apply that to languages. Admittedly, I think you could probably start a lot of flame wars with that.
EEBS: [chuckles] Let's not do that.
JOËL: I wrote an article a while back where I applied that mental model to look at the F# programming language. And there was a debate in that community about certain features to add and whether they would allow advanced programming but potentially at the cost of accessibility to newer members of the community and how to balance those. And so I thought, hey, let's throw this video game metaphor at the problem and talk about it through that lens.
EEBS: That's really cool. Did you draw any conclusions, or was it as a way to start a conversation?
JOËL: It is a way to start a conversation. I don't think there is a single correct or best distribution of your skill, ceiling, and floor. It has to match the goals you set out for your project. Just like in games, people love to rank which characters are best and not. And sometimes you can show that, in general, this character is better.
But oftentimes, in a balanced game, you can talk about this character being easier to get started with or this character working very well if you're a pro. But the fact that you have a higher or lower skill ceiling or floor doesn't necessarily make the character better or worse.
EEBS: So, this conversation about differing mental models, I think I hadn't realized that there can be so many different types of mental models. And some things that I do in my thinking I haven't classified as a mental model. But now that you bring it up, I think one that I think about fairly often is this idea of two objects that are collaborators and reaching into the internals of one of those objects from the other object.
So A and B are two separate things. And if A reaches into B's bucket and messes with the state of B, I view that as sort of a bad practice. You're not really adhering to maybe the public API that that object is exposing. You're kind of reaching in and going around behind its back and changing some stuff that it may not expect.
JOËL: Would you refer to that maybe as tight coupling?
EEBS: Yeah, it's definitely tight coupling. It's not just tightly coupled; it's almost worse than that. It's almost like going behind somebody's back and making a change without them knowing. And so when I see that in code or when I write code that does that, I have this really intense desire to separate that and to say, no, no, you can't go in and update this record directly in the database. You have to send it a message and say, "Hey, I would like you to be aware of something," and then it goes and changes its own internal state as a response to that.
And so I have this very vivid sort of mental feeling of it being wrong, of it being like, I'm being sneaky, or I'm not being gracious to the person I'm interacting with as though I were one of these objects.
JOËL: That's fascinating. You've practically anthropomorphized these objects.
EEBS: I do. I view them as little people.
JOËL: You describe this interaction as going behind someone's back. That is the thing that I, a person, do to someone else. It's not a function making a direct call. And yet, it's such a strong...we use a social mental model to talk about objects and interactions.
EEBS: Yeah, I almost want them to be friends. And I think that applies to real-life relationships, right? If you have a nice dialogue back and forth, there's an understanding. There's commonality that you can find. But if I were to go do something behind your back without chatting with you about it first, you might not be so happy with me.
JOËL: I'd feel betrayed.
EEBS: Right.
JOËL: I feel like there's probably a really fun conference talk to be done about that. We often use that metaphor; I think when talking about objects sort of subconsciously but making it explicit and just being, hey, let's talk about these objects as if they were people. Why don't we want to do this? Because this one here is betraying the other object there. This one here is being impolite.
EEBS: We could have two people get on stage and talk to each other. And I might then go and reach in your pocket and pull out some change without you knowing, and you might be upset with me.
JOËL: That would be great. Get a little skit going up on stage. Or even if you're artistically inclined, you could probably draw some really fun little characters to illustrate this.
EEBS: That would be really cool. I, unfortunately, don't have the artistic talent to do that.
JOËL: Well, free conference talk idea to all listeners of the podcast. I expect to see this for RailsConf 2023, maybe.
EEBS: I'll be looking for it. So I've shared a mental model that I didn't really know was a mental model. Are there other mental models that you want to share that I may not be thinking of?
JOËL: Here's one that I've just come to realize recently that I'm actually quite excited about: when you think about the word refactoring, how would you describe that idea?
EEBS: Well, refactoring to me is changing the implementation without changing the behavior.
JOËL: Yes, I think that is the classical definition. You should be able to change the implementation of a method, and the tests without changing are still green after you've done that.
EEBS: I guess, mentally, I think about that as perhaps drawing a box around some of the objects that are floating in my mind's eye, rearranging how they exist within that box, and then the box dissolves. And the tests still pass, but the structure of the objects or the code has changed in my mind.
JOËL: I love that you immediately went to a visual approach there. And I think I have something similar, but I'm coming at it from a slightly more domain modeling perspective. So thinking maybe less from an individual method approach but looking at maybe a larger system, what you're trying to do is use code to describe some version of reality. So it might be a business process that you have. It might be trying to describe some aspect of your customer's life that you're trying to automate for them.
Oftentimes, this thing you're trying to describe in code terms is going to be a simplification because life has a ton of edge cases, and many of them we don't care about. So if we go with a visual metaphor here, you're trying to draw some kind of shape using only straight lines to approximate some weird curve.
And so, let's say you draw something with only four lines. It's really simple, how you have a diamond. That's the shape you're trying to create. And then you're going to fill it in with little other shapes that approximate a diamond. And those are your different models and functions and all the other components that we use to build software.
At some point, your understanding of the underlying reality might change. Maybe you need more precision, or maybe the actual feature requirements have changed. The thing you're trying to approximate with your code is not a diamond. Maybe you've added a few more sides to it. It's a pentagon. So we've gone from four sides to five. And the little components, and modules, and things that you have there approximate that diamond work.
They still mostly approximate your pentagon, but it's really clunky because the initial design was to approximate something else. They were really good for fitting in really tightly and being very loosely coupled to each other when we were trying to do a diamond, but then they don't work as well in the pentagon.
EEBS: So maybe some of the internal shapes need to change or adjust to fill the space that the pentagon has now created.
JOËL: To fill the space or maybe even just to fill it in a way that's less clunky. And so the idea here in this metaphor is that the reality we're targeting in software is always changing. And so the underlying reality changes, and so we're changing that shape that we're creating all the time.
But also, we're getting more precision as we decide; oh, we care about this edge case now. We didn't in version one, and so as part of that, we're constantly having to take the modules that maybe were very well designed initially but then restructure them to fit the new requirements because now there's a fourth object coming in, and it's kind of clunky with our current configuration.
EEBS: That's interesting. One of the first things that jumps to mind is that maybe there are better ways or worse ways to do that refactoring to fit that new shape. Do you think there's any truth to that in the sense that you might initially design a system that perfectly fits that diamond or very closely fits that diamond but then as it changes to a pentagon, do you need to simply add a new piece to fill in that empty space? Or do you need to restructure everything within the diamond now to fit the shape of the pentagon?
JOËL: Oftentimes, you do need to restructure. And I think there's this wonderful little phrase from; I believe it's Kent Beck that says, "Make the change easy, and then make the easy change."
EEBS: Yep.
JOËL: And so, to me, that makes the change easy is that initial restructuring that you need to do of those first shapes so that you can finally bring in the new one.
EEBS: Oh, that's a cool visual. I immediately can imagine the pieces in the pentagon moving around to make space for a new piece that you need to now bring in. And that movement of all those pieces can be really difficult.
Have you ever played that game where it's a square, and you're trying to get a ship out of a port, but there's a whole bunch of other ships, and you can only move them left and right and up and down? And you can do that. And that's what I'm picturing right now is moving shapes within that pentagon to then make space for either a new shape or to allow a shape to escape that is no longer relevant.
JOËL: I played a version of that that had cars, cars, and trucks.
EEBS: Gotcha. Yeah, I think I played that too.
JOËL: That would also be a fun conference talk, right? Like, start with that game as your initial metaphor. And then you use that as a way to talk about refactoring.
EEBS: That would be really cool.
JOËL: I would watch that talk. To anybody listening who wants to give that talk, I want to see you at RailsConf 2023.
EEBS: [laughs] Are we just a talk factory now?
[laughter]
JOËL: I love talk ideas. Maybe this should become a segment. Just have Eebs come in for five minutes once a month and give us a talk idea. It could even be fun to see a talk idea that multiple people implemented differently.
EEBS: That would be really cool, actually. I always get nervous about giving talks or being on podcasts like this one. I would love to be the person that gets to sit there and throw out random ideas and have other people fulfill my dreams.
JOËL: Well, thank you so much, Eebs, for joining us to talk about mental models. And to all of our listeners, I'd love to hear about what mental models you find are helpful, and so please share them with us. On Twitter, you can reach us at @_bikeshed.
EEBS: Thanks for having me, JOËL. This has been super fun.
JOËL: And on that note, let's wrap up. The show notes for this episode can be found at bikeshed.fm. This show is produced and edited by Mandy Moore.
If you enjoyed listening, one really easy way to support the show is to leave us a quick rating or even a review in iTunes. It really helps other folks find the show.
If you have any feedback, you can reach us at @_bikeshed or reach me at @joelquen on Twitter or at hosts@bikeshed.fm via email.
Thank you so much for listening to The Bike Shed, and we'll see you next week. Byeeeeeee!!!!!!
ANNOUNCER: This podcast was brought to you by thoughtbot. thoughtbot is your expert design and development partner. Let's make your product and team a success.
Sponsored By:
- Airbrake: Deploy fearlessly and fix bugs faster with Airbrake Error & Performance Monitoring. Airbrake notifiers are available for all major programming languages and frameworks, and install in minutes, with an open-source SDK-based install and near-zero technical debt. Spend less time tracking down bugs and more time developing. Visit Frictionless error monitoring and performance insight for your app stack.