A book club for developers.
BookBytes is a fortnightly (or biweekly) book club for developers. Each episode the hosts discuss part of a book they've been reading. And they also chat with authors about their books. The books are about development, design, ethics, history, and soft skills. Sometimes there are tangents (also known as footnotes).
(Intro music: Electro swing)
Hello and welcome to BookBytes, a book club podcast for developers. We’re continuing our summer of Imposters’ Syndrome by talking about “The Imposter’s Handbook” by Rob Conery, which is a CS primer for self-taught programmers. Today we’re going to go over the chapters about software design patterns and software design principles.
I’m Adam Garrett-Harris.
I’m Safia Abdalla.
I’m Jen Luker.
I’m Jason Staten.
All right. So let’s talk about first what is software design patterns? And then just an overview of something interesting or new that we learned.
Any takers on it?
I think we kind of talked about software design patterns when we went through “Apprenticeship Patterns” because those are soft skills versions of the same thing.
Where it’s like a common solution to a common problem.
Yeah, that’s a pretty good concise definition I was kind of a little speechless, because I was struggling to come up with a good definition of design patterns, and that was actually one of the things that I really liked about this chapter and what was new to me. There were patterns that I already knew and things that I was using that I never just had the words for. So as I was reading this chapter it was really great to say, “Oh. That design that I implemented that I really didn’t have like, a name for? That’s what it’s called.” Or that thing that somebody was talking about that I was like, “Oh, that seems like a useful pattern. That’s what it’s called.” So that was one thing that I really liked about the book is that it gave me the words to use to define the things that I already, kind of, had experienced or seen.
Uh-huh, interesting. So did you study this in college in your computer science degree?
Yeah! So that’s a great question ‘cause actually… let me think. No, I did not. There weren’t any classes at the university that I went to that were just like, software design. There was a software engineering class but it didn’t talk about this particular set of things. This was my first time like, seeing the term, “Facade”, I think that’s how it’s pronounced, used to define the pattern of an abstraction that hides implementation details. Like, you know, that’s… Again, like I knew the definition but I didn’t know the word so it was great to kind of see that. Or like, a Bridge or a Composite.
Yeah that’s interesting.
I feel like I didn’t really do any of these things until I learned about them first.
I should clarify. It’s not like I used every pattern in this chapter in my career. Like some of them were definitely new to me, both in like definition and design, and also the term. But, you know, for some of them I had used the pattern I just never really knew what to call it.
For all the things that my university skipped over, the Gang of Four “Design Patterns Book” was actually one of the things we spent a bit of time on. And while I learned about them, didn’t necessarily have a use case for all of them, but they are kind of those things that sit in the back of my mind that there is like, a common pattern for so like, they can resurface. And then, kind of like Adam said, where not so much, not doing them before learning about them but knowing about some of the design patterns, it does give a chance to intentionally go and do them. So that’s the nice thing for me is that you can think about a specific scenario and being able to have some level of pattern to approach it with. And you definitely don’t need to use all of them. Many of them actually serve a similar purpose as like a way to go and extend functionality of something that you already have within your codebase without going and making large changes across your codebase because of it. Kind of increasing maintainability, or at least that’s the goal of some of them.
Yeah, so I have a question from say, a newer engineer to someone who’s worked more in the industry. When you’re having design discussions with your workmates and you’re trying to convey that you want to use one of these patterns for something you’re implementing, do you use the actual term? Like, do you say, “Oh, let’s use the Mediator Pattern to do x,y,z.” Or like, is this part of your lingo? Or generally not?
Some of these are. Like, Constructors and Factories and Builders and things but once we got deeper in and started talking about like, Mediators and you know, Facades, those I hadn’t heard of before. Flyweight? Not even close.
You know, Composites? So I mean, it’s not so much “We’re gonna use this pattern.” As much as you just say, “I’m gonna use a Factory.” And people know what that means.
That makes sense.
Similar for me.
It’s... a few of them that are more common, definitely I think Decorator is one of the more common ones and a Factory, I’d say. And I guess, for something like Flyweight I don’t think that’s ever come up as a topic. Like I had to relook at the definition of it and it’s probably a factor of, most of the time, I’m not in need of something like the Flyweight. But I did go and find a pretty good example of where it can be applicable, though.
Because even with Rob’s example I wasn’t totally solid on it. I’m like, “Why would I want to do this thing?” Other than it made it so you could instantiate some more instances, or like, you’d instantiate lots of instances and share a bit of memory and there’s actually a website that’s called Game Programming Patterns that covers the Flyweight in terms of actually rendering a game.
So if you think about a game that has a forest-type background to it and in the forest there are thousands of trees, or just an immense amount of trees, and you have to draw those things through the GPU, if you have one hopefully you do at this point, and to actually go and spend the time to draw all those things would be really expensive to do and GPUs now have what’s called instance rendering where you can say, “I actually want to draw the same tree over and over and over, I just want to put it in different places.”
And so it’s kind of a form of doing the Flyweight where you go and give like, the actually polygons that are supposed to get rendered, those are all identical it’s just where location-wise it gets rendered, and so it breaks the Flyweight up into two different parts for a model. You have first your intrinsic state which is a shared state amongst everything, like, the polygons that need to get drawn. And then each model also has extrinsic state, which is a unique state for each model being something like its position, and I thought that that was a pretty good example. I’ll share a link with all of you because it was insightful to me.
Please do, I’m really interested in that.
Can you explain really quick what Flyweight is exactly in a more general sense?
So a Flyweight is a way to share memory across a whole bunch of object instances. So say you’re newing up a whole bunch of objects. Rob does give the example of like, a query-type provider, and those happen to have a list of tables in them. I have to go and look up exactly which page it’s on, but you go and are able to reuse that same piece of static memory across all of the instances as if each instance had that state within it. And so it saves you a lot of memory, because to go and to load all of the tables from the database every time you wanted to make a query would be really expensive, but if just the first time it loads it and then the rest of the time they just share it, that’s what the Flyweight does, is it’s sharing memory but it’s kind of behind the scenes.
Okay. And I guess it’s called Flyweight because it kind of loads up once and then after that it has momentum because it’s already ready to go.
Cool. What other patterns did y’all find interesting?
I found the Composite Pattern quite interesting, which is basically a pattern that links parent/child relationships. So it allows you to develop relationships for things wherein if the child doesn’t exist the parent can’t either. And the example that the book showed, it’s on page 252, is example of a connection pool for a database which is basically a way for keeping a certain number of connections to your database alive that you can use when you’re executing queries so you don’t have to reconnect to the database every time.
I actually found it really useful ‘cause we were talking about connection pools at work a while back and we were talking about some bug that we were dealing with and, at the time, I hadn’t realized that it was a Composite Pattern. And in hindsight, knowing this would have kind of helped me understand things a little quicker. So it’s just kind of cool to see an example that was really direct to me and also the word for what that design pattern was.
Yeah, that’s cool.
Yeah, nice to be able to put a name to something. Something that you’re doing.
For me, one of the things that I didn't quite grasp was the Adapter versus Bridge and what the major difference between those two patterns was, and I looked over the code and it was kind of clear? But not totally.
And a Bridge, on the other hand, is something that you would implement before the alternatives are implemented. And what that allows you to do is code up almost like an adapter itself, but that’s built against an interface. So it’s built kind of two levels deep and what that allows you to do is make changes to what the bridge provides, but because it’s implemented against the interface, the interface stays the same, but the Bridge is able to change. And I guess I haven’t found myself actually ever needing to use a Bridge but, in simplest terms, the Adapter is for connecting things that have already been implemented. And the bridge is designed for things that have yet to be implemented but you know there are going to be lots of implementations.
Oh, okay. Interesting. So those two things almost sound, now that you explain it like that, sound similar to the one I wanted to talk about which is the Façade Pattern. Do you see some similarities there? Because the facade pattern is kind of putting a bit of code between some other code. So it’s a façade to that other code. And I think, in general, the book says it hides implementation details. So I guess it kind of makes it simpler, but it also allows you to change out what is behind the façade.
It’s more like you’d use a Façade to choose which adapter you’re going to use. So you would pass your entire query to the Façade, the Façade would be the one that’d say, “Okay, well this is what this is, so we’re going to use the JsonAdapter.” Or, “This is what this is, so we’re gonna use the XmlAdapter.” And that Adapter would then talk to the database it needs for those purposes.
So that Façade happens to be, or have a Factory behind the scenes that is allowing multiple implementations to be used across a Bridge?
So you have the Façade that you just tossed stuff at, the Façade says, “Okay, this is the Adapter we need.” And then the Adapter uses the Bridge to actually connect to the portion of the code that we need to talk to the database.
Yeah, and all that messy stuff that goes on back there, that’s kind of the whole notion of the façade, is kind of simplifying the interface of something so users don’t necessarily have to deal with it, or know about the implementation details which can sometimes be really good. And sometimes you do need to expose the internals, but if you think about something like Babel versus the Babylon parser. That will, it kind of covers up all that. It’s a Façade in front of it that lets you work nicely with it and you don’t have to concern yourself with all the details of the parser and instead you just say, “I want these plugins.”
Yeah. I feel like I’ve done kind of a simple version of a façade before where… I don’t know, I have an API coming in with certain data and maybe the endpoint isn’t even built yet, so instead while I’m waiting on the endpoint to be built, I make a Façade and, it’s probably just looking at a .json file or something and then returning me stuff, and I’m building a Façade for the way that I want the API to look, and then after the API is built if the data comes back slightly differently that’s fine. The Façade can just rearrange it a little bit and pass it on.
I feel like that’s what a mock is.
I mean, I guess that that would, in some ways, fall under it because you’re not changing details under the hood. I feel like Façade is also kind of a generic name for a pattern, because I mean it definitely allows something like mocking, but also I mean, mocks are a form of the Adapter Pattern in some sense in that, like, you have a fake implementation of an interface that’s programmed against.
Yeah. Yeah, I feel like Façade might be an overloaded term.
And there’s… Really, I feel like, a lot of overlap amongst all of these. Or like, they’re kind of… I don’t know.
A lot of them are similar it’s just where in the level of implementation is it actually located.
Yeah. Jen, did you have one that you found interesting?
I thought I did the Flywheel (laughs).
Yeah. Oh, I thought Jason did that one?
I talked a little bit about it.
Jason did do that one-
But I was the one who mentioned it. (laughs)
Cool. All right, well, anything else about this chapter?
You know, some of the portions at the end I really liked. One quote, more specifically, from it says that, you know, “As you implement patterning as we’ve done here, the code you write tends to become more generalized and you end up writing a lot more of it just to do a simple operation. This is not what these patterns are for. A design pattern should make things simpler. If you implement one, have a look at your code before and after and see if it makes more sense or less.” So I liked the idea of, you know, diving into the next chapter of YAGNI in that you don’t necessarily need to dive into these patterns until the complexity gets to the point that these actually simplify them.
Yeah, that’s a good point. You don’t want to use them just for the sake of using them, or to look smart.
I agree with that, and that is also another why things like GIT are so amazing because if you go and, before you refactor some of your code into some of these design patterns, you go and make the change and then all you have to do is roll back quite simply and, you know, if you said, “This was not really worth it to spend all this time on a Façade with a Factory that bridges.” Then you can roll back out.
So since you mentioned GIT, you opened that can of worms and I’m going to totally take the…
Take the wheel.
Take the, yeah, I’m taking Safia’s tangent for this section. (laughs)
And I’m gonna say that one of my favorite uses for GIT is specifically that. To be able to make those refactors and really see if the change made a difference. And I also use GIT as a way to adventurously make refactors. It’s how I learned to understand webpack as deeply as I do, it’s because I wasn’t I wasn’t afraid of changing it because I’d just roll back if I break everything. So, I learned a lot about how my programs work, how webpack works, how Babel works based on the benefits of being able to just back up and refactor at will. And that’s the end of my tangent.
I’ll take that and wrap it right back into the chapter. So, he mentions a pattern that’s called The Memento Pattern and he didn’t actually describe it in the book but he said it’s yet another that’s within the Gang of Four, and I’ve looked up what it is and it isc a form of undoability. So-
Yes! (laughs) And so GIT very much allows you to do that where The Memento Pattern is something where you can say, “All right, I want kind of a saved state for this thing so that way I can roll back to that point whenever I want to.” And then the object itself knows how to use that memento to kind of rehydrate itself back to the original state. So, for example if you do a ‘git commit’ and you get yourself a SHA, then you have a state that you can tell your git head pointer to point at whenever you want to, much like The Memento Pattern.
Which, again, is great for teaching yourself things by breaking it and fixing it again.
Cool. Let’s go to a sponsorship real quick.
So this episode of BookBytes is brought to you by V School. It’s established in 2013 and it’s Utah’s highest ranked coding boot camp and the first of its kind in Utah. It’s actually GI Bill approved and one of only two coding boot camps nationally to partner directly with Adobe on inclusion-based coding scholarships.
You can choose to learn full-time or part-time in the evenings and completely immerse yourself in learning new skills. They really encourage you to take a campus tour. It’s in Salt Lake City. You can come meet their students and faculty and even shadow a class and see if it’s a good fit for you.
And if you go visit, tell them you heard about them on BookBytes and it will help support the show.
V School. Life awaits! Launch a career in code, design, or data.
And thanks to V School for sponsoring the show. All right! Software Design Principles.
Favorite chapter out of the pair. Again, because it referenced things that I had heard people discuss recently and I had done the thing where I kinda like, was in the meeting where it was mentioned and I nodded and pretended that I knew what people were talking about and then I went back to my desk and like googled what it was to try and figure it out. Which we’ve all done at some point. (laughs). But in that case, for me, it was the YAGNI pattern which touches on what we were talking about earlier with respect to not adding unnecessary complexity to your software if you don’t know that you’re gonna need it.
And I think one of the most common ways that I’ve been stabbed with this is attempting to like, future-proof things in anticipation of a use case that might come up and then just implementing really terrible, messy code and the use case that you imagine never comes up, and you didn’t really need the thing that you ended up writing.
For those of us that can’t go google right now, what is YAGNI stand for?
So YAGNI stands for “You Ain’t Gonna Need It!”
Which is a…
Favorite of mine. (laughs)
We’ve got another friend of the YAGNI.
Absolutely! Both YAGNI and DRY, which is “Don’t Repeat Yourself”, are definitely favorites of mine, but you do have to be careful with DRY, but let’s go back to YAGNI because I love YAGNI, I use it all the time.
Yeah, I actually had to google this a couple weeks ago when I heard someone at work say, “YAGNI.” And I went and googled it and I was like, “Oh yeah, okay.”
The basic is you can’t future-proof, and if you future-proof too hard then you end up with a lot of code that you don’t necessarily need, like you said before. The benefit of this is you only code what you need right now, and if you end up getting to the point where you’re going to need it later, code it then. I mean, two separate stories and therefore you can kinda test out that the concept that you’re working on, right now, works before you try to expand on it later. If you spend too much time future-proofing you end up wasting lots and lots of time and you add lots of complexity to your code for something that you could have just whipped out real fast and been done with and never touched again, possibly.
Yeah, and I think, probably, software engineering might be one of the things where YAGNI is the most needed just ‘cause it’s so easy to add another column to the database or another method to this class, or another, you know, prop to this component. Like, it’s so easy to just go down that rabbit hole that you have to like, restrain yourself from adding extra things that you’re not gonna necessarily need at the moment.
Yeah, unlike with like, road construction you don’t have to get approval to go buy more cement, just in case you might need it, need it (laughs).
With YAGNI, much like a logical fallacy when you’re debating with somebody, don’t use YAGNI as your sole reason for shutting somebody down-
When they do want to go and implement something, because that is pretty rude to say. Like, if they have something with an eye towards the future and your counter argument is, “You ain’t gonna need it.” Then that can be not productive. But rather, have that discussion with them because, oftentimes, like, if somebody is seeing something and you’re not, it’s good to go and at least come to the same page so that way you can both agree or disagree that you’re going to need something in the future.
Absolutely. That’s definitely a good idea to have that discussion. I’ve also been in conversations with people that have just gotten excited about, you know, an aspect of a program and they say, “But well we could do this! And we could do that! And we could add this! And we could change this! And we could modify it in order to be able to do all of these things!” When the actual goal of the program was just to do this one thing. And yes, maybe those things might be useful in the future, but if we’re not going to be potentially needing those things in the next 3 months, 6 months, 9 months, 5 years? Then don’t spend the time, right now, getting those implemented. And I think that that’s where it’s really supposed to be used. You know?
And I really like the fact that they’ve brought in test-driven development as a way of enforcing YAGNI in that if the code that you’re writing and the implementation that you’re using doesn’t actually touch a bit of code, then you don’t need it. So the use case that’s required is what your test defines, and if you don’t have to test it,, if you don’t have to touch it, if you don’t touch it, then you don’t need it.
Yeah. Can I go on a side rant about TDD?
(laughs) So, I’ve been… I’ve struggled with TDD for a long time. Like, at internships, and open source work, stuff like that. And one of the things that I always run up against is the fact that TDD requires that you outline the design for your code in tests, and I’ve always tended to be the person who, as I’m thinking through a problem, I’ll prototype it in code and then evolve it to a complete implementation, not write a spec for it and then write the implementation. So I’ve always, you know, struggled and I think fairly struggled with TDD just ‘cause it doesn’t align with the way I think; which is at first, I think about how to solve a problem and tinker with the different solutions and then write the test for it. Not, you know, write the exam and then study for it. Do you get what I mean?
I think a couple different things. So there’s two aspects that I really think of when I go for test-driven development. One of them is that it is a paradigm shift, just like going to like, state-based architecture was a huge paradigm shift. Same thing goes with test-driven development. There’s some that say you have to write all of your tests before you start coding and that’s like, ridiculous. I like to start with, you write just enough tests to get your first fail. So at that point your tests starts with, you know, does one equal false? So it’s just like, a very simple did you instantiate a class or did you create anything whatsoever? And it’s going to fail so then you write the thing to make it pass, you know? Does it exist? True! Good enough, okay. So now what’s the next portion? So it’s step-by-step, you end up doing your tests as you’re writing your code.
For me, I like to prototype out my code through code comments so I start commenting out like, “Well I need this and I need this, and if I’m going to do this and I’m going to do that.” And my code gets more and more commented as I get deeper into the implementation, but as I’m getting to that level my tests get more and more detailed as well. So, for me, test-driven development is I write just enough a test to be able to get the next part failing and then make it pass. It’s not getting it all written and getting it all completed and then starting to code the thing that you’re coding.
So some spoilers for both of you, that in the testing chapter he actually goes through a big TDD advocate, Brad Wilson, and he goes through the implementation process and, much like you just said, Jen, he outlines kind of his desired flow of code just in comments that sit within a test and kind of figures out just the general flow of things and like, how he wants to approach it before even throwing down actual code of something.
And also what I’ve found too, is as people get more and more comfortable with TDD they start taking off bigger and bigger chunks so you’re not asserting always the simplest possible thing, like, every single time.
To the point where it’s kind of ridiculous. It’s like, the exercises like doing the bowling game up front to get the pattern down, is excellent. But in time, you realize, “No, I don’t need to assert zero is equal to zero.“
Necessarily. Like, I mean if that’s what you need and that’s what makes you productive… But you have to find your level of granularity to work through things; or even if the solution is really well suited to TDD. I mean, occasionally, for me, it’s just like, figuring out an API or something like that and I’m like, “What do I even want this thing to look like?” Prior to necessarily implementing anything about it’s ‘cause it’s just knowing like, the actual DSL that I’m working with.
Yeah, so that’s interesting. It seems like, you know, a TDD is really, really is you’re still doing that prototyping and that exploration that I was talking about, but you’re doing it in the context of a test suite, not you know, your actual codebase.
And I say I do them both at the same time. I actually am writing the codebase at the same time. As I’m writing increasingly more complex tests, I’m writing increasingly more complex code. So I do them hand-in-hand, they go together. It’s just that the part I’m writing for my test is like, just barely half a step ahead of what my code is doing.
The second point that I wanted to make about TDD is that I don’t think it’s always necessarily. I think that it benefits me the most when it gets beyond something really basic. So once I actually have to start thinking about laying something out, that’s when I start writing tests. And that may or may not be what everyone does. I definitely see the value in TDD, but if it’s something that’s really simple, I already know how to implement it, it’s three lines, I don’t need a full test to make sure that I create this code in a way that’s testable and clean and concise and all the other benefits of TDD. So I don’t always use it. And yeah.
So that may be “Jen’s Unpopular Opinion of the Day” but, as soon as I have to sit down and actually architect something tests really help me kind of find those cases that I didn’t think about before and may not have until I ran into them later. So it kind of helps me architect things better from the beginning. That’s when I use TDD.
No, that’s makes total sense. All right, I’m going to stop this tangent now because we’re getting close to the mark and it looks like we’ll be able to have a super extensive discussion on tests. And the-
In future episodes, so stay tuned for that, listeners.
That was just a preview.
(laughs) It was just a tribute.
(laughs) Oh, throwback to React Rally.
So, on 276, they talk about the wrong abstraction and specifically, the quote from Sandi Metz is one that I’ve heard many a time and I am a fan, where it says that, “Duplication is far cheaper than the wrong abstraction. Prefer duplication over the wrong abstraction.” And I am definitely on board with that.
In one concrete example of that, that pertains to daily work for me, is in React I use Redux; and Redux, you do a lot of the same thing over and over. And I have been tempted at times, I’ve had coworkers tempted at times, to go and wrap up some of the things that we were doing there in some kind of patterns, but then it always winded up being this thing that doesn’t necessarily fit all cases.
And so by actually having used Redux in the raw with what we’re doing, or I guess Redux with the React adapter so that kind of minimal layer, it’s made it where there is a decent amount of boilerplate code but it’s very linear. Like, you just always do that same pattern every time even though, like your use case may be a little bit different, because of the level of abstraction that it happens to be at it allows it to be reused in lots of cases and not having to shim it in to some abstraction on top of it. That has been a thing that I have noticed or, brought about my current day.
I also like the part that says, “The term ‘separation of concerns’ honestly doesn’t mean anything anymore, but it used to.”
Yeah. ‘Cause saying that it means, “I’m doing the right thing.” Or, “I’m trying to do the right thing.”
Whatever that thing happens to be.
Yeah, I feel like a lot of these terms can be something that just gets repeated in a conversation and you just say it and it makes you feel better about your code because you think you’re doing it the right way, but it doesn’t help explain why it’s better to anybody else.
There’s another sentence that says, “And this is where we come up against the weight of history and a little trick that every politician knows: if you say something long enough, it becomes true. I think it’s the same with the phrase ‘separation of concerns’, it’s reminiscent of the phrase, ‘I could care less.’ or ‘Hone in on.’ These phrases make no sense at all but for some reason popular American-English vernacular has twisted them to mean something, and as time goes on, they get adopted.”
So it’s just one of those, you know, phrases get, you know, not just adopted but converted into something that means something. And separation of concerns seems to mean that you’re focusing your attention upon some aspect and your, you know, that aspect’s point of view means that the others are currently irrelevant concerning what you’re thinking about. So you could be looking at making it clean, or making sure that you’re doing a specific vertical slice or it could mean a specific horizontal slice and however way that you're looking at it at that time is separating the concern that you’re considering from everything else.
And that kind of was the original meaning and now we’ve taken it to be that we’re trying to isolate one aspect of it away from everything else. So we want to make sure that either it’s the MVC model or it’s the component model or something to that effect. We’re trying to find the best way to slice it to make it good.
Yeah, I think the difficult thing in communicating separation of concerns, and some of the engineering discussions I’ve had, is that everybody has different perspective on what the concern is.
So it’s hard to kind of align and get that to match up.
Yeah I think it’s related to another pattern that’s not in the book, but it’s just called “Do one thing, and do it well”, I guess. Where each program should only do one thing and do it well.
Yeah. I learned that lesson the hard way a long time ago. But that’s a tangent so…
And it also comes with its own challenge. Like, what one thing does Facebook do well? I mean, one thing?
Oh, I was going to go in a completely different direction with that! (laughs) I was going to say give your data to people who shouldn’t have it.
Yeah. Yeah, we read that book! (laughs)
Yeah and not every program follows the ‘Do One Thing Pattern’. A lot of programs try to do everything or many things. I was just working with a program the other day, a command line program that will… It was some command line program that worked with images and it only took in certain formats, and the reason was that ImageMagick is already a command line program that is really good at converting to different formats and so, you know, they weren’t going to take all the time to do that when you could just use ImageMagick and then take that format and put it into this other program and it’s kind of the Unix philosophy.
I almost stepped into the Unix philosophy stuff, but there is a whole chapter on it so, I will-
Yeah! That’s another preview.
For until then. That may, that might come at the same time testing.
Oh hey that’s gonna be a-
That’s gonna be a good episode. Y’all better stay listening!
That’s some good stuff coming up.
Especially since we’re like, really close to that, that’s gonna be fun.
I think one of the things that stands out to me with all of these principles as well, including separation of concerns, is a lot of being mindful about the code that you’re writing with the, having an eye to being able to maintain it, and that obviously depends on what you’re writing, who you’re writing it for, like if it’s something that only you are going to read versus having a team that you’re working with.
For example, things like the Law of Demeter, or principle of least knowledge, where something like digging at the internals of something you’re consuming might not be good and if you’re say, dotting three levels deep, then that might not be good. But it also might be entirely fine. But they are things that you can consider.
Like, when I’m reviewing code, like that’s sometimes a question that I’ll ask on something. It’s like, “Okay, you’re really digging into this thing, are you sure that it’s going to be all right? You feel good on it? Carry on.”
Yeah, you said something there. You said it’s a flag, and that reminds me of, it’s a thing called “code smells”, I think that’s from clean code.
And one of the code smells is inappropriate intimacy, which is exactly this.
I also like the quote from Martin Fowler that says, “I'd prefer it to be called the Occasionally Useful Suggestion of Demeter.”
Instead of the law? Yeah.
So one of the things I wanted to maybe finish off this section with, since it talks a little bit about software design and actually writing code that you ship to people who use on a regular basis, is, since I’ve started working full-time, one of the biggest distinctions between, you know, like, working and open source and doing college work and working outside of projects and all that stuff, is when you work full-time you have to keep all of these design principles in mind and all of these like, engineering techniques as you’re like, dealing with deadlines and meetings and all of the stuff.
So one of the things that I’ve just struggled with is like, keeping all of these best practices in mind when you’re at work which can get like, a little crazy sometimes. And, you know, it’s a book, it’s written, it makes it look like it’s really easy to always be thinking about these things or always implementing them, but they’re definitely habits that you have to develop and, like anything, you have to put it into practice.
So one of the things that I’ve been going out of my way to do is I kind of will pick one habit that I want to get good at. I’ll say like, “For the next two weeks I’m just going to get really good at writing in a test for all of my pull requests.” Or, “For the next two weeks I’m going to get really good at making sure that I don’t implement this certain bad design pattern in my code.” And I’ll just do it and keep that in mind and slowly build the kind of muscle memory that I need to start keeping all of these design principles in mind in the future as I’m coding.
So if all of this is like, very overwhelming to you and it’s super scary or like, I definitely feel like an imposter right now, it’s fine. Just pick a technique that you want to improve on or something you want to get better at and focus on it and start to have it be part of your muscle memory.
Not only that but, again, like “Apprenticeship Patterns”, going back to the first book that we read, this book is meant to help give you the language to start these conversations. So though some of these things may be best practices, though people may talk about them a lot, some of them are more useful than others; and the point here is to be able to give you that knowledge and vocabulary enough to be able to know what to look up in the first place. So, I don’t think that all of this needs to be committed to memory. I think that it’s just a good reference.
Yeah, I found it helpful as I was learning things, just knowing something exists, I’ll just put that in my back pocket, sometimes, and just know that it exists and not have to dig in too deeply. And just knowing that it exists in the future can help me out, and like you said, Jen, help you look it up when you need it.