7 ms·
Every Line Of Business codebase I've worked on has been the worst "there I fixed it" copypasta spaghetti, and has never made it to the point where "maybe we sho
by Pxtl 6y ago
Every Line Of Business codebase I've worked on has been the worst "there I fixed it" copypasta spaghetti, and has never made it to the point where "maybe we shouldn't add a parameter to this existing, cleanly abstracted method to handle this new similar-but-distinct use-case" was anywhere near my radar for abstraction.
I would love to have developers where my problem was "maybe you piggybacked on existing code too much, in this case you should've split out your own function".
- mlthoughts2018 6y agoIt’s been the exact opposite for me. The spaghetti code has always come from poorly conceived abstractions and the massive problem of inverting an API to reimplement functionality through the API that should be extensible within the API (but fails to be because of poor choices in abstraction or abstracting prematurely). Later on that spaghetti code gets labeled as lacking abstraction, similar to what you are saying, despite the actual problem being too much abstraction and poorly designed abstraction that became load bearing in a way where everyone decides that living with API inversion as a reality is the lesser evil and figures they’ll probably quit the company and move on to greener pastures before it becomes their headache to deal with. https://en.m.wikipedia.org/wiki/Abstraction_inversion https://en.m.wikipedia.org/wiki/Abstraction_inversion
- hesdeadjim 6y agoAbsolutely this. I’d rather look at 200 lines of linear, inline documented code then a spaghetti mess of “helper” functions that do nothing better than obfuscate everything going on. I’ve had a strict rule with my team of “1, 2, N”. I don’t want to see an abstraction until we’ve solved a problem similarly at least two times, and even then an abstraction may still be a poor idea. Abstraction is an especially poor idea early in a project because often you only half know what you’re making (I’m in games). Requirements change, or a special case needs to be added, and all of a sudden you are trying to jam new behavior into “generic” helpers without breaking the house of cards built around them.
- hackinthebochs 6y ago200 lines of code means that you have to comprehend all 200 lines simultaneously since any line could potentially interact with any other line in that code block. Using functions where the state is passed as parameters limits the potential for code interactions through functional boundaries. The point of abstractions are to limit complexity by limiting potential interactions. Helper methods do a fine job of this.
- hesdeadjim 6y agoThat’s a gross over-generalization to assume that 200 lines is always a self-referential mess. Functions fundamentally transform data, and often that transformation is a linear process. If it’s not, sure, break it up in a more sensible manner. Regardless, helper methods have a significant cognitive cost as well. It’s nice to pretend that a four word function name can entirely communicate the state transformation it does, but in reality you need to know what it does and mentally substitute that when reading the function using it. No free lunch.
- hackinthebochs 6y ago>That’s a gross over-generalization to assume that 200 lines is always a self-referential mess. The point is that you don't know this until you look. You have to look at all 200 lines to understand the function of even one line. When you leverage functional boundaries you generally can ignore the complexity behind the abstraction.
- barrkel 6y agoYou're fooling yourself, in a mature codebase, if you think you can modify code and not look past function boundaries. That assertion would be more credible in a language that captures side effects in the type system, but that's not what most people use.
- hackinthebochs 6y ago
- nick-garfield 6y agowow, just reading that term "line of business" makes me anxious. I used to work on a global payments platform that supported "multiple LOBs", and it was a nightmare of ifs and switch statements all the way down. The situation was made more difficult by the fact that our org couldn't standardize the LOBs into a common enum.
- mrfredward 6y agoThe business codebase I'm working on now was written by OOP crazy people who thought inheritance was the solution to every line of duplicated code. When they hit roadblocks, they filled the base class with things like if(this.GetType() == typeof(DerivedClass1)){... I would do anything to have the duplication instead.
- raverbashing 6y agoVery relatable. And they even have the guts to call this code "SOLID"
- BurningFrog 6y agoOnce you ask what the class is you're no longer even "OOP crazy". You've just capitulated to the complexity and do whatever it takes. I don't want to sound (too) condescending. I know how easy the best intentions can lead a project there. This job is hard.
- fauigerzigerk 6y agoIf you're truly OOP crazy you will always find ways to avoid resorting to branching on types or even avoid branching altogether (just on the language level of course). "There's a design pattern for that" :-)
- pierrebai 6y agoChecking for the type is the exact opposite of OO. The correct OO would be to think about what the check represent, maybe abstract it in a base interface with pure abstract methods and derive from that interface. What you describe is what people without understanding of OO do when they come from a language without OO.
- goatlover 6y ago> they filled the base class with things like if(this.GetType() == typeof(DerivedClass1)){ That defeats the purpose of polymorphism.
- isbvhodnvemrwvn 6y agoThen the very same people learn that inheritance bad, composition good, and they'll create abstractions with no meaning on their own, which call 10 vague other abstractions (but hey, no inheritance!). Figuring out what happens there is even worse than with inheritance. Some people grow out of it, fortunately (mostly after having to deal with shit like that once or twice).
- grey-area 6y agoIn contrast, every junior developer I've ever worked with has wanted to abstract too early and often, and been slow to recognise that abstraction has costs too (often far higher over time than is initially obvious). There are costs to copying code, and costs to abstraction, and there's a balance somewhere in between where the most resilient and flexible code lives. The costs of both are paid later, which makes it very hard to judge when starting out where that balance lies, and hard to assign blame later on when problems manifest. Was it too little abstraction, or too much, or the wrong abstraction? Note that the article claims that duplication is cheaper than the wrong abstraction. The problem is not abstraction in itself, but that abstraction is very hard to get right and is better done after code has been written and used.
- Pxtl 6y agoWhat I run into with juniors is that yes, they want to abstract the new problem, and that's good... But they show disinterest in learning the existing abstractions and the existing problems and how their new code would fit into that. Given that approach, you end up with a million individual "frameworks", each only solving a single specific case of a series of overlapping similar problems. Because reading code is harder than writing it. And the only thing worse than "there, I fixed it code" is "there, I fixed it with this massive cool new framework I've built".
- grey-area 6y agoyes, they want to abstract the new problem, and that's good... I'm not sure that is good. I started off this way too, but now I like to think carefully about abstractions and avoid introducing them till I'm sure it will not hinder understanding, hide changes/bugs, bury the actual behaviour several layers deep, or worst of all make things hard that should be easy later (the problem in the article). Building abstractions is world-building; it's adding to the complicated structure other developers (including your future self) have to navigate and keep in their head before they can understand the code. So perhaps because of your second point (that people rarely like other people's abstractions), it's better to keep abstractions simple and limited.
- misja111 6y agoEvery failed IT project that I have worked on in the last 20 years (except those where the cause was non-technical such as bad planning/ bad requirements), failed because it used too many layers of abstraction.
- IncRnd 6y agoTnere is truth in this! I've also seen that some of the most successful projects with the highest performers are the most full of duplicate code. The operating theory is to be first to market in order to capture the largest market share and be the market leader. Programs are just tools that can be rewritten later. That's similar to any large tech company today that "innovates" then apologizes later.
- collyw 6y agoIf a company has been running long enough to be making money, chances are their codebase will be crap.
- pkolaczk 6y agoCounter: Every failed IT project that I have worked on in the last 20 years had too much code. Code is bad. Delete code mercilessly. Seriously though, the problem are bad abstractions, not just abstractions. A total lack of abstractions is typically a spaghetti you need to read fully to understand.
- BigJono 6y agoWhen I read these threads I feel like I must be working on another planet to the people commenting in them. In almost every front-end project I join, there's a positive correlation between number of abstractions and code size. Everything is so "best practice one size fits all"-y that you can usually start with halving the size of the code base by removing 50% of the dependencies. Even once you've done that, you can usually speed up development by cutting 50% of the remaining dependencies. All the ones where the API surface area is more complex than the bloody implementation. Code is bad, sure, but at least it speaks for itself. A lot of the time the choice is between 3 lines of code that are well written and self explanatory, or 1 line of code that is incomprehensible without trawling through 800 lines of documentation first. I agree that code size is probably the most important metric for measuring complexity, but it's not an absolute thing. If you're too merciless with culling code, you can easily code yourself into a shitstorm of required context that makes hiring and onboarding impossible. Having said that, I think the problem is mostly contained to using other people's abstractions. I can't think of many times I've walked onto a project and gotten lost in the mud because someone there had coded up something that was too convoluted. Only one springs to mind and it was a back-end system. And that probably gives some clue as to why nobody can agree on this stuff. I'm guessing different ecosystems lie on different points on the scale, and so different approaches are going to be more successful. I've seen probably 20 projects grind to a halt because of overabstraction, and none because of code duplication. But I'm sure there's other programmers involved in other communities and industries that have seen the opposite. So if we're talking to a faceless crowd on a forum, we're going to give vastly different advice, under the assumption that the people we're talking to are somewhere around the average of everyone we've ever worked with.
- sagichmal 6y agoI have had exactly and overwhelmingly the opposite experience. I wonder if it's a function of our fields, or what...
- captainmuon 6y agoSo much this. I've encountered many codebases (in science and in tech) where the coder did not even use basic abstractions. In one case there was a lot of plot('graph1') plot('graph2') .... plot('graph100') because somebody didn't know how to create strings at runtime in C++. Another codebase did complex vector calculations in components, I was able to reduce a 500 lines function to 50 lines (including comments, and with bugs fixed). I can sympathize with this a bit, I started programming with BASIC - you could not return structs, you could not use indirect variables (no pointers/references)... but at least you had the FOR loop :-P People get often called out for over abstracting (rightly so), but I've rarely seen somebody critisized for copypasta or for overly stupid code. Probably because we're too accidentially afraid to imply somebody can't code.
- platz 6y ago> I've rarely seen somebody critisized for copypasta or for overly stupid code. Do you think that is in the realm of what the article is concerned with?
- klyrs 6y agoplot('graph1') plot('graph2') .... plot('graph100') I've done a lot of that myself. What you might not be seeing is the for loop in a scripting language that was used to generate that text. It probably took less effort than looking up and implementing it the "right" way. It might make your eyes bleed but if you need to change "plot" to another function, that's just a find-and-replace-all away. Most importantly, the code works fine and doesn't actually need abstraction.
- humbledrone 6y ago> the code works fine and doesn't actually need abstraction Well, maybe it works fine. We didn't see the other 97 lines to verify that they actually include all the integers from 3-99 without skipping or duplicating any. (NB with a loop this verification would be trivial.)
- 6y ago
- dynamite-ready 6y agoNothing I hate more than seeing two files or more, sharing 90% of the same code. No matter what justification one attempts to use, there's a mistake somewhere in the design / development process. I can see a case for what the OP is saying, but I feel it should always be seen as a temporary measure.