Duplicated code is bad. It's a code smell, it makes you look like an amateur, and worst of all, it makes the next developer who has to maintain your code want to drag you out into the parking lot and slap you around for a while.
Learning to recognize DRY violations is a core foundation to writing cleaner code, but I'll be the first to tell you that recognizing and squashing repetition violations is a discipline. It requires you to slow down, really think over your code, look for patterns and refactor them.
Here's the thing though: making your entire code-base purely DRY is pretty difficult, and runs the risk of reducing the readability and the flow of the application from a maintenance perspective (excessive abstraction is a code smell as well, known as contrived complexity, and a fun fact is that it almost annoys me more than DRY violations because the people who create that code smell are more likely to be arrogant/inept where DRY violating people are more like children running with scissors). So in my mind the goal of DRY is not to purge every possible ounce of duplication out of your system, but the closer you get to the business logic the more DRY your code should become.
To put this in perspective, let's consider an enterprise solution with the following layers (from outside in):
- Presentation- Various UI clients, executables, etc.
- Service- Feeds presentation layer
- Business/Interactors/Rules- Actually does the work
- Persistance- Stores and retrieves data
Presentation layer? Sure, you might have some duplicate service calls on various forms. This in the grand scheme of things is not all that big of a deal, because your presentation layer should not be performing business logic. Thus, even if you duplicate some calls and structures, those calls shouldn't need to change for a behavior update. It's nice to make this layer reasonably DRY, but there's a line to be crossed where it seems like developers start cramming unrelated methods together into the large class or "god object", which is another code smell. You need to weigh the risk of change and readability and make an educated decision. However, even our designer brethren understand DRY, what do you think CSS does? Reduces duplication, provides a single source of truth!
A well designed service layer just takes requests and returns responses. Again, due to minimal business logic, duplication here really should be avoided, but it probably won't kill you if some similarities pop in, particularly in cases where similar services are exposing to different clients. I definitely take a harder look at this layer than the presentation layer.
Business layer is where we really lock things down. For any business rule, logical sequence, calculation, etc there must be a single source of truth. One of the main reasons the architecture forefathers created multiple layers was to purge duplication of these very important facts within software systems. Until you experience the nightmare of having to update a calculation that is spread throughout multiple layers and duplicated everywhere you can't really appreciate this. It's a game of coding whack-a-mole that you are almost guaranteed to lose by introducing bugs into production.
Cool story bro, I once had to work on a system where an important fact was in a middle tier, in stored procedures, also hidden in expressions in reports, and additionally was even duplicated in JQuery on the presentation layer, what was literally a 2 line change took about a week by the time all the duplication spots were located and shaken out. The hellish thing about duplication like that in distributed systems is that you can't do any cross platform searches easily to find all the buggers. As to be expected with such shoddy code structure there weren't any tests to run either.
In the persistence layer, particularly in the realm of relational databases any database architect worth their salt will take care of DRY for you. The whole concept primary keys and unique constraints is to make your data DRY. Duplicated code is bad enough, but let me assure you that unintentionally duplicated data is a nightmare in its own right!
In the end, DRY is a key to making your code reusable and more maintainable. Having mentored a lot of developers over my career, I've also found that the pursuit of the DRY principle actually is what leads many new developers to discover architecture patterns in more progressive and natural way than handing them a gang of four book and telling them to go away.
Sometime soon we'll talk about the Single Responsibility Principle (SRP). Mixing SRP violations with DRY violations is a great way to punish future maintainers if you're a sadist, but that's a topic for another day!