4 ms·
I half agree with this. The problem is: what's the alternative? The reason we have abstraction is because not abstracting also has a cost. Consider encountering
by darawk 8y ago
I half agree with this. The problem is: what's the alternative? The reason we have abstraction is because not abstracting also has a cost. Consider encountering a legacy codebase with no abstractions. Yes, perhaps each unit of code is more digestible, but there's so many more units. The codebase is 10x as large, because there's no abstraction. Is it really easier to comprehend that way?
As in everything else, it boils down to an issue of balance.
- throwaway415415 8y agoUsually abstraction adds LOC
- darawk 8y agoIf abstraction adds LOC on net to your project, you're doing it wrong.
- svat 8y agoIn the very example in the OP, the abstraction adds lines of code: function calls, function signatures, possibly return statements. I think many programmers associate abstraction with having less code (which is almost always good, under reasonable circumstances of course), and this translations into a love of abstraction even in cases where it doesn't simplify things or lead to less code.
- speedplane 8y agoAbstractions should reduce complexity, which often correlates to LOC, but is not necessarily so.
- darawk 8y agoYa, but that's because the abstraction in the OP isn't complete. It's showing the abstraction of a single instance of a subproblem, for clarity. But real abstraction generally abstracts multiple instances of a subproblem (or at least, it should), and thereby reduces LOC.
- hliyan 8y agoI think refactoring large blocks of code into functions named after their purposes is good abstraction. But introducing whole new constructs (Proxy, Adapter, Bridge, Factory, Repository) should only be done when it makes the code simpler than the function-only alternative.
- musiciangames 8y agoI once inherited a project implemented in Spring. It meant that while we wanted to interview for bright people who would be able to understand the business domain, we actually had to interview for people who knew Spring, and might be able to pick up the domain knowledge. Otherwise the overhead of bringing people up to speed on Spring was too much.
- fdw 8y agoSome time ago, I would have agreed with you about Adapters, Factories and so on. But now, I'm not so sure. My team inherited a code base that wasn't really legacy - maybe two years old - with a very simple business logic: Collect data from one REST service, save it in a "cache" database and answer to requests from another one. Seems completely simple, and the code wasn't awful, either. However, there was no abstraction, no layers, nothing: The REST controllers knew exactly what the DB looked like and contained a large part of the collection logic. There was a client for the collection, but it was very low level and exposed everything. Additional domain logic was smeared over five to ten levels of hierarchy. In the end, each apparantely simple feature we had to add took days instead of hours because we had to touch so much code. The principle of locality was completely absent. In the end, we rewrote large parts of it so that you don't have to change the REST controller anymore if the DB schema changes. My personal lesson was that you should always have some abstraction, even if the service's task is so simple. Things will change, and you must be prepared for that. If every part of your code knows all the other parts, you're doing it wrong. Have clear interfaces and boundaries (and models) so that changes can be localized. Of course, that doesn't mean that you should implement something like: https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris... .
- structural 8y agoI have an overriding design principle that helps find where that balance should be: "Attempt, within reason, to minimize the number of places a reader must look in order to understand the code on his or her screen. Minimizing the number of changes required to alter functionality is a secondary but lesser goal. Minimizing the number of characters the programmer must type to implement functionality is explicitly a non-goal." For large C++ codebases at work, this leads to coding standards like: - Don't introduce typedefs referencing other typedefs in public API, especially when the typedefs and the API that uses them are in different files. Having to look in more than half a dozen different files just to understand the signature of a function is actively reader-hostile. We have a ton of conventions similar to this that help to make the code significantly more pleasant to read. It turns out that we still have quite a few useful abstractions, but they tend to be fairly large compared to most codebases I've worked with previously.