I read this article about DRY and this prompted me to write some thoughts about this. This was a very debated article about what is DRY and what it means to use it or not and then there was a lot of discussion about OOP and good code.
I will not go into debating that article, but I think there are a couple of things to consider when thinking about how to design our code.
I will mostly talk thinking about (Ruby and thus OOP), but I think some of the comments I will write below might apply in general to programming in a lot of languages.
First, we have some principles about what it means to write good code. Could be they are not principles but more guidelines or maybe a kind of philosophy about how to think about code.
Here is an example:
"Every piece of knowledge must have a single, unambiguous, authoritative representation within a system" - Dave Thomas and Andrew Hunt in The Pragmatic Programmer
This seems like a very good principle to follow. Actually, if you will go ahead and read this amazing book you will see this principle as being named the "DRY principle" like in the "Do not repeat yourself principle".
What is the problem with having a principle? The problem with it is that it is hard for someone new to apply it in concrete situations. Thus when people are learning to code it is hard without prior experience to understand this principle and so they stick with the shorter version of it: "Do not repeat yourself". This is easy to remember and being so prescriptive it is easy to follow.
I don't think there is a problem with starting to learn to code and follow this principle.
Based on my experience as a trainer, delivering a lot of technical training (programming, testing, architecture), when learning a hard skill there is a lot of information to process and some of it is very abstract and very hard to internalize and use every day.
Imagine that you did not encounter yet any bad code nor have you encountered the kind of maintenance issues generated by having duplicate logic or data models for example. It is will be hard to mentally process this principle and then while writing code to be able to distinguish between when to use DRY and when it is ok to let the code WET for a while.
A senior programmer will probably know this and should be able to decide when to break a principle and what to do to protect their change against introducing failures into the system because of that decision.
Where I think there is a gap is in between. What should happen on the road from being a novice to being a senior?
If you are lucky enough you will work in a team where there are already some senior programmers that have enough time to play the role of a mentor and help you do good code/solution/architecture design.
If you are not benefiting from such help, then breaking unknowingly these principles might create a lot of problems further down the road, most of them having an impact on how quick/easy your app will adapt to new requirements or will adapt to change.
What can be done is to go back to basics: from time to time revisit these materials about how to do code design. Re-read some of the books from your field, some of them might have revisited/updated editions. I do this from time to time and get new perspectives. Most of the time I look back at the code I wrote 1-2 years ago (and sometimes even a couple of months ago) and find out some bad design that I did.
Another thing that you can do is to ask for a code review and not only that but when receiving a suggestion, ask "Why?" not with the purpose to debate it but to understand what is the principle behind that suggestion or comment.
Try to find out timeless and mostly programming language agnostic advice.
Talk with the elders from your field, watch their videos, and read their books or articles. Even if they are published a while ago, having 30 years of experience coding brings a kind of wisdom that should be taken into account no matter the framework or programming language you are using today.
Coming back to the DRY acronym and the actual principle behind it, I think it is worth understanding from where they come and what are they trying to solve.
The answer is in two amazing books:
- The Pragmatic Programmer by Andrew Hunt Hunt and Dave Thomas
- Practical Objected Oriented Design by Sandi Metz
And it is mostly related to the following let's say axioms:
"Good Design Is Easier to Change Than Bad Design" - Dave Thomas and Andrew Hunt in The Pragmatic Programer
"The purpose of design is to allow you to do design later, and its primary goal is to reduce the cost of change." - Sandi Metz in Practical Object-Oriented Design
Thus if you think about it (or just read about this in these books) the purpose of code design is to write code today that will make it easy to change in the future.
In a way every other principle is derived from this or in a way tries to achieve this (not my idea, read about it in "The Pragmatic Programer"). So is SOLID or GRASP or CUPID or design patterns. They are all trying in various ways to provide a way for the developer to think about how to design their code to make it easy to change.
No matter if you agree or disagree with any of these principles, there is no easy way to achieve this at scale and make it easy to teach it. Programming is more close to a mix of art and engineering endeavor than it is a science when implementing apps that deal with the real world.
Photo source: publicdomainreview.org/collection/cycling-art