Member-only story
The Case Against Relying Solely on DRY
Repeat yourself when it makes sense to do so
One of the most common principles, and one regularly mentioned on pull request reviews, is Don’t Repeat Yourself. The initial reasoning behind adhering to the DRY principle is a sensible one.
However, over time, like a lot of things in software engineering, its meaning and reasoning for existing has been lost, in my opinion. Instead of being applied when needed, it’s thrown around when any sniff of duplication is spotted, and I believe this leads to worse code in the long run.
In this article, I’ll talk through why I believe duplication is not the root of all evil, and why it’s perfectly fine to repeat yourself sometimes.
What Does The Dry Principle Aim To Solve?
In 1999, Andy Hunt and Dave Thomas released the book The Pragmatic Programmer. It’s become incredibly popular since then, with a number of teachings from the book becoming regular practice for a large number of software engineers.
One of the practices was Don’t Repeat Yourself, often referred to as DRY. Here’s the definition of DRY, from The Pragmatic Programmer:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
That makes total sense to me. To put it another way, it means that your business logic shouldn’t be repeated in two places.
A quick example of DRY in action
Let’s say you’re working on an eCommerce system, and an order is valid for 7 days. The logic for whether an order is expired or not should be defined once and only once. For example, in an Order class:
class Order
def initialize(order_id:, order_timestamp:, items:)
@order_id = order_id
@order_timestamp = order_timestamp
@items = items
end
def expired?
Time.zone.now > order_timestamp + 7.days
end
end
As you can see, the logic for whether an order is expired lives within the Order class. Assuming this is the only place where that logic is defined, the code within that repository is considered DRY.