Sometimes it's quite interesting to take a development guideline and see how far you can apply it, and what other recommendations emerge from it or are subsumed by it.

I first tried this while doing a code review many years ago. There was a gratuitous asymmetry in naming between two operations: Attach and Close, IIRC.

I then did most of the rest of the review based on the question of symmetry (although I didn't share that with my colleagues πŸ™ƒ), looking to improve the symmetry of the code or understanding what the underlying cause of an asymmetry was.

It was surprising how effective and insightful this fulcrum was.

This carried over into some of the subsequent code I wrote. In general it was to favour symmetry, but that was not an assumption.

I approached it as "What would symmetry mean here? What would asymmetry mean here?"

Finding necessary asymmetries also clarified a number of design issues and simplified a lot of interfaces and implementations.

Another guideline I have been testing the boundaries of is DRY. This is not a universal or absolute principle, as some developers think, nor is it simply about duplicated code.

Consider it as an enquiry into the role and necessity or superfluity of repeated information, with a strong skew towards reduction of duplication β€” whether that is duplication of intent, information, etc.

When you lever your view of code through the fulcrum/razor of DRY then reduction of comments, extraction of methods, replacement of enum/switchs with lookups or polymorphism or callbacks, etc. falls out as a natural consequence.

Likewise, avoiding prefixes like get, test, check, etc.

And also the use of type deduction, i.e., instead of

ClassName a = new ClassName();

prefer

var a = new ClassName();

DRY can be quite a productive line of enquiry.

@kevlin I find myself wanting to be a bird on your shoulder through one of these code evolutions, because what becomes clear in working with the shape of source code may be obscure in either the text of the beginning state or the end state.

@kevlin Having a language for refactorings and patterns and the motivations for moving code one direction or another is helpful for making intent clear.

Intent can be hard to infer from the code itself.

@jmeowmeow πŸ‘
@kevlin I am reading Your Code as a Crime Scene, which takes a forensic metrics approach to source code health and evolution, so "when code changes, is it better?" is at the top of my mind.
@kevlin One you suggested which, once I finally did it I found very liberating, is not calling exception classes ThisParticularException

@kevlin I distinctly remember arguing with the Lead of my team (at a Fortune 50 company!), who asserted that use of `var` should be preferred, in all cases (instead of naming the type), whenever instancing an object, in our c# codebase.

I asserted then, and maintain, that specifying the type can be considered a type of "self documentation" in the code, and when using heavy polymorphism and inheritance (as we did, as a rule) it is often (if not nearly always) preferable to specify the type, whenever possible, if you are legitimately restricting yourself (and the current operations) to that type.

At the time, I was overruled. Not a single one of the other 7 developers on the team put forth an opinion, so the Lead overruled me.

@rancor @kevlin I think Kevlin is saying that from a DRY lens

var x = new ClassName()

*is* usually better than

ClassName x = new ClassName()

Or even

ClassName className = new ClassName().

But if you have

var x = DoSomethingComplex()

Then

ClassName x = DoSomethingComplex()

Isn't repetitive and adds new information.

@edyoung @kevlin right. I don't think I said anything contradicting that...
@edyoung @kevlin you can take what I said about extensive polymorphism and inheritance to imply "DoSomethingComplex()"; That was my intended meaning.

@kevlin hello!

Wanted to add the benefit of DRY in dynamic programming where ideal is executing transactions only once to avoid side effects like excessive memory footprint or erranious flow in passing data among classes, use of state functors (callbacks) comes in handy.
Debugging with logging enabled for each transaction is also helpful to see the flow of execution.

Another thing is comments, found using doc strings is much better to explain the code components to the readers

@aziz DRY, in terms of time and space, can be considered an optimisation tool. On the other hand, adding duplication can also be considered an optimisation tool in other cases.
@aziz I'm not sure what you're saying about doc strings and comments: doc strings _are_ comments πŸ™ƒ
@kevlin I generally wait to copy paste 3 to 5 times the same partial code before trying to refactor it. It generally won’t pay off until that level of reusability.
@fvilers @kevlin I agree, but I find myself having the urge to DRY code at the 3rd instance or so of a pattern repeating. Perhaps I benefit from waiting, but I don't think I have the patience to wait for the 5th instance. 😒
@fvilers Yes, the rule of 3 is the conventional advice on code duplication and refactoring. DRY, however, is not just about code duplication, and thought experiments and "just how far can I take this idea?" explorations are not about following conventional advice πŸ™ƒ

@kevlin Indeed not. Dry is a very useful principle but far from a universal absolute. Just keeping both test and production code around is a deviation from DRY, when to a large extent one can be generated from the other (or vice versa).

We do it because expressing the same thing two ways helps us understand and communicate better and makes it harder to make most.

@kevlin and even here its good to think about possible ways to reduce WETness. E.g. tests that are auto generated on demand from a previous version of the code to prevent BC breaks or other unintended changes.
@kevlin sometimes the simplest code to write has a bit of repetition. Particularly when there are just 2 items in a collection.
@Techychap "... necessity or superfluity of repeated information..."

@kevlin in my case it was the reverse i.e. removal of complex code and replacing it with something simple but repeated.

The simpler code should be easier to change if we need to and is easier to understand if we don't.