7 ms·
It's important to remember that all best practices are not created equal. I'd prioritize readability over DRY. I'd prioritize cohesion over extensibility. When
by hardwaregeek 2y ago
It's important to remember that all best practices are not created equal. I'd prioritize readability over DRY. I'd prioritize cohesion over extensibility. When people talk about best practices, they don't talk about how a lot of them are incompatible, or at least at odds with each other. Writing code is about choosing the best practices you want to prioritize as much as it's about avoiding bad practices.
- unnouinceput 2y agoMaintenance is 90% of a project life time. Sometime those "best practices" rigid implemented means the project won't live to see even it's 1st birthday.
- 0xbadcafebee 2y agoReadability doesn't matter much when you have 10,000+ lines of code. You aren't going to read all that code, and new code introduced by other people continuously isn't something you can keep track of, so even if you understand one tiny bit of code, you won't know about the rest. You need a system of code management (documentation, diagram, IDE, tests, etc), to explain in a human-friendly way what the hell is going on. Small chunks of code will be readable enough, and the code management systems will help you understand how it relates to other code.
- ugh123 2y ago> You need a system of code management (documentation, diagram, IDE, tests, etc), to explain in a human-friendly way what the hell is going on I think this is where AI could be helpful in explaining and inspecting large codebases, as an assist to a developer.
- rohansingh 2y agoMaybe but hallucinations become a real problem here. Even with publicly available API's that are just slightly off the beaten path, I've gotten full-on hallucinations that have derailed me and wasted time.
- chipdart 2y ago> I think this is where AI could be helpful in explaining and inspecting large codebases, as an assist to a developer. That's a great point. Everyone lauds the benefits of chatgpt/copilot in generating new code, but I'm starting to learn that the places they might shine is onboarding onto projects and preliminary code reviews. What LlMs excel at is context, and they should excel in activities where context-awareness is key.
- dieortin 2y agoEven if you’re not going to read 10.000+ lines, if the few you read are easy to understand you’re still going to have a much better time maintaining the codebase.
- chipdart 2y ago> Readability doesn't matter much when you have 10,000+ lines of code. You aren't going to read all that code (...) You got it entirely backwards. Readability becomes far more important with the size of your project. When you get a bug report of a feature request, you need to dive into the code and update the relevant bits. With big projects, odds are you will need to change bits of the code you never knew they existed. The only way that's possible is if the code is clear and it's easy to sift through, understand, and follow. > You need a system of code management (documentation, diagram, IDE, tests, etc), to explain in a human-friendly way what the hell is going on. That system of code management is the code itself. Any IDE supports searching for references, jump to definitions, see inheritance chains, etc. Readable code is code that is easy to navigate and whose changes are obvious.
- foresto 2y ago> Readability doesn't matter much when you have 10,000+ lines of code. You aren't going to read all that code, As someone who has read 10,000+ lines in order to track down surprising behavior in other people's code, I can say without a doubt that readability still matters at that scale. Code management systems can sometimes be helpful, but they are no substitute.
- fmbb 2y ago> Small chunks of code will be readable enough Ravioli code is a real problem though. Saying small chunks are readable is not enough. The blast radius of a five byte change can be fifteen code paths and five million requests per hour.
- HumblyTossed 2y ago10KLoC is a very small app. Ours isn't that big and it's 140KLoC and I have read almost all of it.
- chipdart 2y agoTo be fair, not all lines of code are equal. A project with a state machine, commands, strategy patterns, etc requires an awful lot of repetitive boilerplate. A number-crunching app or a data processing pipeline packed with spaghetti business logic is far harder ti read.
- HumblyTossed 2y agoAnd that is why KLoC is a very piss poor metric. >A project with a state machine, commands, strategy patterns, etc requires an awful lot of repetitive boilerplate. Yeah, good thing we're not a java shop...
- drojas 2y agoI agree and would add that one of the goals for technical design or architecture work is to choose the architecture that minimizes the friction between best practices. For example if you architecture makes cohesion decrease readability too much then perhaps there is a better architecture. I see this tradeoff pop up from time to time at my work for example when we deal with features that support multiple "flavors" of the same data model, then we have either a bunch of functions for each providing extensibility or a messy root function that provides cohesion. At the end both best practices can be supported by using an interface (or similar construct depending on the language) in which cohesion is provided by logic that only cares about the interface and extensibility is provided by having the right interface (offload details to the specific implementations)
- englishspot 2y agoI have a pessimistic view that ultimately the only best practices that matter are the ones your boss or your tech lead likes.
- jkaptur 2y agoWhat about when you are the boss or tech lead?
- znkr 2y agoThen the only best practices that matter are the ones that your team believes are correct
- rvnx 2y agoThe best practices are the ones that allow you to do business and where the maintenance work is relatively not too painful considering the budgeted development time. Your task is to deliver a good product, not necessarily good code.
- englishspot 2y ago> The best practices are the ones that allow you to do business and where the maintenance work is relatively not too painful considering the budgeted development time. the problem is even that in concrete terms can be controversial. everyone wants to minimize maintenance work; not everyone agrees on what kind of code will achieve that.
- delichon 2y ago"Read" isn't quite the right word for code. "Decode" is better. We have to read to decode, but decoding is far less linear than reading narrative text. Being DRY usually makes decoding easier, not harder, because it makes the logic more cohesive. If I know you only fromajulate blivers in one place I don't have to decode elsewhere.
- hathawsh 2y agoWell, "read" is still the verb we use most often to describe a human interpreting code. Also, many information-dense books are not intended to be read linearly, yet we still say we're "reading" (or "studying") the book.
- wwfn 2y agoI was just mulling this over today. DRY = easier-to-decode is probably true if you're working on groking the system at large. If you just want to peak in at something specific quickly, DRY code can be painful. I wanted to see what compile flags were used by guix when compiling emacs. `guix edit emacs-next` brings up a file with nested definitions on top of the base package. I had to trust my working memory to unnest the definitions and track which compile flags are being added or removed. https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/emacs.scm#n577 https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages... It'd be more error prone to have each package using redundant base information, but I would have decoded what I was after a lot faster. Separately, there was a bug in some software aggregating cifti file values into tab separated values. But because any cifti->tsv conversion was generalized, it was too opaque for me to identify and patch myself as a drive-by contributor. https://github.com/PennLINC/xcp_d/issues/1170 https://github.com/PennLINC/xcp_d/issues/1170 to https://github.com/PennLINC/xcp_d/pull/1175/files#diff-76920bc632df09fee7a19d4e85d1daf3f0409419f016a94a40e2684b16b005a6 https://github.com/PennLINC/xcp_d/pull/1175/files#diff-76920...
- emidln 2y agoBazel solves this exact problem (coming from its macrosystem) by allowing you to ask for what I term the "macroexpanded" BUILD definition using `bazel query --output=build //some/pkg/or:target`. When bazel does this, it also comments the file, macro,and line number the expanded content came from for each block. This gives us reuse without obscuring the real definition. I automated this in my emacs to be able to "macroexpand" the current buid file in a new buffer. It saves me a lot of time.
- blackoil 2y agoI am of opinion, code should be written to be readable. Rest of the desirable properties are just side-effects.
- gavmor 2y agoI think it's fair to say that between behavior and maintainability, one is inflexible and the other hangs from it in tension.
- jay-barronville 2y agoFully agree. I think this is something that takes some time/experience to appreciate though. Junior engineers will spend countless hours writing pages of code that align with the “design patterns” or “best practices” of the day when there’s a simpler implementation of the code they’re writing. (I’m not saying this condescendingly—I was once a junior engineer who did that too!)
- coffeebeqn 2y agoIt’s impossible to know what “good” looks like when you’re new and haven’t seen a few codebases of varying quality and made some terrible mistakes
- marcosdumay 2y agoMost commonly, code should optimized into being easy to change. That's almost entirely coincidental with being easy to read. But even easiness to read is a side effect.
- hnick 2y agoI agree with this. Easy to change often means good tests too. I worked in Perl. Yes it has a reputation for being hard to read, but that was not the problem. Our scripting was pretty basic and easy to read. It's the loose typing, the runtime evals, the lack of strict function parameters, no real IDE, “Only perl can parse Perl” - the fact you can load a module from a network share at runtime, import it, and call a function, based on a certain run flag - and so on. Refactoring was always a mine field and there was a lot I wanted to do in my old job but could not justify it due to the risk.
- jay-barronville 2y agoReadability is almost always (almost only because there are some rare exceptions) the most important thing to me, even for low-level systems software. I always ask myself, “If I don’t touch this code for a year and then come back to it, how long will it take me to understand it again? How long will it take someone who’s never been exposed to this code to understand it?” Luckily, our compilers and interpreters have gotten so good and advanced that, in 95%+ of cases, we need not make premature “optimizations” (or introduce hierarchies of “design patterns”) that sacrifice readability for speed or code size.
- arp242 2y agoWas reading 1978 Elements of Programming Style a while ago. It's mostly Fortran and PL/I. Some of it is outdated, but a lot applies today as well. See e.g. https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style#Lessons https://en.wikipedia.org/wiki/The_Elements_of_Programming_St... They actually have a Fortran example of "optimized" code that's quite difficult to follow, but allegedly faster according to the comments. But they rewrote it to be more readable and ... turns out that's actually faster! So this already applied even on 197something hardware. Also reminds me about this quote about early development of Unix and C: "Dennis Ritchie encouraged modularity by telling all and sundry that function calls were really, really cheap in C. Everybody started writing small functions and modularizing. Years later we found out that function calls were still expensive on the PDP-11, and VAX code was often spending 50% of its time in the CALLS instruction. Dennis had lied to us! But it was too late; we were all hooked..." And Knuth's "premature optimisation is the root of all evil" quote is also decades old by now. Kind of interesting we've been fighting this battle for over 50 years now :-/ (It should go without saying there are exceptions, and cases where you do need to optimize the shit out of things, after having proven that performance may be an issue. Also at scale "5% faster" can mean "need 5% less servers", which can translate to millions/dollars saved per year – "programmers are more expensive than computers" is another maxim that doesn't always hold true).
- semi-extrinsic 2y ago> Dennis Ritchie encouraged modularity by telling all and sundry that function calls were really, really cheap in C. The old salty professor who taught numerical physics at my uni insisted that function calls were slow and that it was better to write everything in main. He gave all his examples in Fortran 77. This was in the 2010s...
- zooq_ai 2y agoaka "Engineering is about trade-offs"
- Guvante 2y agoDRY is IMHO a maintenance thing. If "I don't want to maintain three copies of this" is your reaction unifying likely makes sense. But that assumes the maintenance would be similar which is obviously a big assumption.
- coffeebeqn 2y agoDRY often gives you the wrong or a leaky abstraction and creates dependencies between sometimes unrelated pieces of code. It’s got tradeoffs rather than being a silver bullet for improving codebases. Having 0% DRY is probably bad, having 100% DRY is probably unhinged
- kitkat_new 2y ago> sometimes unrelated pieces you are using it wrong https://news.ycombinator.com/item?id=40525064#40525690 https://news.ycombinator.com/item?id=40525064#40525690
- insane_dreamer 2y ago> I'd prioritize readability over DRY. Yes. Especially at the beginning when it's critical to ensure that the logic is correct. You can then go back and DRY it up while making sure your unit tests (you did write those, right?) still pass. PS: same applies to "fancy" snippets that save you a few lines; write it the "long way" first and then make it fancy once you're sure it runs the way it's supposed to
- kitkat_new 2y ago> You can then go back and DRY it up while making sure your unit tests (you did write those, right?) still pass. not gonna happen once merged
- hot_gril 2y agoI place copy-pastability somewhere into those priorities too :)
- woodpanel 2y agoAgree and would add that software projects also run through different phases in their lifespans with each phase having their own objectives [1]. So while - as you say - best practices can be at odds with each other - dev teams might be following both over time, just prioritizing one in some phase while completely disregarding it during another. [1] E.g. the UI of the actual product might pivot multiple times at phase 1 because the product has yet to find its niche or core offering. While at a later stage the focus might be on massive scaling, either in numbers of devs or rolling out the product in new jurisdictions. Other phases might be a maintenance one, when an "offshore" team is given ownership or a sundown of an application.
- p1necone 2y ago> Cohesion over extensibility. Imo the very best approach is a codebase that's small enough that you can just do chunky refactors every so often rather than building in extensibility as a "thing". Not applicable to all problem spaces (I'd hate to do this for UI code), but for a lot of stuff it works really nicely. For me this often looks like an external DSL/API that stays relatively constant (but improving), with guts that are always changing.