Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I feel like what you’re describing is bad abstraction. This is the real issue, people designing things off two or three examples, not making sure that what they have is general enough to accommodate future usage.


In particular, a good approach to this is to abstract the common parts to all those into just some very simple functions. Abstract bottom to top, not top to bottom. There is no need to create a single point where everything happens and deals with the 2^n combinations.

You still reduce repetition, you can still change stuff in a single point, but you retain the ability to make custom changes if needed.


> Abstract bottom to top, not top to bottom.

Amen. With the caveat that this is a guideline, not a rule.


Yes, the problem in the real world is that no one KNOWS they're writing a bad abstraction at the time they're writing it, otherwise they wouldn't write it.

Therefore it's insufficient to say things like "avoid bad abstractions" or "make sure you accommodate future usage". No one can predict the future, generally speaking.

Abstraction should be used with extreme caution, even when you feel that it's probably right. Be an extreme skeptic.


I completely agree. The issue with the "clean" version of the code is that it's completely coupled together. If you touch one thing in the math code, it affects everything. At some point, it becomes easier to keep some duplicated code, point out the similarity using some code structure cues or comments, and over time, highlight any key differences using more comments.

A "clean code" approach to this kind of code doesn't handle evolving requirements well. It always ends up as a mess of helper functions with multiple code paths within depending on where the function is called from. This can sometimes be abstracted: some people might have noticed already the previous sentence is describing OOP polymorphism. But how would anyone know the exact requirements ahead of time? If we're in such an early phase, any attempt to "clean code" will only result in a bad abstraction, or in overengineering. The right approach is to do nothing, note the possible issue, and wait until more is known about the problem domain.


We could call it The Premature Abstraction Anti-pattern :)

Been a victim of this myself a few times myself so I normally do exactly what you've suggested and wait until a clear, and still performant abstraction has emerged from the code and slowly refactor-in the abstraction. But it's always better to do this on a nearly completed codebase, so at the end, where you should naturally be looking to remove lines, not add.


This is why I've grown to like discovering patterns based on changes - new features and bugs being fixed.

I wouldn't worry too much about somewhat duplicated, but easily understood code, like the original example.

I would however worry if I have to fix the same issue in 3 places, or add code for a new feature in 3 places. That's when I start wondering if I can push the code I need to change or add into a common place somehow.


This is completely right. People read about design patterns or DRY, usually apply them wrong since they're still learning... and then act like it's the source materials fault?


Well, it kinda is? Teaching materials should show how to not refactor too.

Also have u seen refactors in clean code?

Guy refactors thread safe code by introducing static variables which make code not thread safe, but hey! At least it is a little bit shorter!


Yup this is the worst part of Clean Code. I've seen real-life bugs caused by this kind of refactoring.

The best part is that the same commit added unit tests so our coverage grew over the magic 80% bar, but of course unit tests don't usually test for race conditions.


The problem is that the source material (the Clean Code book in this case) has almost no caveats. And it rarely acknowledge other styles or points of views. For example, when the book discusses possible objections to having "lots of small functions", it simply doubles-down, suggesting also having tons of small classes, and rationalizes it. Experienced developers know that reality is a bit more nuanced than that.

This is actually a big reason for the popularity of the book, showing a "one true way".

And this carried on to followers of the style. Some linters even enforce the style without much regard for the practicality of it.


If there is a source material that many people are "applying wrong", then I'd question the quality of that source material.


Design patterns, for example, really should only be studied once you have quite a bit of experience with complex code bases under your belt. You need to have done battle with some nasty code problems in bigger code bases before you really understand the problems design patterns are trying to solve. Inexperienced developers can't be trusted to apply them because they don't have that judgement. It just looks like a shiny thing.


True for so much of compsci stuff. You won't understand regular languages, automata, grammars etc until you have done a fair bit of pattern grokking yourself.


Imagine if math books told you that you should ALWAYS solve for X and if somebody tells you to solve for Y they are a bad mathematician :)

