Why You Shouldn't Nest Your Code

2,642,447
0
Published 2022-12-06
I'm a Never Nester and you should too.

Access to code examples, discord, song names and more at www.patreon.com/codeaesthetic

Correction: At 2:20 the inversion should be "less than or equal", not "less than"

All Comments (21)
  • I once nested 20 layers deep. Much like inception, time reading the code becomes exponentially longer the deeper you get... It's a miracle I'm even here today.
  • @PrimerBlobs
    I will admit to being an out-of-control nester, but I'm recovering. It really does make code easier to understand.
  • @aleceastman
    I think this is actually crucial to teach to beginners. Holding exceptions and conditions in your head makes a code base really hard for others to read.
  • @CodeAesthetic
    A few of you, rightly so, pointed out that the inversion at 2:20 should be `<=` instead of `<`. I'll need to start unit testing my videos
  • @jonesmartins
    Update: He fixed it. Nice! :-) I'd suggest using a lighter background when highlighting code and darkening the rest instead of blurring the rest, so that it's faster to find the line.
  • @Komil484
    There's actually a small error at 2:20, when you change the "top > bottom" to "top < bottom", as they are not exactly opposites. This actually changes the output of the function when "bottom == top"
  • @toddbarton1049
    I particularly like Extraction because then you can give the function really descriptive names, then when you read thru the top function it's almost like you're just reading a book, instead of interpreting the logical flow of the code. I often combine Extraction and Inversion, in that after I invert, I'll extract the inverted code into its own (descriptive) function.
  • I just want to applaud the visual design of this video, especially the code. The blurring, previewing important definitions, uncluttered diagrams, use of color, typewriting, introducing motion to draw/hold attention. It really communicates the intent of the code better than I've seen anywhere else.
  • Just wanted to point out a common error when inverting logic. At 2:20, the inversion technique is demonstrated. Before, the "happy" case was (top > bottom), which made the "sad" case (top <= bottom). After, the sad case was (top < bottom), making the happy case (top >= bottom). This creates a classic "off by one" error. In the case where top and bottom are equal, the former returned 0 and the latter returns one iteration of the sum equal to the result of filterNumber(). I know that isn't really the point of the example, but you do need to be careful when using logic inversion.
  • @kilianbalter
    I'm a huge fan of "guard clauses" (simple if's at the start of the function which basically just return because the return value is obvious due to a special case input). So I was VERY bewildered when in my early programming classes (In 2020!) it kept being blanketly repeated that "a function should never have multiple returns". If you have one return 50 lines in and another 100 lines in, sure... but then you probably haven't split up the function correctly to begin with. You can write much simpler and cleaner code when you filter out all the special cases at the beginning as much as possible. One simple example would be a power function: pow(base, exponent) if(base == 0 && exponent == 0) throw Exception; (if you'd want to treat it as undefined) if(exponent == 0) return 1; if(exponent == 1) return base; ...rest of function to actually calculate the power Now this definitely goes against a different technique called branchless programming, but unless your function is called very very often in some heavy computing task, the readability far outweighs the speed.
  • @PaulSinnema
    I totally agree. This was a nice example of refactoring code. When I start a new piece of code I always force myself to not go into the details right away but create a fundament that outlines what I'm trying to build. Extracting routines and give the names of what I need to do in them and handle any results. This way I can start to think about the bigger picture before diving into the details. It helps me tackle the whole problem more easy. When I get to the nitty gritty of the details I may need to refactor some of the outline I made but most of the time it is not needed. Chopping the problem up like this lets me focus on each little detail independent of the whole problem. When I find that an extraction is becoming too big I create a little more outline before diving into the details again. Works very well for me. Sometimes I find that the way I thought about the fundament is totally wrong. No problem. I didn't write much code so far, so starting over is not very costly and I've learned a lot setting it up the wrong way.
  • @techman2553
    Just code for clarity. Sometimes that means breaking complex methods in several simpler routines, other times that means combining several micro routines into one larger method. Sometimes nesting gets really confusing, other times nesting adds clarity to the code. Sticking to any one type of code structure religiously just adds complexity in different ways.
  • @jsonlee01
    Out of control nesting is definitely bad but sometimes when the guts of the code are extracted into smaller and smaller functions it also makes following the flow of the logic hard as well. You still have to try and keep track of what the parent of the parent is doing. At that point you are still in a nesting scenario, you’ve just shifted into smaller chunks of separated code. It’s a fine balance. Guard clauses help to get rid of unnecessary if/else conditions.
  • A former colleague of mine used to nest entire programs in an if (true) {} at the top of all his code. Someone spent a day while this colleague was on vacation trying to understand why one of these programs was indented one additional, unnecessary level in all places. When the problematic colleague returned from vacation, he explained that this pathological behavior was simply for debugging and as a “safety switch” he could set while programming. Our boss gently but firmly ordered him to discontinue this practice.
  • @shanehebert396
    At 2:24 in your inversion, "if (top > bottom)" doesn't invert to "if (top < bottom)", that potentially introduces a bug. It probably should be "if (top <= bottom)". While I agree with you generally, be aware that inverting logic can introduce additional issues.
  • @SJrad
    Reminder to not go overboard with extractions as it creates a readability issue having to excessively jump from function to function. Especially if they’re not placed near each other and/or poorly named.
  • 100% on what you said about separating the error paths from the good paths, it makes it so much easier reading the code months or years down the line. That approach really shines when writing code: you think of the error conditions first, handle them, then continue writing the good paths, but with a lot less to think about.
  • @ColdFuse96
    One time in a programming fundamentals class, I ran into a progran that had a block of code that was a loop within a loop within a loop, and it asked how many times total will the inner most loop loop, and I just sat there like an idiot actually working it out by hand. I decided right there that I will avoid nests wherever I could!!!