I was chatting with someone in my Virtual Coffee community today, and they were talking about acronyms, because we love to create acronyms in tech....
For further actions, you may consider blocking this person and/or reporting abuse
I agree and have been pretending I'm in support of DRY all the time, I don't always think it's good to put all your eggs in one basket abstraction. When do you stop, is this overdone? Just more problems sometimes
ECSS covers an interesting anti dry concept because it's more decoupled and easier to remove
Whatβs ECSS?
It's a little known and a little old theory of how to work with CSS
It's also a book and a style guide.
ecss.benfrain.com/
Even if you don't use it, it's worth a read particularly the bits about DRY and the strength of duplication
For a mediocre developer, it takes discipline to be dry and it takes iron balls to justify the dry (=longer) way to bosses.
For talented autistic hackers loving their craft, it takes discipline to not be dry when necessary and it takes iron balls to justify the βwetβ way to themselves.
Dry can be different, as well as context for it. Thatβs why itβs definitely not something thatβs cut in stone. But in general, itβs a nice practice. The smaller the team/project, the nicer it is.
Blaming folks is never really a good idea, but it sounds like it could possibly be a good teaching moment and/or improving communication with the team.
What can I say, I explained business analysts that development environment is not QA/UAT so many times that I forgot the count.
They always say sorry and that it's just in case we didn't noticed ππ€·π»ββοΈ
DRY, like most of the guiding principles, is best though of as a guideline rather than a rule. There are always tradeoffs, good architecture practice is mostly a matter of understanding the tradeoffs and making deliberate informed decisions.
Sometimes it is better to duplicate a block of code if it cuts across multiple bounded contexts or presents difficult ownership & synchronization questions.
Database normalization somewhat parallels the DRY concept and helps illustrate the point. The early forms of normalization greatly improve the structure of the data but the highest levels of normalization will start to incurr additional database server overhead and application complexity. There is a middle ground that works best for any application but the exact balance is always a bit fuzzy, imprecise and moving.
The real value of the principles is to provide a language framework for discussing the work so we can make cooperative decisions acknowledging the tradeoffs we make for any given decision.
My thought process to decide to go with DRY is simple - Does applying DRY makes my code more manageable or more speghetti?
If applying DRY is making your code complex and less manageable, it is not worth itπ€·
The issue is that there always is more nuance than the slogan suggests.
Point: Don't Repeat Yourself
"every piece of knowledge must have a single, unambiguous, authoritative representation within a system."
Just because there are two similar representations doesn't necessarily mean they refer to the same piece of knowledge. It's likely but in some cases the resemblance simply reflects the current incomplete understanding of the problem and its solution.
Counterpoint: Beware the Share (see also Fate-sharing).
Implementations sharing a common dependency are inherently coupled. If the implementations have slightly different requirements the common dependency absorbs complexity to accommodate that variation in order to be more "generic". When the requirements of one of the implementations change, the commonality has to adapt-often taking on complexity that doesn't benefit the other implementations, sometimes leading to a breaking change for the other implementations. So at times maintaining multiple distinct but much simpler dependencies can make maintenance simpler (Used Three Times).
Look at Bounded Context ("Beware the share. Check your context."):
Customer
to get work done inside the Sales contextCustomer
to get work done inside the Support contextCustomer
necessary for the the Support context and Sales context to communicate/collaborate.Superficially there is repetition across the three
Customers
but they serve very different roles and more importantly neither context should let implementation details about the their internal handling of aCustomer
leak out.The ones I work with in the current project are good people, It's a bi-directional professional relationship, it must be. As tech lead/ lead dev, I try to explain them the concepts, the big picture about the architecture, the nuances of some features, what needs to be done to reach a given feature and so on.
They try to get better deadlines with that information and they try to understand whether something that is wrong in develop is due to a current development or if it's a flaw "Yes yes we know, it's develop, we don't want to bother you guys". π
My guideline is once, sometimes twice but never three times.
Single Responsibility principal is king and applies to functional programing too.
I was thinking about having maybe a
getUserById
and then agetUserByEmail
, if you gonna DRY you can join both together in agetUserBySomething
so you avoid repeating most of the query, but then you will have a conditional inside your function that makes the function more complex and it also breaks the Single Responsibility principle and it's worse IMHO.Single Responsibility does not mean all functions must only do one thing.
For example if we need new behavior, we simply write a new method whose name indicates that single responsibility. It then allows for parameters to change behaviors. It can contain calls to many other functions but strictly only does what the name implies.
I call this a decorator pattern because it adds functionality by use of optional parameters. Allows parts to be added at will, but never departs from what the name implies. It only does that one thing.
The decorated function prefers use of reusable SRP functions because that code is already done and bullet proof. They are closed for modification.
The Concept is so simple but often confuses pepple.
Doing more than one thing in a function composed of SRP Functions is only more fragile if tests prove it.
Its a balance act (like most of the time). The drawback in getting DRY is that the code will have reduced flexibility. If parts of the application need to be refactored, that is much more work in a DRY application because you either need to extend the parts and need to be super careful not to affect other parts of the program. Or you need to break up again and create near-copies of some structures.
On the other hand, being DRY reduces the surface for bugs. More code = more surface for bugs, simple as that.
I think its a good rule of thumb to not trying to get into too DRY code too fast. Stay flexible until the overall architecture of some modules got settled and with refactoring and the use of unit tests it will be easier to DRY the code part by part.