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 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.
@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.
@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
@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 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.