DEV Community

Cover image for Code duplication needs to be avoided at all costs. Keep code DRY.
Varun Palaniappan
Varun Palaniappan

Posted on

Code duplication needs to be avoided at all costs. Keep code DRY.

In this podcast episode, Krish introduces the concept of keeping code DRY (Don't Repeat Yourself) and its significance in maintaining clean and efficient codebases. Using a practical example related to the product's data structures, Krish illustrates how entities are organized hierarchically and emphasizes the importance of identifying similarities and shared functionality to avoid code duplication. Strategies for implementing and refactoring code, such as inheritance, composition, and design patterns, are discussed to promote code reusability and maintainability. Krish highlights the importance of timely refactoring and the challenges associated with maintaining code quality over time, particularly in dynamic languages. Ultimately, Krish encourages continual improvement of code bases to enhance readability, scalability, and developer productivity.

Summary

Explanation with Examples:

  • Explanation of the concept of keeping code DRY with a practical example related to the product's data structures.
  • Discussion of the hierarchy and relationships between different entities in the product.

Implementation and Refactoring Strategies:

  • Strategies for implementing and refactoring code to avoid duplication.
  • Discussion on identifying similarities and shared functionality between different entities.
  • Explanation of the importance of avoiding duplication and maintaining code cleanliness.
  • Consideration of options for refactoring, including inheritance, composition, and design patterns.

Importance of Timely Refactoring:

  • Emphasis on the importance of refactoring code sooner rather than later.
  • Discussion on the challenges of maintaining code quality and cleanliness over time.
  • Mention of the benefits of strongly typed languages in facilitating refactoring.

Podcast

Check out on Spotify.

Transcript

0:01

Hey everyone, this is Krish and welcome to Snowpal podcast. Hope you're doing well. In this podcast I want to talk about keeping code dry like as in do not repeat yourself.But before we go into the podcast, I want to ask you if you've checked out snowpal.com.

0:18

If you've not, you should.And if you like charts and data visualization.We've got plenty of those half my own favorites, but I love the Sankey charts. So the next time you're on the product, check out the Sankey charts.Without further ado, let's get into the podcast.

0:34

So in this podcast, like I said, I want to talk about keeping Code DRY.What does that mean?Let me take an example, right, a more practical one, which takes our product into consideration. So we have in our product, the business, in our business model and the data structures at the highest level, we have something called a key, which is like an entrance to managing whatever it is that you want to manage.

1:01

And then when you get into a key, you have blocks, you have pods at the same level and you have pods underneath blocks as well, right?So you have 3 to 4 levels of hierarchy.And then you could create tasks at each of these levels.Now that's just a high level example.Let's just remember that you have keys and blocks, pods, block pods, tasks, right.

1:21

So it's a bunch of different models now.They're all different and they are yet similar, right?And what I mean by that is they're different because they, they sit separately, they have dependencies on each other.They are sit in a hierarchy, but they also have similarities in the sense there are things underneath at the implementation level that we share between these items.

1:42

One of it is metadata, right?You know when was something created, when was something modified, who modified it, who created it, things of that nature.But there's other items that are data related, which are also shared between these entities and models.Now that's kind of the high level.

2:00

If I go any deeper, it wouldn't make that much sense in the context of this monologue.But the reason I bring up the example is when I start making some changes to a key, I make the changes to the key, right?I write it as though there are no blocks or pods or block pods or tasks, right?

2:17

Keep it simple, just write it like as though that's the only problem you're trying to solve.Now when you go to a block, I mean it's all right to be cognizant of what's coming, but I'm just, I want to keep the early part of this monologue simple enough. So I'm saying ignore that there are other models or entities and be selfish.

2:33

Implement keys as though they are only keys and keys and nothing else but keys.Right.Now you go to implementing blocks, you're going to identify, you're going to write some code and then realize, you know what, this looks a little bit similar to what I have for keys.And then you're going to write more code and then you're going to realize, Oh yeah, this looks a whole lot similar to what I have for keys already.

2:52

At that point, you have one of two options that should really. It's really one option, but at least on the surface, right?Superficially you could say that you have one of two options.One is you can ignore the fact that you have keys and you did something similar.And by you I mean you or your team member, one of your team members.

3:09

And again, if you're working in a larger team, you may not even know that someone did that, because keys is if you're a smaller shop, you know there is 5-6 developers or whatever, but if you have like 100 of them, how are you supposed to know?But even if you have 100 developers, each team is going to have like a smaller number.

3:25

So I think you'd still know.But in any case, right?You want to.You want to ask yourself a question, which is, hey, now that I'm writing this, is there anything similar that this product could possibly already have?If it does have, I do not want to reinvent the wheel, right?

3:41

I want to keep it DRY.If you did it, or if you're in a much smaller team, you know someone else did it because you code reviewed their changes. Then it becomes all the more easier, at least for you to know that there are similar changes. So you go look for those changes and now what you do is, I said one of two options.One is copying everything you have for keys and pasting it for blocks.

4:00

It works, but it's super ugly and it's going to be a maintenance nightmares.Got fifty other problems right?So obviously you don't want to do that. So that's why I said it's kind of an option, but not really an option.The second one, which is truly the only option, is to make sure that you have it in one place and you use it in a number of places.

4:17

And now again, depending on the stack you're in, and depending on the complexity of this particular problem, I just took a very simple use case here.You could have dependencies on gems, other NPM modules, plug insurance, whatever, right?It could be N number of things.But let's say in our case, let's keep it simple.

4:34

Let's say it's none of those external dependencies that you've pulled in. It's code that's literally sitting in your code base, but not even as a library, but literally in the realm of your own directory structures. In that case, you go look for that module, or the mixing, or the class, or whatever it is right in the stack you're working on.

4:52

You pick that, You refactor.You make sure that it's generic enough so it satisfies the problems of both key and the block.Now, how can you go about doing this right?There are many, many ways to skin this cat.Again, you want to look up design patterns, different methodologies, You know whether it's object oriented or otherwise.

5:12

However you want to do this, you want to do it through inheritance, through composition, through through one of many means, and it'll make sense in the context of that particular problem and the stack as well, right?Whether you want to have modules or mixins and mix them here, or you want to implement other interfaces anyway, even if you're implementing interfaces, every language does it differently. dot does it a send way, Java does it another way.

5:37

I'm not a C# person, but I'm sure it does it something.Maybe it does it slightly differently, maybe it's only syntactically different. Conceptually it's probably very close to Java. It's just a slightly better language, I think. Nicer. Anyways, that's a digression and call for digression.Sorry.

5:53

Back to what we were discussing, right?So depending on the stack you want to pick, how do you want to go about solving the problem?But Long story short, you want to keep it DRY.You don't want to see the same line of code twice, right?Generally my rule of thumb is if it's one line or two lines, sometimes I'm all right repeating it even though it bothers me.

6:12

But I might not go all out to rewrite those pieces, especially if it means I have to touch fifty other files. By the way, I I actually don't mind touching 50 files almost every single time.The the the strong, the more strongly typed the language is, the easier it is.

6:27

But if you're doing it in JavaScript or Ruby, it's a little more challenging because you know you have to rely on the editor catching a bunch of things which it does not, not all the time. At least you have to have your test suites, and if you don't have them, there's other ways you have to catch them.But if it's strongly typed, it's it's much easier, right?

6:44

You can find these issues, so refactoring becomes a whole lot more pleasurable and strongly typed languages.Now you want to go refactor it.Make sure it you never. My school of thought is never stop yourself from improving the code base around where you're at. It does not.

7:00

I mean, I understand it's tricky because you want to keep your focus.Don't shake the foundation.Understood.All of those points are good and well taken.But having said that, there's no reason to not continually, continually work on improving our code bases all the time, right?

7:16

Code that we write, we don't like it the next day, the day after. So you know you constantly want to improve because you know things change, right?It's like my five, my 6-7, whatever it is, things keep changing, libraries keep changing.I recently did an upgrade to was it like Ruby 2.7 dot something?

7:35

Maybe it was higher.I can't remember the exact version number, and there are some actual changes that ended up throwing a bunch of warnings.You could ignore those for a little while, but it bothers me to see any warnings in my console or my log, so I try to make sure it stays clean.

7:50

More like your e-mail inboxes, more you have.You don't know what you have to act upon, and if there are plenty of logs with warnings and debug and info messages, you don't know which ones are more important, which ones are important enough to be addressed, so I try to keep them as clean as possible. So this Ruby upgrade was actually something, you know, it did end up throwing a bunch of warnings, but unfortunately it's not within our code base necessarily, it's with our gem dependencies, so we couldn't do much about it.

8:16

Now again, I'm digressing back to what I was trying to say, keeping it DRY. So now you make the change because sometimes you're like you want to get this out the door. So can I had it added to do? Can I come back to it later?Trust me, adding A to do and coming back to it rarely ever works.

8:32

You're going to have a code base full of to Do's.I have plenty of to do's myself and I have priorities on those to Do's.I follow a certain format when I add add the to Do's in the code base so it stares you in the face and says that need this needs fixing.But the fact that it it became a comment like A to do comment tells me sort of implicitly that it could have it could have waited, which is why it waited, which means it can't probably wait a bit longer and then you end up sometimes waiting forever.

8:59

So you know, just just do it right away and you'll be in good shape. So back to keeping it dry, you know, even if you're pressed for time, try your best to to not create the duplication because what happens, it's slippery slope.You add duplication once and then you're going to, someone else is going to write more code, they're going to look at this and maybe they copy paste and then it's going to be a vicious circle where there's going to be a lot of copy paste and stuff.

9:22

And now when you get into that point and three months later you want to come back and refactor it, it's it's a much bigger nightmare.You have to touch a whole lot of stuff.And if you don't have a test suite, and if you're not wealthy enough as a company to offer these test suites, writing tests is expensive, right?They are great, they're useful, but they're pricing right.

9:41

It takes a lot of time.And if you're getting, if you're trying to get done with a lot of stuff, it's not possible to always write a lot of tests or sometimes any test.Code coverage becomes challenging, so the nicer thing is it's like a double edged sword if I may.

9:57

The more code coverage you have, the less you have to worry about code quality.Kind of, if you know what I mean.Because you rely on the code coverage, your test to actually catch your code problems.But when you don't have those tests, your mind thinks otherwise.You're like, you know what, I better do a much better job because otherwise there's nothing for me to fall back on, right?

10:17

You can't rely on manual intervention to catch these bugs.And as the product grows, grows, it's impossible because you have so many dependencies.Like we have a ton of code already.We have a number of clients like in terms of the user clients and we can't.

10:32

I mean we refactor, we want to be careful and you know it has a lot of dependencies, so it does get very challenging, right?So doing it earlier as quickly as possible is a whole lot easier and the smaller your team, smaller your company, and the more important more imperative it is that you do it as soon as you possibly can and don't delay.

10:56

Which essentially is an inevitable right?So now I talked about keeping a drive with blocks and now when you go to pods, now you have a design pattern, You have something for keys and blocks, you could use them for pods.Now a pod is a child of a key, a block is a child of a key.But a pod can also be child of a block by thereby becoming a grandchild of a key, right?

11:17

So there is a relationship there, but outside of the relationship, there are commonalities between these items and tasks is entirely in parallel because each of these can have one or north number of tasks.Now you identify the common items right?As you understand the design, the product, the business and the whole 9 yards, you sort of draw these mental patterns in your mind and you're like, you know what?

11:41

I need these pieces to sit separately, how they end up being sitting separately, whether they're services embedded in your product offering in a single monolithic app or whether they're micro services, better you know, more services the merrier.However you keep them separate and isolated, the better off you are, the more isolated it is, the better off you are.

12:01

But that's left to you, right?That's outside of keeping it dry.You could keep it dry in one of many ways, but, and the reason I say this, I felt the need to do a podcast because I did want to talk about this topic.But also every time I've seen even open source code bases, right?

12:18

Sometimes you see no redundancy, you you feel like a wide and again, open source people are volunteering that time. So you're absolutely grateful to folks for doing that.They're moderators.There's a whole process. So it's you know the larger the library, the more adopted it is is, the more contributors it gets more challenging and there are a number of open peers at any given point of time.

12:43

So all of this adds to the complexity.The devil is in the detail.But if you're again, if you take your team, even if your company is thousands of developers, you bring it down to divisions and teams and departments and whatnot, you end up in maybe 5101520 devs in a team, I would imagine.

13:01

So that's it's a big number, but it's not a terribly unmanageable number of people. So you want to establish the establish these patterns because the moment code starts appearing, that does not look right.That doesn't look clean.That sort of sets a bad precedence.And there's someone else could.

13:17

Someone else who joins A-Team might look at it, might be influenced by it, and might end up adopting it, which is kind of bad, right?Then it starts spiraling because you had something which is not a great example.Maybe you had A to do, but again, how many times do you carefully look for it to do when you're looking for design pattern that you want to adopt in other places in your code?

13:36

So it's it's easier said than done and you'd be like OK, what's?Why would someone need even state the fact that you should keep something DRY and not repeat yourself. It's because again, it's easier said than done.I can't tell you how many code bases I've had the luxury of being able to both contribute to and reviewing or helping out with, And I see that there's so much redundancy and it becomes legacy as well, right?

14:06

If it's there from people are generally all right to touching it based on the personalities, of course.I like to touch code that I, you know, all the time.Code that not is immediately in the purview of what I'm writing and interest of improving code bases, but I worked with other folks, so great engineers, but who just like to stick to their worlds because they don't want to shake or shake the foundation.

14:29

It's personal preferences, so to speak.But outside of that, even folks who want to make these improvements, they tend to do it.If the changes were made in the last week, two weeks, three weeks, a month, maybe two months, the moment they see that it's three months, six months or a year old, I feel like they don't want to be touching it right?

14:48

So it becomes the problem becomes more aggravated. So do your best, keep your code clean and enjoy your code base yourself and also make it more enjoyable for folks who will be contributing to your code bases.Hopefully some of it made sense.

15:04

Thanks for listening.

Top comments (0)