4 ms·
My take on it is that all software developers novice or otherwise try to write simple, clear code. For some(especially novices) that means plodding, low abstra
by stonemetal12 5y ago
My take on it is that all software developers novice or otherwise try to write simple, clear code.
For some(especially novices) that means plodding, low abstraction code, so that all the details are visible. This makes for longer code. Others see high abstraction code as the cleaner simpler code because the abstractions hide what they see as irrelevant details, which makes for terse code.
“the less, the better”
“the more, the better”
Tautologically both are incorrect when pursued farther than is prudent, and "the right amount, the better". Unfortunately no one really agrees on what "the right amount" is or we wouldn't have to discus different definitions and strategies to reach "the right amount".
- Osiris 5y agoAnd of course it depends on context. The interworking of a game engine may require some really obtuse code because it's focusing on performance and not on readability (in those cases, comments should be used to explain the code). In my experience the problem with juniors is more about thinking about the problem in a very linear fashion and not stepping back to see it as individual parts. For example, I need to know when a user takes an action. So, I go into the code where that happens and throw in a bunch of analytics vs having a messaging system where events are raised and the code that handles those events are completely separate workers that are simple and easy to understand.
- aYsY4dDQ2NrcNzA 5y ago“We must always think of the Way of strategy as being both a rat's head and an ox's neck. Whenever we have become preoccupied with small detail, we must suddenly change into a large spirit, interchanging large with small. This is one of the essences of strategy. It is necessary that the warrior think in this spirit in everyday life.” — Miyamoto Musashi, The Book of Five Rings
- cardanome 5y ago> For example, I need to know when a user takes an action. So, I go into the code where that happens and throw in a bunch of analytics vs having a messaging system where events are raised and the code that handles those events are completely separate workers that are simple and easy to understand. It is interesting that you think that code with more abstractions is easier to understand. From my experience the simple linear beginner code is the one that is quite easy to work with. It is easy to grasp the general intention and to slowly refactor parts of the code if need be. Now a mid level developer that thinks of themselves to be smart and tries their hardest to use some fancy abstractions and patterns? Yeah, put it in the trash. We will have to rewrite that code. The best code is from the senior that finds the right balance. Finding the right abstractions to use takes years of experience. The most important rule when programming is: Don't try to be smart. Keep it simple.
- stouset 5y agoCode with more abstractions is generally easier to understand, which is precisely why most of us prefer to work in modern languages over assembly. And why we use SQL instead of working directly with low-level storage engines. And why most people prefer languages like Ruby and Python to FORTRAN and BASIC. It’s why we build software on top of an operating system and kernel, and now why we do so with the further abstraction of containers. It’s why we use an HTTP library for clients and servers instead of just writing and parsing requests directly on the wire. And it’s why io_uring is a stark improvement over select. The problem is bad abstractions. Bad abstractions don’t cut the underlying problem across clean axes, they leak too many implementation details, and they aren’t often able to be reused. “Linear beginner code” that handles too many concerns in one place is inarguably bad, but bad abstractions are generally worse. We shouldn’t be trying to stop using abstractions: virtually all of the history of progress in computing has been driven by finding good abstractions that allow us to build bigger and better things with less mental overhead. We should be doing absolutely everything we can to understand and teach the practice of writing good abstractions.
- kerblang 5y agoIt's that concise, straightforward, efficient & flexible are often contradictory instead of complimentary: You're typically sacrificing others for the one. It often helps to be specific about which traits you are/aren't focused on when arguing for the "right" solution. Words like "easy" and "simple" are more ambiguous and lead to confusion.
- dmartinez 5y agoA mental analogy that I personally use for this is cabinets. A section of an app is kind of like a cabinet in a kitchen. Some people like opaque cabinet doors while others prefer glass. Other people go even further, and eschew cabinets for open shelves. These differences in object and system visibility sometimes reflect specific use cases (e.g., a professional kitchen can operate faster with open shelving than with opaque cabinet doors). Other times, they simply reflect the personal preferences of the designer.
- Hermel 5y agoIdeally, the code is structured such that one can navigate it at different levels of detail, with the lower level functionality encapsulated into separate units that can be ignored if one is not interested in the details.
- opportune 5y agoCompletely agree with you. The issue IMO is over-eager abstraction tends to simply make code more confusing. It may be more “elegant” but if it turns out the class/functions/whatever used to generalize code will never need to be used elsewhere (so they will only be changed in their current state), or have too many different behaviors based on configuration options, it actually makes things more confusing than just proliferating boilerplate - because instead of a big imperative chunk you can read and modify directly wherever it’s used, now you have to understand the class, maybe base classes, the function and which control paths it takes based on which args, etc. And that nuance means for example, maybe it makes sense to create a helper to append some additional error detail to a string if used only twice, but maybe if some similar behavior is used in 7 slightly different ways, it shouldn’t be generalized if it requires lots of conditionals and arg plumbing. This is why I kind of hate the mantra of “if it’s used 2-3 times or more, wrap it in a function or class.” IMO the bar for something being wrapped needs to be higher - either the amount of logic should be large and segmentable enough that it can be placed in something that separates concerns from where it otherwise would be, small and very repetitive, or it needs to be used much more often in a way that truly resembles a library (and thus requires an interface that does not expose implementation details or wrap messy conditional logic).
- stouset 5y ago> This is why I kind of hate the mantra of “if it’s used 2-3 times or more, wrap it in a function or class.” I think that’s a fine signal to use to identify that something needs to be refactored, but that doesn’t absolve an engineer of having to think about how to actually do so. It’s why I’ve always cringed at IDEs with “refactor selected code into its own function” actions. This is so rarely what you should ever be doing. Refactoring is like butchering. You need to figure out how the muscles lie and separate them on their natural boundaries, not just start hacking things into parts because they seem too big. Once you’ve separated pieces across good functional boundaries you can start trimming and breaking things up to fit specific needs, but it has to start with stepping back and getting a wider view.
- golergka 5y agoEveryone has their own definition of "simple". Some think that closures are too fancy and complicated while others don't understand what's so hard to grasp about a monoid in the category of endofunctors.