7 ms·
As I get older my code gets a little more verbose and a little less idiomatic to the language I am writing. I’ve been writing code, starting with C, since 95. M
by bitexploder 6y ago
As I get older my code gets a little more verbose and a little less idiomatic to the language I am writing. I’ve been writing code, starting with C, since 95. Mostly Python these days, but I try to make it clear and easy read. Mostly for myself. Future me is always happy when I take the time to comment my overarching goals for a piece of code and make it clean and well composed with enough, but not too many, functions.
- nomel 6y ago> well composed with enough, but too many, functions. In my experience, code with too many functions is more difficult to grok than spaghetti code. It's like trying to read a book with each sentence reference a different page. So, I try to code like I would write, in digestible chunks. > As I get older my code gets a little more verbose I've seen too many of my previous projects die right when I moved on. Now I tend to write code as if it were written by a beginner: verbose and boring, with no magic.
- axcdnt 6y agoSo many levels of indirection is the recipe for the modern goto.
- nx7487 6y ago> In my experience, code with too many functions is more difficult to grok than spaghetti code. In a way, it kind of _is_ spaghetti code. Even if there's no back references, it turns a single train of thought into a string of entrances and exits.
- agallant 6y agoThe best label I've heard for the excessive layers anti-pattern is "lasagna code."
- UK-Al05 6y agoLasagna code isn't meant to be derogatory, just a description.
- agallant 6y agohttps://wiki.c2.com/?LasagnaCode https://wiki.c2.com/?LasagnaCode https://en.wikipedia.org/wiki/Spaghetti_code#Lasagna_code https://en.wikipedia.org/wiki/Spaghetti_code#Lasagna_code https://matthiasnoback.nl/2018/02/lasagna-code-too-many-layers/ https://matthiasnoback.nl/2018/02/lasagna-code-too-many-laye... https://dev.to/mortoray/what-is-your-tale-of-lasagne-code-code-with-too-many-layers-3lp2 https://dev.to/mortoray/what-is-your-tale-of-lasagne-code-co... Generally used with a negative connotation. C2 also discusses how the layers can become entangled/stuck with one another and difficult to replace, which seems to fit the metaphor. For describing layered code in a non-negative fashion, just saying "layered (or "modular") seems most typical.
- u801e 6y ago"Lasagna code" might be a better term.
- pineconewarrior 6y agoIt's easy to say ugh, but we juniors are more than willing to learn "the right way". This is the hardest part for me. I get anxiety about it and it slows me down. How do I apply this to taking over someone else's 4 year old Magento project? We're out here doing our best, and sometimes our learning environments are in that context.
- hutzlibu 6y ago"the right way" I would say, don't stress about it too much. There is no perfect way. Everyone makes misstakes. And about when to make abstractions and when not, is mostly about experience. There are modules worth optimizing and abstracting. And others are not. You definitely will make wrong decisions about it and later found out, this optimisation was a waste of time, or that quick and dirty approach really cost you much later on, we all did that and still do. Much worse than making a wrong (design) decision is making no decision at all - because mostly you have to decide for something and then just go with it. Overthinking things seldom helps. What helps me sometimes is, putting a special hard problem to the side if I am stuck and solve something easier first. Then after some time, when I get back to it, things are much more clear. But I also wasted too much time thinking about the right approach in a neverending, neverprogressing loop to achieve perfection. Now my question is not, is it perfect or shiny, but: Is it good enough? What matters is, that shit gets done in a way that works.
- laudable-logic 6y ago> wasted too much time thinking about the right approach in a neverending, neverprogressing loop to achieve perfection A CEO from my past often muttered that "perfect software comes at infinite cost". It's key, imo, to identify which components of what you are building _must_ be perfect. The rest can have warts.
- hutzlibu 6y ago"to identify which components of what you are building _must_ be perfect" Well, but by the words of your former CEO (and my opinion) those parts would then have infinite costs, too... if they really need to be perfect. I mean, it is awesome, when you do a big feature change and it all just runs smooth without problems, because your design was well thought out, but you cannot think of every future change to come - and when you still try, chances are you get stuck and waste your time and risk the flow of the whole project. I rather tend to think about the current needs first and the immediate future second, but everything after that, I spend not much thought anymore.
- dcolkitt 6y agoI disagree. I think the central thesis of Clean Code still holds up. You should never mix layers of abstraction in a single function. That more than anything is what kills readability, because context switching imposes a huge cognitive load. Isolating layers of abstraction almost always means small, isolated, single-purpose functions.
- Chris_Newton 6y agoI think the central thesis of Clean Code still holds up. You should never mix layers of abstraction in a single function. I agree up to a point, but I find this kind of separation a little… idealistic? I prefer the principle that any abstraction should hide significantly more complexity than it introduces. At the level of system design, there probably are some clearly defined layers of abstraction. I’d agree that mixing those is rarely a good idea. But at the level of individual functions, I have too often seen numerous small functions broken out for dogmatic reasons, even though they hid relatively little complexity. That coding style tends to result in low cohesion, and I think the cost of low cohesion in large programs is often underestimated and can easily outweigh the benefit of making any individual function marginally simpler. If you’re not careful, you end up trading a little reduction in complexity locally for a big increase in complexity globally.
- gcpwnd 6y agoYes context switching is a huge cognitive load. Abstractions enforce context switching.
- eyelidlessness 6y agoI’d say that’s a sign that either it’s the wrong abstraction, there’s implicit coupling (a distinct variant of the wrong abstraction), or both sides of the abstraction are in so much flux that the context switching is inevitable until one or both layers settle down.
- mjfisher 6y agoThe primary motivating reason to have abstractions in the first place is to prevent context switching - i.e. you shouldn't have to think about networking code while you're writing business logic.
- abledon 6y ago> It's like trying to read a book with each sentence reference a different page. Yes!!! I've been trying to teach Juniors that if the function itself has 4 levels of abstraction, even if the names are readableFunctionThatDoesXwithYSideEffect ..... it is harder to understand, Ctrl+clicking downards into each little mini-rabbit -hole. Just keep the function as a 80-liner, not a 20-liner with 4 levels of indirection w/ functions that are only used once (inside parent function) ugh.
- methodsignature 6y agoThey all probably read Clean Code, the discussion on functions in that book may be the most harmful/costly to programming in the last 20 years.
- IggleSniggle 6y agoClean Code is still a great read in 2020, but I think you’re right about some of the specific advice about functions.
- abledon 6y agoIs there a good blogpost/writeup on this idea? I've seen it mentioned before in other threads.... And i agree 100%
- tekdude 6y agoFrom John Carmack: http://number-none.com/blow/blog/programming/2014/09/26/carmack-on-inlined-code.html http://number-none.com/blow/blog/programming/2014/09/26/carm...
- UK-Al05 6y agoThat's a for a specific case of high performance code and removing duplicated work. Referencing carmwack always has to be in the context of high performance code. Even carmack himself has started like functional code. Which normally leads you down small pure functions.
- bitexploder 6y agoI meant to write “not too many” functions of course :)
- koolba 6y ago> In my experience, code with too many functions is more difficult to grok than spaghetti code. Because it is, just on multiple plates.
- hutzlibu 6y ago"I've seen too many of my previous projects die right when I moved on. Now I tend to write code as if it were written by a beginner: verbose and boring, with no magic." Theres nothing wrong with charming magic in your code, if it really does something special and is not just used for the sake of it - it only gets into dark magic, when you forget or are too lazy to add proper documentation in the end. Which ... happened to me, too many times. But otherwise very much yes. Clarity and simplicity should be always goal number one. But since simplicity is hard to reach at times and time is short, it is always about the balance.
- bigbizisverywyz 6y agoI once read a quote, possibly here on HN that said: "Code first for the machines, then for others that will maintain your code and lastly for yourself." And that I think for me nicely strikes the balance.
- hutzlibu 6y agoHm, coding for the machine would mean to me, write processoroptimized code allways. And I rather have clear, maintainable code - which is easier to work with and therefore less filled with bugs.
- runald 6y agoIf you are comparing reading code with reading books, then surely you have read books that have unfamiliar words that you have to lookup the definition, and then you might have to recursively lookup the unfamiliar words in the definition as well. Then when you internalized the sub-definitions, then you return to what you were reading and have a better understanding. The difference between code and books is that programmers can freely and naturally define functions. I wonder if some people complaining about too many functions never actually learned how to read code in the first place.
- jrott 6y ago> In my experience, code with too many functions is more difficult to grok than spaghetti code. It's like trying to read a book with each sentence reference a different page. So, I try to code like I would write, in digestible chunks. This is so true. The worst code that I've dealt with is the code that requires jumping to a ton of different files to figure out what is going on. It's usually easier to decompose a pile of spaghetti code than to figure out how to unwrap code that has been overly abstracted.
- redisman 6y agoMy experience has been that spaghetti is almost always in the real world mostly overly abstract and poorly thought out abstractions. You know you get a stack trace and you end up on a journey in the debugger for 5 hours trying to find any actual concrete functionality. Compared to someone writing inline functions that do too much, the wasted brain hours don’t even come close
- bigbizisverywyz 6y agoIt's also often very deeply nested and follows different paths based on variables that were set higher up in the code, also depending on deeply nested criteria being met. Bugs, weird states, bad error handling and resource leaks hide easily in such code. In my experience refactoring out anything nested >3 levels immediately makes the code more readable and easier to follow - I'm talking about c++ code that I recently worked on. Decomposing to functions and passing as const or not the required variables to functions that then do some useful work makes it clear what's mutated by the sub functions. Make the error handling policy clear and consistent. Enforce early return and RAII vigorously to ensure that no resources (malloc,file handles,db connections, mutexes, ...) are leaked on error or an exception being thrown. And suddenly you have a code base that's performant, reliable and comprehensible where people feel confident making changes.
- Ma8ee 6y agoOn the other hand, no abstractions is like reading a book where each and every thing is spelled out in outmost detail. Instead of telling you “I’m fuelling the car”, I’ll tell you: “I’m walking to the entrance hall. I’m picking up the car keys. I’m putting on my shoes. I’m putting on my jacket. I’m unlocking the front door ...”. You see where this is going. And here we already assumed that things like “putting on shoes” are provided by a standard library. There seems to be two types of programmers: one that can read a line of code like or theCar.fuel() and trust that you in the current context understand enough of what the call does that you can continue reading on the current level of code. This type of programmers don’t mind abstractions even if a function is called in only one place. The other type of programmer must immediately dig into the car.fuel code and make sure she understands that functionality before she can continue. And of course then each and every call becomes a misdirection from understanding the code, and of course for them it is better is everything is spelled out on the same level. I’ve seen quite a bit of code written by the second type of programmers, and if you don’t mind scrolling and don’t mind reading the comment chapter headers (/* here we fuel the car */) instead of all the code itself, it can be reasonably readable. But there’s never comprehensive testing coverage for this kind of code, and there’s usually code for fuelling the car in four different places because programmers 2-4 didn’t have time to read all the old code to see if there was something they could reuse, and just assumed that no one had to fuel the car before since there wasn’t any car.fuel() method.
- x0054 6y agoNot sure why you are down voted, I completely agree.
- slaymaker1907 6y agoThe one caveat is that I want to easily be able to find out what fuel() is doing. Preferably nothing like car.getService('engine').run('fueling'). Code navigation is very important, preferably doable via ctrl+f since that makes review easier. Most people just use the browser tools for reviewing code and don't actually pull the branch into their IDE.
- cxr 6y ago
- nicbou 6y agoPerhaps we just imagine different things, but I like when code is a list of human-readable calls to functions. The implementation of these functions isn't so important to understanding the code you're reading. This works really well as long as you use pure functions, because their impact on behaviour is clearly restricted.
- augustk 6y agoJohn Ousterhout's "A Philosophy of Software Design" is an interesting alternative to Clean Code.
- zamalek 6y ago> Mostly Python these days, but I try to make it clear and easy read. Which is why I enjoy languages that let me do this without getting too hung up on performance. It's curious that you bring up Python, because idiomatic Python (especially where math libs are concerned) seems to vastly favor brevity/one-liners over all else. It's nice to hear that a veteran is favoring clarity.
- bitexploder 6y agoThere is a point where fitting a little more code on one screen actually helps. Usually not though. Our brains can only see a screen at a time. There is some optimal mix of terseness, especially when you know your reader (probably you in a few months!) will grok it, vs verbosity. If I find myself untangling a single line down the road in my brain it was too complex. Python is already so expressive! We all find our style, but generally I know I did it right if I look back at code at think “wow that’s easy to understand” vs “hmmn, what was I thinking there?” Heh.
- eyelidlessness 6y ago> idiomatic Python (especially where math libs are concerned) seems to vastly favor brevity/one-liners over all else I can’t speak to math libs, but in my experience with server-side development, Python devs tend to (often even religiously) cite PEP style guides favoring explicitness and verbosity. I think there may have been a shift as Python got a lot of uptake in scientific and ML communities, and I hope that hasn’t seriously impacted the rest of the Python community because, while I don’t especially love the language/environment, I deeply appreciated the consistency of valuing clear and readable code.
- paganel 6y ago> cite PEP style guides favoring explicitness and verbosity. Explicit is better than implicit, always has been, always will be. Granted, I've been writing backend/server-side Python code for 15 years now, so that might be one of the reasons.
- 6y ago