That's Clean Code.


I don't see how that's a fair characterization of a book that has this quote in the first chapter:

> Many of the recommendations in this book are controversial. You will probably not agree with all of them. You might violently disagree with some of them. That’s fine. We can’t claim final authority. On the other hand, the recommendations in this book are things that we have thought long and hard about. We have learned them through decades of experience and repeated trial and error. So whether you agree or disagree, it would be a shame if you did not see, and respect, our point of view.

It's been a while since I've read Clean Code, but I seem to recall it stated many times that blindly applying the rules of Clean Code without good justification would lead to bad code. The author even provides examples of this. People in this thread are criticising Clean Code principles as if they are meant to be a rigidly enforced dogma. They aren't, and the author never intended them to be so.


I think that quote is a good example of why it is a fair characterization. It uses the authors’ seniority to argue from authority, even explicitly requesting respect.

To a beginner, it reads like ”these are subjective matters so experience is king, and we have more experience than you do”.


"Respecting my experience" does not translate to me as "do everything exactly accordingly to these strict rules". To me it says "consider my opinions before doing something different". Consider. Not follow blindly. I can see how one may interpret it as the first if they read the quote in isolation, but certainly not in the context of the book. Which, as mentioned before, goes out of its way to state these rules are more like guidelines, and gives examples of where strict adherence causes worse code.


Well, based on this disclaimer, this is a book that never should be recommended to somebody learning how to program.

And yet, that's clearly their target audience.


Is it? The book requires being quite familiar with programming already. Perhaps this is me projecting my own experience of when I read it, but I feel like the book is targeted at someone in the late-phase of being a Junior Dev, and/or the early-phase of being an Intermediate Dev.

I personally derived a lot of value from reading the book, and I feel like my skills noticably improved from before to after. So perhaps my own biases are showing, but I believe discounting the book's contents wholesale is a mistake. There is a lot of value to be garnered from reading it. The book doesn't have to be the infallible word of the Software Gods for it to be useful.


A junior dev is somebody learning to program.

That disclaimer filters out anybody that isn't at least on the transition to be a senior dev (with real seniority, not just in inflated title). It takes quite a lot of experience to agree or disagree with a rule, and respect a point of view without automatically applying it.

In fact, since the rules on the book have way deeper impact than they look like, being able to read that book and not getting damaged by it is a good test for seniority.

But, funny thing, if you are mature enough to fit the disclaimer, you've necessarily already seen all that the book talks about and don't need reading it.


Not bad advice when you remember that advice is only ever for people who know absolutely nothing and need encouragement to start. "Only solve for X" gives some constraint so that one can start to focus on what really matters and not be bombarded with so many choices as to derail the entire effort.

With practice, one soon comes to understand why you might also want to solve for Y. Those with experience are going to ignore what everyone else says anyway, so it doesn't matter if it is not true for them.

Indeed, we in this industry are bad at practicing, and that's a problem. Imagine being Taylor Swift and having your guitarist for the night's performance having picked up a guitar for the first time yesterday. That would never fly, yet that's often how we treat software development – and that's how we get to these kinds of places.


There is no need to accommodate for future usage. Most of the issues resulting from abstractions actually come from people treating abstractions as sacred, trying to adapt abstractions used by some piece of code to fit new use cases, when they should be treating abstractions as disposable instead, swapping them out and creating new ones instead of altering existing ones. If the abstraction that you come up with based on the first few examples is not suitable for new use cases, that's completely fine.

As far as generality is concerned, it's not the number of examples that matters. Once you learn to distinguish whether your duplicated code actually duplicates some piece of knowledge or just happens to resemble another piece of code by happenstance, you stop having to rely on an unreliable magic number as your limit on how many instances of duplication to allow before abstracting something. And that skill probably correlates strongly with the understanding that abstractions are not just macros that make it more convenient to repeat some chunk of code, they actually represent knowledge, and thus their primary use is not to eliminate duplication, but to encode an understanding of a problem domain into the code.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: