Latest / DevQuestions with Tim Corey / 140 Is It Possible To Overuse DRY? Is Repeating Yourself Ever OK?
Transcript
- 0:00SPEAKER_00: Welcome to the Dev Questions Podcast with Tim Corey.
- 0:03SPEAKER_00: Join us each episode as we tackle the questions you are asking about a career in software development, understanding the industry, and new technology.
- 0:12SPEAKER_00: If you're just starting out or you want to grow stronger as a developer, this is the place to get your questions answered.
- 0:19SPEAKER_00: Now, here's your host, expert developer and online educator, Tim Corey.
- 0:25SPEAKER_02: Is it possible to overuse dry?
- 0:29SPEAKER_02: And by dry, I mean don't repeat yourself.
- 0:31SPEAKER_02: This is a principle of software development that seems like it's the foundation of everything we do.
- 0:38SPEAKER_02: We decide to keep our code dry because that makes for better code.
- 0:44SPEAKER_02: But can we ever overuse dry?
- 0:47SPEAKER_02: Is repeating yourself ever okay?
- 0:50SPEAKER_02: This question I want to address in today's episode of DevQuestions.
- 0:54SPEAKER_02: Now, if you have a question, you can go to suggestions.imtimcorey.com, ask your question there, or upvote an existing question.
- 1:01SPEAKER_02: Hopefully, you'll see your question answered in a future episode of DevQuestions.
- 1:06SPEAKER_02: Now, let's talk about dry.
- 1:08SPEAKER_02: Now, again, dryer stands for don't repeat yourself.
- 1:11SPEAKER_02: We'll just use dry from now on.
- 1:13SPEAKER_02: But dry is not an absolute.
- 1:17SPEAKER_02: It is not a requirement.
- 1:19SPEAKER_02: It is not something that you should always do.
- 1:23SPEAKER_02: It is a principle.
- 1:25SPEAKER_02: This is something that people often get stuck on when they first learn about software principles and software design, even design principles or design patterns, they start to think of these as rules.
- 1:37SPEAKER_02: There's, I don't want to say there's no rules of software development, but they're pretty flexible.
- 1:42SPEAKER_02: There's, you need to do what is best for the situation you're in, which means sometimes you repeat yourself.
- 1:50SPEAKER_02: So let's talk about why you might repeat yourself.
- 1:55SPEAKER_02: And let's talk about why not repeating yourself could cause problems.
- 2:00SPEAKER_02: So reduced repetition can lead to increased complexity.
- 2:04SPEAKER_02: This is the first issue.
- 2:06SPEAKER_02: So let's talk about a simple example.
- 2:09SPEAKER_02: In C, we have what's called a console read line.
- 2:12SPEAKER_02: We can use that to capture information from the console.
- 2:15SPEAKER_02: And usually we, especially in demos, we'll do things like, hey, print out or console.write, what is your first name?
- 2:23SPEAKER_02: And then do a console read line into a variable.
- 2:26SPEAKER_02: And then you might say, well, I need your last name too.
- 2:29SPEAKER_02: So I print out what is your last name, and then I capture that into a variable.
- 2:34SPEAKER_02: And you might say, oh, wait, wait, that's repetition.
- 2:37SPEAKER_02: Let's go ahead and create a method that prints out a message and then captures a value back into a variable.
- 2:44SPEAKER_02: And so you do that.
- 2:46SPEAKER_02: And now you have one method call, which has the message, and it has the variable it goes into the return value.
- 2:54SPEAKER_02: And life is good.
- 2:55SPEAKER_02: Well, except for the fact that now you have to think about well, we sometimes capture integers or doubles or other values that are not of type string.
- 3:06SPEAKER_02: And so you want to make sure we cast for that.
- 3:09SPEAKER_02: And so now we'll have overloaded methods that will say, oh, if you want a string, you do this, or if you want an integer, you do this.
- 3:17SPEAKER_02: If you want a double, you do that.
- 3:18SPEAKER_02: And you call these different overload methods.
- 3:21SPEAKER_02: That way it's it's simple to call.
- 3:22SPEAKER_02: It's one line still, maybe throw some generics in there.
- 3:26SPEAKER_02: And all of a sudden you have this whole complex library that's just for really calling two lines of code.
- 3:33SPEAKER_02: And you have to keep adding complexity to it because you have more scenarios that are a little bit different, but they're close.
- 3:42SPEAKER_02: And if you take a step back and you look at your application, you've got multiple different methods and maybe even different classes, and maybe even a class library, all to handle this one situation.
- 3:57SPEAKER_02: And that's a lot of complexity that maybe you didn't need, because maybe you just need to repeat those two lines three times.
- 4:05SPEAKER_02: So that's where your reduced repetition actually adds complexity.
- 4:11SPEAKER_02: And you had to think about the balance there.
- 4:14SPEAKER_02: This is why you have to understand your application.
- 4:18SPEAKER_02: Because sometimes that makes total sense.
- 4:20SPEAKER_02: Because you're going to do it a hundred times, you're going to do it in different places, and having one place to do it one way right makes a lot of sense.
- 4:29SPEAKER_02: But maybe you're creating a simple application that just asks for a couple pieces of information to process, and that's it.
- 4:36SPEAKER_02: Well, knowing your application, you know the second one doesn't need the complexity.
- 4:42SPEAKER_02: It just needs those two lines of code duplicated three times.
- 4:45SPEAKER_02: That's it.
- 4:46SPEAKER_02: So understanding where you're at.
- 4:49SPEAKER_02: Whenever you start to say, this is the absolute, I always or I never, you're pretty much wrong.
- 4:57SPEAKER_02: This is why senior software developers will answer any question with it depends.
- 5:04SPEAKER_02: Because the right answer for your application is not the same answer as for my application.
- 5:11SPEAKER_02: Because the situation is different.
- 5:14SPEAKER_02: It depends on your team.
- 5:15SPEAKER_02: It depends on your code base.
- 5:17SPEAKER_02: It depends on what other code you have.
- 5:20SPEAKER_02: It depends on the size of your application.
- 5:22SPEAKER_02: It depends on the type of your application.
- 5:24SPEAKER_02: It depends on your environment.
- 5:26SPEAKER_02: It depends on the speed in which you need to get things done.
- 5:28SPEAKER_02: It depends on your update schedule.
- 5:30SPEAKER_02: It depends on the number of things it depends on is pretty large.
- 5:35SPEAKER_02: So when we say it depends, it's based upon all that stuff.
- 5:40SPEAKER_02: It's not just as simple as here is the right answer.
- 5:44SPEAKER_02: Which is why when you say always do dry, you're wrong.
- 5:48SPEAKER_02: Okay?
- 5:48SPEAKER_02: So that's the first one is increased complexity.
- 5:52SPEAKER_02: So the second one, reduced repetition, can lead to increased fragility.
- 5:58SPEAKER_02: An example of this came out a little while ago when the maker of the library or the package, really, it was really a tiny little thing called LeftPad decided that they were going to pull that off of NPM.
- 6:16SPEAKER_02: So if you're not familiar, LeftPad is a little JavaScript library.
- 6:19SPEAKER_02: All it does is it allows you to very easily pad the left hand side of a string with either spaces or zeros.
- 6:26SPEAKER_02: Simple.
- 6:27SPEAKER_02: It's probably 10 or 15 lines of code max, but it's something that a lot of different applications need.
- 6:35SPEAKER_02: And instead of recreating or not being dry, recreating that code in their code, they said, hey, left pad's already done it.
- 6:45SPEAKER_02: They've done it once.
- 6:46SPEAKER_02: Let's not repeat ourselves.
- 6:48SPEAKER_02: Let's just point to LeftPad.
- 6:50SPEAKER_02: The problem was that the owner of LeftPad was rather frustrated with how they were treated over a different situation.
- 6:56SPEAKER_02: And so they said, fine, I'm going to take all of my code off of NPM because you treated me poorly.
- 7:04SPEAKER_02: And when they did that, they destroyed thousands of applications.
- 7:10SPEAKER_02: Because thousands of applications needed that dependency, left pad, that, but it wasn't there.
- 7:17SPEAKER_02: And so since that dependency wasn't there, they could not build new versions, which means bugs couldn't be fixed, uh, security vulnerabilities couldn't be patched, because they couldn't build their code anymore, because they all depended on one library.
- 7:32SPEAKER_02: It was the ultimate case of dry.
- 7:35SPEAKER_02: Let's, as an industry, not repeat ourselves.
- 7:38SPEAKER_02: We're going to use this library in order to handle this one little situation.
- 7:45SPEAKER_02: And that way, if there's ever a bug in LeftPad, we can fix it once and fix it for the entire industry.
- 7:54SPEAKER_02: But when you take away LeftPad, you also take down the entire industry.
- 8:00SPEAKER_02: So it created a fragility that was bad enough that even though the person who owned LeftPad said, I don't want it on NPM, NPM said, we kind of don't have a choice, we have to put it back anyway, against your wishes.
- 8:16SPEAKER_02: Even though you own it, it doesn't matter.
- 8:17SPEAKER_02: Now the community does.
- 8:19SPEAKER_02: So it was a bad situation, and there's some murkiness that got cleared up and some things got fixed.
- 8:26SPEAKER_02: However, the point is that when you create that ultimate dry, you create some fragility.
- 8:35SPEAKER_02: Now, maybe you won't do that.
- 8:37SPEAKER_02: Maybe you say our organization does not allow any external packages.
- 8:40SPEAKER_02: That's probably short-sighted and incorrect way to think about it, but I get it.
- 8:45SPEAKER_02: I've seen a lot of organizations do that.
- 8:47SPEAKER_02: And you say, okay, well, we don't have that problem then.
- 8:50SPEAKER_02: Yeah, you do.
- 8:52SPEAKER_02: I've seen organizations that create central packages for their applications.
- 8:57SPEAKER_02: They built them themselves.
- 8:58SPEAKER_02: It's their DLL, it's their package, it's their library.
- 9:02SPEAKER_02: But when they create a bug or when they break that DLL, it doesn't just break one application, it breaks them all.
- 9:12SPEAKER_02: So instead of downtime one area, you have downtime everywhere.
- 9:16SPEAKER_02: So when it comes to dry, you have to balance the repetition with the fragility that it can create.
- 9:27SPEAKER_02: There's ways to mitigate the fragility.
- 9:29SPEAKER_02: There's ways to make sure that a change over here does not directly affect something over here.
- 9:35SPEAKER_02: But you have to think that through because sometimes the right answer is to repeat yourself.
- 9:42SPEAKER_02: Those companies that rely on LeftPad, they probably should have just created their own version of it.
- 9:49SPEAKER_02: Because even though they had to support that then, it was the better decision.
- 9:53SPEAKER_02: It's one less dependency to depend on.
- 9:55SPEAKER_02: It's one less thing that can go wrong.
- 9:58SPEAKER_02: So reduced repetition can also lead to reduced functionality.
- 10:05SPEAKER_02: So the example here is one that I get a lot in C sharp.
- 10:10SPEAKER_02: And that is when I create a data model versus a UI model.
- 10:15SPEAKER_02: And the models look the same, where they have, let's just create a simple example.
- 10:19SPEAKER_02: Yeah, first name, last name, and email address as three properties as a data model.
- 10:24SPEAKER_02: You can have in the UI model first name, last name, and email address.
- 10:28SPEAKER_02: Why wouldn't you combine those?
- 10:30SPEAKER_02: Why wouldn't they be the same thing?
- 10:32SPEAKER_02: Well, because in my UI model, I want to put some data validation.
- 10:36SPEAKER_02: I don't necessarily want that in my data access or data model.
- 10:41SPEAKER_02: Well, you say, you know what, Tim, you can just put the validation in the data model, no big deal.
- 10:45SPEAKER_02: It's not going to use it for your data access, so put it there.
- 10:48SPEAKER_02: Well, now, in order for the data access, which is in the class library, to use that model, that model also has to be in the class library.
- 10:57SPEAKER_02: So I put that class model in the class library, and now I have to do UI work in the class library.
- 11:06SPEAKER_02: That's kind of a problem.
- 11:07SPEAKER_02: And even worse, let's just say I'm working on a WPF project and I create some validation and some messaging for my desktop UI.
- 11:16SPEAKER_02: Well, then when my API decides to use that same data access and the same data model, but it wants to create different messaging?
- 11:28SPEAKER_02: It can't.
- 11:29SPEAKER_02: Because now you've got a problem of, yeah, but that messaging is for the WPF UI, not for the API.
- 11:38SPEAKER_02: Or, you know, it's not for the Blazor UI.
- 11:41SPEAKER_02: And so now you've got a problem of you've got reduced functionality.
- 11:45SPEAKER_02: You have to actually reduce what you do in that model because it doesn't serve both UIs appropriately.
- 11:52SPEAKER_02: And now you're thinking about, well, I can create some kind of inheritance structure, or you know, you're creating complexity again.
- 11:58SPEAKER_02: And what you could just do is repeat yourself.
- 12:01SPEAKER_02: It's okay, you can do it because they're two different things serving two different purposes.
- 12:07SPEAKER_02: So reduced repetition can lead to reduced functionality.
- 12:14SPEAKER_02: Now, reduced repetition can also lead to reduced speed.
- 12:19SPEAKER_02: Here's a practical real-world example of this.
- 12:22SPEAKER_02: Um, I live in a house with six people, including myself.
- 12:25SPEAKER_02: So we have myself and my wife, my two sons, and then we have my in-laws live with us.
- 12:32SPEAKER_02: So as six of us, that means when my wife goes and picks up groceries, it's a full car.
- 12:37SPEAKER_02: We've got a ton of groceries we bring home because it's, you know, it's feeding six people.
- 12:41SPEAKER_02: There's a lot of groceries that come home.
- 12:43SPEAKER_02: So if my wife and I have different approaches to taking in the groceries, the way that I do it is I grab what I can and I take them in.
- 12:52SPEAKER_02: My wife is the master of putting every single grocery bag up her arm, both arms, and walking in with the entire grocery store, it feels like, on her arms and gets them in quickly.
- 13:03SPEAKER_02: Okay.
- 13:04SPEAKER_02: And now she's, you know, it's not over the top, but there's two different approaches there.
- 13:09SPEAKER_02: There's the approach of just grab what you can and make multiple trips, or I'm gonna make one trip.
- 13:16SPEAKER_02: And this is where that reduced repetition can lead to reduced speed.
- 13:21SPEAKER_02: Because you think, well, if I walk back and forth from the car to the kitchen once, that's reduced repetition.
- 13:28SPEAKER_02: So if I can get all the groceries in at once, then I actually make it faster, right?
- 13:34SPEAKER_02: And I reduce repetition.
- 13:36SPEAKER_02: I keep myself dry.
- 13:37SPEAKER_02: But it takes a long time to figure out how to fit every bag and every box and everything under your arms, on your arms, on your back, and all the rest.
- 13:49SPEAKER_02: And you kind of, you know, have to hobble into the house because you're so burdened.
- 13:54SPEAKER_02: And it might have been faster to take three trips.
- 13:58SPEAKER_02: So that's kind of what we do with code sometimes.
- 14:01SPEAKER_02: We overburden it with doing all these checks.
- 14:04SPEAKER_02: We say, you know what?
- 14:06SPEAKER_02: The best place to store data is a database.
- 14:09SPEAKER_02: And so every setting is going to be the database.
- 14:12SPEAKER_02: Well, that reduces repetition because you can always point to that from whatever place you're at, except for the fact that now you have data access, which isn't free.
- 14:23SPEAKER_02: It takes time.
- 14:24SPEAKER_02: And then you say, well, we want to make sure you process all of this in one spot.
- 14:29SPEAKER_02: And so we have this whole system to process it, make sure we pick out which one we want and all the rest.
- 14:34SPEAKER_02: And you have this whole long thing that takes half a second to work because you're doing all the work for any different scenario that might come about.
- 14:42SPEAKER_02: Instead of just saying, you know what, we're gonna store this in a JSON file on the disk right next to the application.
- 14:49SPEAKER_02: I do this right now on our website.
- 14:51SPEAKER_02: The imtimcore.com website actually runs off of a JSON file, which is on the site with it.
- 14:57SPEAKER_02: That JSON file goes into source control.
- 15:00SPEAKER_02: There is no database, there is no data access call, there is no need for a caching layer.
- 15:05SPEAKER_02: I don't have to add all these layers of complexity because it's right there.
- 15:09SPEAKER_02: It's the fastest it can possibly be because I repeated myself.
- 15:14SPEAKER_02: Okay, so that's the way that repetition, reducing repetition, can actually lead to reduced speed.
- 15:23SPEAKER_02: Now, I've talked down a lot about repetition.
- 15:26SPEAKER_02: I've talked down about down a lot about reducing repetition, but dry is very important.
- 15:32SPEAKER_02: In fact, it's one of the most important ways that we can make our application better.
- 15:38SPEAKER_02: I'm not saying that reducing repetition is bad.
- 15:42SPEAKER_02: But what I'm saying is to make an absolute is bad.
- 15:47SPEAKER_02: So treat dry as a recommendation and adjust when you need to use it based upon your specific circumstances.
- 15:58SPEAKER_02: Don't just say that dry is a law.
- 16:02SPEAKER_02: If you make dry a law, you will make bad applications.
- 16:06SPEAKER_02: Instead, treat it as a principle.
- 16:09SPEAKER_02: Treat it as something to aspire to, to think about, to plan for if you can, but do so in a wise way.
- 16:18SPEAKER_02: Always think of the big picture, always think of your specific circumstances, and make the choice that's right for your circumstances, for your application that sets you up for the best success.
- 16:30SPEAKER_02: All right.
- 16:31SPEAKER_02: So that's my answer to should we always use dry?
- 16:34SPEAKER_02: The answer, no.
- 16:35SPEAKER_02: It's up to your specific circumstances when you use dry.
- 16:39SPEAKER_02: Do it a lot, focus on it, make sure you try and keep your application as dry as possible, but don't treat it as a rule.
- 16:47SPEAKER_02: All right.
- 16:47SPEAKER_02: Thanks for listening.
- 16:49SPEAKER_02: As always, I am Tim Corey.
- 16:51SPEAKER_01: Thank you for joining us for this episode of Dev Questions.
- 16:54SPEAKER_01: Tim is committed to making it easier for you to become a developer.
- 16:57SPEAKER_01: If you would like to help make more content like this possible, please like, subscribe, rate, and share Dev Questions.
- 17:05SPEAKER_01: You can also send your questions to questions at IamTimcorey.com.
- 17:10SPEAKER_01: Until next time, remember, you are too smart and your time too valuable to waste it making all the mistakes Tim did.
- 17:17SPEAKER_01: When you're ready to learn to think and code like a professional developer, head over to imtimcore.com and enroll in a course.