5 ms·
I dislike code duplication. But do you know what I like even less? Giant functions with 12 keyword arguments passed up and down a call stack, because those fun
by ekidd 3y ago
I dislike code duplication. But do you know what I like even less?
Giant functions with 12 keyword arguments passed up and down a call stack, because those functions have many callers which want slightly different things.
Choosing the wrong abstraction often leads to endless kludges and special cases. Two warning signs are functions with 12+ keyword arguments, and strange class hierarchies full of callbacks that only interact with a few functions.
The problem with all programming advice is that it needs to come with George Orwell's classic advice to "Break any of these rules sooner than say anything outright barbarous."
If programming advice makes your code look obviously gross, ignore the advice.
- gpderetta 3y agoWorse, for those 12 parameters (invariably booleans or if you are lucky enums) functions is that usually only a small subset of all possible flag combination is tested (or even meaningful). Worst part is when the flags are directly or indirectly under user (or configuration) control and the application can go into uncharted territory. Worse still, good luck refactoring those functions when you have no idea which combinations are actually meant to be supported and what their original semantics where.
- CharlieDigital 3y agoThat's not what abstraction is. Abstraction tends to shift logic from procedural to structural. Rather than 12 keyword arguments and 12 branches in 1 big function, it should be 12 small classes (in OOP) or 12 small functions (in FP) that each handle one of the branches. All organized in some way that thelogic of executing those parts is shared in the structure of the code.
- ekidd 3y ago> Rather than 12 keyword arguments and 12 branches in 1 big function, it should be 12 small classes (in OOP) or 12 small functions (in FP) that each handle one of the branches. I mean, sure, you could convert your library into 12 little classes, or a collection of purely-functional combinators. Sometimes that helps. Sometimes it makes the situation even worse. Some of the most terrifyingly inappropriate abstractions I've seen in my career involved complex class hierarchies, or worse, things like "abstract interpretation over the free monad." There's no substitute for asking, "Are these things I'm trying to abstract over actually similar in any fundamental way?" And "Is this code actually just horrible?"
- CharlieDigital 3y ago> "Are these things I'm trying to abstract over actually similar in any fundamental way?" I'm not sure why this is even a point; if there's no similarity of the things that are being abstracted, why would one even discuss abstraction in the first place? The point of abstraction is that there is some fundamental similarity that the abstraction addresses. `ICloudStorage` abstracts `GoogleCloudStorage` and `AwsS3Storage` because at some level, they both have the same abstract operations: read, write, delete, etc.
- dllthomas 3y ago> if there's no similarity The point is that there may be superficial similarity. Code that happens to look the same, but represents different "pieces of knowledge" that are likely to change independently probably shouldn't be unified.
- overgard 3y agoAh, but the solution is to turn that 12 argument function into a class that does one thing (runs the function), and dependency inject all those arguments. It still totally sucks, but you can pretend you're writing "clean" code by obfuscating the parameter passing.