Why You Shouldn't Nest Your Code

Sdílet
Vložit
  • čas přidán 5. 12. 2022
  • I'm a Never Nester and you should too.
    Access to code examples, discord, song names and more at / codeaesthetic
    Correction: At 2:20 the inversion should be "less than or equal", not "less than"

Komentáře • 6K

  • @tristanneal9552
    @tristanneal9552 Před rokem +6030

    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.

    • @onlyhereforthefish9924
      @onlyhereforthefish9924 Před rokem +280

      I worked at a place that had SQL stored procedures calling stored procedures sometimes 10 or 15 deep. It was nuts.

    • @christianschmid1440
      @christianschmid1440 Před rokem +55

      Welcome. It's good to have you back!

    • @BiP00
      @BiP00 Před rokem +89

      Perhaps the dream became your reality.

    • @voster77hh
      @voster77hh Před rokem +24

      it's a learning process. We all start there

    • @maurobrandolt2166
      @maurobrandolt2166 Před rokem +9

      LMFAO

  • @PrimerBlobs
    @PrimerBlobs Před rokem +7139

    I will admit to being an out-of-control nester, but I'm recovering. It really does make code easier to understand.

    • @tomzitiger
      @tomzitiger Před rokem +104

      Primer! ❤

    • @linebreaker8751
      @linebreaker8751 Před rokem +119

      Also I didn't know I was a never nester. I just thought I had to code like that. Also I am a strong single liner because I hate scrolling my code.

    • @linebreaker8751
      @linebreaker8751 Před rokem +9

      Oh boy how did you end up in coding? Can you make a video about it if you are able to?

    • @thiagoassisfernandes
      @thiagoassisfernandes Před rokem +1

      and easier to test

    • @voster77hh
      @voster77hh Před rokem +4

      It's a learning process. We all start there

  • @aleceastman
    @aleceastman Před 5 měsíci +731

    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.

    • @anibalubilla5689
      @anibalubilla5689 Před 3 měsíci +34

      Not only for others but for oneself.
      I find myself comming to a week old code, and wonder who nested all that code.

    • @chaosa928
      @chaosa928 Před 3 měsíci +2

      I'm quite glad I came across this video...

    • @greyrifterrellik5837
      @greyrifterrellik5837 Před 2 měsíci +2

      Imma be honest.
      At least in my situation, I fail to see any reason why any of this matters.
      I'm a solo dev, nobody else is working on this code but me so nobody else is gonna be seeing it but me.
      And I'm looking at this "un nested" code and it's honestly HARDER for me to read than nested code.
      The unnested code blurs together, while nested code creates immediate, obvious separations.

    • @chaosa928
      @chaosa928 Před 2 měsíci +1

      @greyrifterrellik5837 so you can't see why others would prefer this way?

    • @greyrifterrellik5837
      @greyrifterrellik5837 Před 2 měsíci

      @@chaosa928 Well I mean I can't see how it's easier to read this way, which is the claimed benefit, so no not really.

  • @tomdarank1272
    @tomdarank1272 Před 24 dny +24

    Nobody tell this guy about HTML

  • @CodeAesthetic
    @CodeAesthetic  Před rokem +2586

    A few of you, rightly so, pointed out that the inversion at 2:20 should be `

    • @Handlessuck1
      @Handlessuck1 Před rokem +32

      You are doing so well! I can already see you growing into a popular channel!

    • @lonkwuzhere4433
      @lonkwuzhere4433 Před rokem +54

      don't worry, people on the internet are always nitpicking like that. Your editing style and video structure definatly make up for minor mistakes like that haha.

    • @code-dredd
      @code-dredd Před rokem +7

      Posted the same prior to reading this. Deleted mine.

    • @malloc7367
      @malloc7367 Před rokem +14

      My day was ruined until I read this.

    • @SixOThree
      @SixOThree Před rokem +17

      @@beqa2758 I don't allow conditionals without braces in my projects. I don't care if the braces are on the same line as their contents, but you _must_ have braces.
      The reason is very literally almost every time I have seen if or else statements without braces, I have seen another person break them unintentionally.

  • @jonesmartins
    @jonesmartins Před rokem +6235

    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.

    • @cyberprompt
      @cyberprompt Před rokem +581

      true, my eye went to the animation blurring then I had to scan around.

    • @LordBeef
      @LordBeef Před rokem +43

      Same for me

    • @dirkniblickable
      @dirkniblickable Před rokem +122

      Came here to say this. Darkening (and blurring) the “unimportant” code would improve readability.

    • @ChrisAthanas
      @ChrisAthanas Před rokem +7

      Yes please

    • @mohammadazad8350
      @mohammadazad8350 Před rokem +77

      A highlighting rectangle will help too

  • @Komil484
    @Komil484 Před 5 měsíci +456

    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"

    • @AntneeUK
      @AntneeUK Před 5 měsíci +88

      If I had a penny every time I saw someone invert > to < I'd have at least 10 pennies! Such an easy mistake to make, and it appears to work until you land on both numbers being identical and you're surprised and confused as to why things aren't working properly. Hopefully automated tests catch it 😉

    • @skccharan
      @skccharan Před 5 měsíci +6

      spot on 😲

    • @jakosvet
      @jakosvet Před 5 měsíci +65

      Inverted > is =

    • @VeritasGames
      @VeritasGames Před 5 měsíci +38

      glad I wasn't the only one triggered by that 😂

    • @bryantwalley
      @bryantwalley Před 4 měsíci +2

      Yes indeed. I had just typed a comment on this.

  • @toddbarton1049
    @toddbarton1049 Před 8 měsíci +198

    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.

    • @Knowbody42
      @Knowbody42 Před 5 měsíci +28

      Choosing descriptive names for your variables and functions is a big part of making code easy to read. The less thinking you have to do to understand what a variable is for, or what a function does, the better.

    • @Baby4Ghost
      @Baby4Ghost Před 4 měsíci +12

      "you're just reading a book"
      Thats what I expect from my code, consistency and appropriate semantic naming are key. The code should be as readable and understandable as a book telling a story.

    • @sebastiang7394
      @sebastiang7394 Před 4 měsíci +4

      And that’s why you shouldn’t need comments in 99% of all cases. Extract all logical units into their own function and give it a descriptive name. Much better than lengthy comments that never get updated when someone changes the code.

    • @LordxJoe
      @LordxJoe Před 3 měsíci +3

      Biggest thing with this is to group the extracted methods logically. I can't tell you how many times i had to ctrl+click a method only to end up at the bottom of a 5000 line file because the developer who implemented new code couldn't be bothered.

    • @ccampau
      @ccampau Před 3 měsíci +2

      It's also makes the call stack much more informative when an error occurs. Easy to see "error in the foo method" vs the 1k line method had "object not set to an instance of an object"

  • @johnheaney3349
    @johnheaney3349 Před rokem +1196

    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). 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.

    • @kakaopor
      @kakaopor Před rokem +94

      I knew that mistake would probably happen before he made the change. Don't ask me why. Pls don't.

    • @jebwatson
      @jebwatson Před rokem +31

      An excellent point and a mistake I've seen (and made) countless times.

    • @idselseno2306
      @idselseno2306 Před rokem +29

      Like in welding. Beautiful doesn't mean good.

    • @reasonable1
      @reasonable1 Před rokem +57

      True, a lot of people get inverting boolean logic wrong. Another one I saw recently was inverting (a && !b) to (!a && b). Instead, first invert the whole expression and then apply De'Morgan's law: !(a && !b) => (!a || b).

    • @fff-kd8kg
      @fff-kd8kg Před rokem +8

      In this case, top==bottom would return 0 too, so it isn't logically incorrect. but yeah, I get your point.

  • @jakobbarger1260
    @jakobbarger1260 Před rokem +1389

    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.

    • @LinkEX
      @LinkEX Před rokem +37

      Seconded. The whole presentation is incredibly elegant.
      It doesn't seem like much but managed to deliver on a lot of aspects.
      Subtle but refined, directing the viewer's attention while not distracting and letting them think on what is being said.

    • @AliAhmad-qy2sf
      @AliAhmad-qy2sf Před rokem +19

      @@LinkEX I do have to though sometimes when the code was blurred it took me a while to find it. idk if thats just be being slow or perhaps an optimization could be made there. Maybe a little more contrast in the part thats not blurred, or a small arrow would help

    • @KeithCooper-Albuquerque
      @KeithCooper-Albuquerque Před rokem +3

      @@AliAhmad-qy2sf Thanks: You said what I wanted to say. Thanks also to LinkEX too for the thoughtful comments.

    • @astropgn
      @astropgn Před rokem +1

      Yeah, it is a good approach. Code in videos are so boring, even for people who enjoy programming, it is a hard task to make them interesting.

    • @robbybankston4238
      @robbybankston4238 Před 11 měsíci

      Agreed. The visual aids make it very clear to understand. Excellent job.

  • @kilianbalter
    @kilianbalter Před 5 měsíci +113

    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.

    • @icedreamer9629
      @icedreamer9629 Před 4 měsíci +18

      The best thing about guard clauses is that they are a perfect match to how you should be thinking when designing your program and writing your tests for it when following TDD practises. If you are designing complex functionality, the way any business describes it to you should be massaged into first the error conditions, then the happy path once all business concerns are satisfied.
      This lets you go and immediately write a test structure from the ticket, and then implementing the test structure automatically creates a flattened guard clause implementation.
      I find it incredible how many professional programmers haven't figured this out yet.

    • @shikyokira3065
      @shikyokira3065 Před 3 měsíci +13

      The problem with branchless programming is, it is often written in a way that you need to write comments to explain what kind of monster you have created, because the next programmer who will be taking up your project is likely more stupid than you.

    • @owenreynolds8718
      @owenreynolds8718 Před 3 měsíci +17

      "Never have multiple returns" was a good rule for the time. Because way back a "stack trace" meant manually adding debug lines to each function: "entering Q" and "leaving Q with value X". Return-from-middle (which is what I've heard it called) made old-time debugging extra-tough.
      So you may have been taught by someone who got their first job in 1982 and never worked anywhere else.

    • @shikyokira3065
      @shikyokira3065 Před 3 měsíci +6

      @@owenreynolds8718 Now that you put it this way, it does look quite logical to have this rule.

    • @ccampau
      @ccampau Před 3 měsíci +1

      Plus 1 for Guard classes. Had a coworker that insisted on writing out exception handlers every time. Needless to say his code was a mess.

  • @PaulSinnema
    @PaulSinnema Před 8 měsíci +18

    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.

  • @jsonlee01
    @jsonlee01 Před rokem +880

    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.

    • @bufdud4
      @bufdud4 Před rokem +116

      Facts. The flow of logic seems much more straight forward when nested.

    • @mrosskne
      @mrosskne Před 10 měsíci +23

      @@bufdud4 less straight forward*

    • @janiscakstins2846
      @janiscakstins2846 Před 9 měsíci +80

      @@bufdud4 nested code is often untestable because you don't have control over it. When you have code in small chunks, then it becomes easier to test individual components. Test driven design is great because it forces you to design testable code in the first place. As long as the interface is testable, then there is nothing wrong with nesting, but you need to have tests in the first place, which rarely is the case.

    • @codejunki567
      @codejunki567 Před 9 měsíci +17

      ​@mrosskne If you ever worked in a legacy back end system. 95% of things are the nested kind. Way easier to follow. Especially if you have 30 scripts to get by the end of the week.

    • @codejunki567
      @codejunki567 Před 9 měsíci +17

      ​@janiscakstins2846 That sounds crazy, any piece of logic should be testable. If you can't get to a nested part of code in your tests, either the test or code is flawed.

  • @techman2553
    @techman2553 Před rokem +328

    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.

    • @Axel_Andersen
      @Axel_Andersen Před rokem +57

      Being dogmatic about anything is wrong. Code for clarity, agreed!

    • @kindlin
      @kindlin Před rokem +22

      Thank you! Exactly. Nothing is black and white. Everything has its place. Even a few nests deep...

    • @Finkelfunk
      @Finkelfunk Před rokem +15

      I've never, and I mean _never_ seen clear code that is nested more than 4 deep. At 4 deep it becomes super tedious already. There is a reason they made this a kernel rule. I highly suggest you increase your tab width in your IDE of choice and you will quickly realize that there is almost always a way cleaner and easier method without nesting. It forces you to code better and come up with cleaner solutions, which ultimately leads to easier to read code that is much more maintainable.
      Gate clauses are a very easy example for that. Having a nested code means if you come across more exceptions your code needs to handle you need to escalate nesting into deeper and deeper parts of the code which will eventually lead to refactors anyways.
      Instead, having gate clauses at the top makes it a million times easier to add exceptions and still maintain readable code.
      Like sure, your 4 deep nest might "not look too bad" now, but wait until 16 different people have started adding conditions and you'll quickly end up with more nests than you can count. Nesting - not even once.

    • @kindlin
      @kindlin Před rokem +12

      @@Finkelfunk
      I'm 5 deep right now, about 100 lines of code. It's quite clean, clear and concise. Each section of the code is purposefully labeled and does it's own little bit just fine. I think this instance, tho, is one of the few times this makes sense, and that's a select/case, where the logic going into the select and under each case needs to work individually, so it's already naturally broken into sub functions, that's just how cases work. I guess I could break out my Line function and my Square function, etc. but there is no need, they are all right here, easy to see, edit and compare.

    • @jackreacher963
      @jackreacher963 Před rokem +24

      “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” - John F. Woods
      That quote came in my mind while reading your comment.
      It may be ok for you personally but if you start working professionally you have to write clean and maintainable code because someone else could be forced to maintain it. Nested code in switch-cases is always smelly code at least.

  • @frankpoon2605
    @frankpoon2605 Před 8 měsíci +2

    Just wow! Crystal clear explanation and superb graphics. You are an articulate teacher. Keep it up.

  • @skaldingdelight
    @skaldingdelight Před 8 měsíci +2

    This video has been on my recommended for months and I've been sleeping on it. This is great, great stuff.

  •  Před rokem +380

    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.

    • @gangulic
      @gangulic Před rokem +3

      trouble is when you need to follow for example MISRA and there you have: "A function should have a single point of exit at the end." - you can use only one return in function

    • @pvanukoff
      @pvanukoff Před rokem +32

      @@gangulic That's a silly rule, but if it must be followed, you could always utilize some sort of "proceed" boolean. At the top of the function, set it to true. Do your input validation steps, and if one of those steps fails, set the proceed boolean to false. When you get to the meat of the function, check that boolean first and only perform it if it's true (you can also utilize this boolean at each validation step after the first). Does this make it more complex than simply nesting? Maybe, maybe not, it depends on how many conditions you are checking, but it should satisfy the rule and allow for some de-nesting. Basically it turns a bunch of nested if statements into a flattened list.

    • @lollertoaster
      @lollertoaster Před rokem +2

      @@gangulic does exception counts as a point of exit? If you can't use those, then "do {} while(0);" and use break instead of return if you want to be polite or use "goto" if you want to send a message on what you thing about this rule.

  • @erichobbs4042
    @erichobbs4042 Před rokem +790

    I think that decomposing your mega function into a bunch of single responsibility micro functions definitely makes unit testing a lot more straightforward. But one thing that I have found is that I still need to write the mega function first. Once it's all down and working, I can then refactor it into something more sensible, but trying to write out all the single responsibility functions first, takes me more time than doing a "first draft" and then editing. It's like premature optimisation. Don't do it until you know that you have something you need to fix.
    I'm also a big fan of kicking out bad paths at the start. Not only is it easier to read, but when you discover a new unexpected bad path, you can just add another concise return block instead of having to nest something deeper in the function, and possibly missing a spot where you also needed to return rather than execute.

    • @alessandrotommasi9941
      @alessandrotommasi9941 Před rokem +51

      Paul Graham (I think) once wrote: good code is like good prose: it requires constant rewriting.

    • @owenrowell
      @owenrowell Před rokem +65

      I'm the complete opposite. I find it way easier to create a main function and complete that with unimplemented functions and then go and implement these one at a time. This way I can start by planning out the overall process of what I want to do and then handle each individual implementation of sections independently. Sometimes if when I then implement a function and it ends up just being a few lines of code I'll then move it back it back to the main function - but I still got the benefit of using placeholder functions to write out how I would approach the problem

    • @cybyrd9615
      @cybyrd9615 Před rokem +9

      Or you can ask GPT to de-nest

    • @thunder____
      @thunder____ Před rokem +3

      I find it certainly depends on what I'm doing; currently, I'm working on a PHP project with a bunch of POST forms, and the flow of those is generally extremely predictable, so I've been creating a main function with unimplemented functions to start off with for that. But when the structure of the task isn't so predictable from the start, I do generally find that jumping in and getting my hands dirty with a rough draft, and then refactoring that rough draft as needed, is a better way to quickly start turning that structure from nebulous to definite so I can start encountering and resolving unknown unknowns.

    • @b03tz
      @b03tz Před rokem +9

      I feel like once you get more and more experienced you don’t need that draft function anymore. But it might be just a way that you think / work it out. I hardly do it anymore unless really rapid prototyping a method or several implementations. I almost instantly know what piece of code should be a private method or even its own class.

  • @Cloudstreet
    @Cloudstreet Před 8 měsíci +1

    Saw a small version of this in a short. Really change my code and made it easier to follow my ideas. I recommend it to loads of people

  • @jmilen
    @jmilen Před 4 měsíci +7

    I was already doing this but not aware of all the benefits outlined here. I've always used extraction and inversion (without knowing their names) simply because it's cleaner and easier to read. Great video.

  • @asdfz0mg
    @asdfz0mg Před rokem +542

    I'm a never nester myself and I've used the extraction and condition inversion techniques many, many times. I just wanted to comment and say I found this video very pedagogical. I really liked how you visually showed how you refactor a function (with extraction and inversion) using animations rather than just live coding it. It's more work for you to edit that stuff but I think it's easier for beginners to follow along.
    The only thing I would suggest you to change is to more clearly highlight the code you're talking about. The blurring didn't quite work for me all the time and I had to really concentrate to see what parts where blurred or not. Maybe it's just me and it's time to get some glasses though. Over all a very nice video!

    • @simulatrix
      @simulatrix Před rokem +6

      Agreed. I like it when they grey out the unhighlighted code, like a comment would

    • @dylanh333
      @dylanh333 Před rokem +3

      There wasn't any blurring in the video - it was just your eyes!

    • @paulkanja
      @paulkanja Před rokem

      just popped here to say if you have too many nests, then yeah, you are screwed,, also just a question for all other folk down here: branched/branchless?

    • @nonzz3ro
      @nonzz3ro Před rokem

      I agree, my eye was drawn to one of the blurred texts first, then I'd see the other blurred text, then I'd be able to focus on the code he was talking about.

    • @ArifBasri
      @ArifBasri Před rokem +1

      my brain were exercised well, but my eyes were straining hell

  • @sebobafett1652
    @sebobafett1652 Před rokem +292

    I've love the way that you animate code code changes. It makes it really easy to follow.
    I like the disgust-o-meter, it is often how I decide whether or not to request a change on a PR and now I've got a name for it.
    This was a nice way to advocate for the Single Responsibility Principle, better than the 7-line methods Bob preaches about.

    • @SixOThree
      @SixOThree Před rokem +3

      I very much wish Visual Studio had a smooth scroll; especially when navigating to definitions in the same file.

    • @papasmurf9146
      @papasmurf9146 Před rokem +2

      I've never heard of the "never nester" concept -- but take "single responsibility principle" very seriously. Just checked my code and it looks like never nester.

    • @dyanosis
      @dyanosis Před rokem +1

      I mean... not really. Single Responsibility is for classes, not methods. And while you COULD apply it to methods, it doesn't always work out as well as you think.
      However, it's much easier to enforce it with classes because classes should be performing 1 type of operation and be handing off other operations to other classes.

    • @papasmurf9146
      @papasmurf9146 Před rokem

      ​@@dyanosis You're right. I misused Single Responsibility here. It is supposed to be "this code is fulfilling one person requirements, and no one else's."
      I was looking at "this code should only do one thing and do it well." I suppose both principles have the number one in them, but they are very different.
      Good catch.

    • @IndellableHatesHandles
      @IndellableHatesHandles Před rokem

      On a PR?

  • @I.Carnivore
    @I.Carnivore Před 8 měsíci

    As a never-nester myself, I appreciate this video and the clear explanation. Subscribed.

  • @nicksrub
    @nicksrub Před měsícem +1

    I rewatch this video every few months to remind myself to do this. Thank you for making it so clear and simple

  • @ahmed.._.
    @ahmed.._. Před rokem +565

    As a comp sci student, I'm loving these videos! These topics aren't really talked about at my university, and the way you present them really makes me consider things from a different perspective. Keep it up! :)

    • @Lucas-hh4oh
      @Lucas-hh4oh Před rokem +15

      luckly my uni has one non mandatory class that talk about refactoring, pattern and code smells

    • @marcusrehn6915
      @marcusrehn6915 Před rokem +30

      Many university teachers have never worked in the real world, so they simply dont know

    • @ThePowerRanger
      @ThePowerRanger Před rokem

      Same

    • @christopherw1248
      @christopherw1248 Před rokem +1

      @@Lucas-hh4oh do you have a recommended public resource for that topics? appreciate it if you have something.

    • @sineme
      @sineme Před rokem +8

      @@christopherw1248 refactoring guru (website, I left the dot out just to be safe), SOLID-principles, object calisthenics are things worth looking into

  • @cc3
    @cc3 Před rokem +481

    The "validation gatekeeping section of the code" can be summarised as "guard clauses". We use it all the time, especially in the backend of our stack where requests must be validated. I didn't think I was a never nester before this video but I've got a bit of a problem with long line lengths so avoid unnecessary nesting if possible.

    • @lefran229
      @lefran229 Před rokem +12

      + also known as the “early return” pattern

    • @911muha
      @911muha Před rokem

      Dad d

    • @georgeyoung2684
      @georgeyoung2684 Před rokem +8

      I love how Swift has an actual ‘guard’ keyword, that makes it just like an if statement, but forces you to return as part of it

    • @markhollas7585
      @markhollas7585 Před rokem +4

      I have always called it "short circuiting". nice to learn other vernacular

    • @erichermann1962
      @erichermann1962 Před rokem +3

      To add to the "fail fast" concept, I will typically go a step further and put my guard clauses into a guard function, abstracting all the negative scenarios away.

  • @ajuc005
    @ajuc005 Před 6 měsíci +79

    In general I agree. I especially like early returns and splitting conditions/validation from operations. But sometimes nesting is better. For example when you have algorithm that is inherently nested (like you have 4 tight for loops indexing some arrays etc.). Better to have the whole looping/indexing in one function and extract the "doing" into another function than to extract part of looping to another function. Because it makes the algorithm less clear and if you do 4 loops with complex indexing you better be aware what you're doing.

    • @pizzapunt3960
      @pizzapunt3960 Před 6 měsíci +5

      I think the problem is that you wrote an algorithm that requires 4 loops.

    • @ajuc005
      @ajuc005 Před 6 měsíci +22

      @@pizzapunt3960 there are algorithms that inherently require 4 or more loops. Some faster versions of matrix multiplication for example. Or pathfinding.

    • @pizzapunt3960
      @pizzapunt3960 Před 6 měsíci +1

      @@ajuc005 they don't need nested loop. If you are using nested loops you're being slow. You need parallel processes (might be called differently, every programming language implements it differently). If you look at a* for example, doesn't require a single nested loop. It's not something inherent to the algorithm but to your lack of skill.

    • @cantthinkofaname1029
      @cantthinkofaname1029 Před 5 měsíci +15

      ​@pizzapunt3960 you are aware that some environments disallow multi threading, yes? Have you ever even heard of an MCU?

    • @BodomsScythe
      @BodomsScythe Před 5 měsíci +16

      @@cantthinkofaname1029 Who hasn't heard of the "Marvel Cinematic Universe", at this point? :P

  • @shanehebert396
    @shanehebert396 Před 7 měsíci +11

    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

  • @SJrad
    @SJrad Před rokem +605

    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.

    • @blazerorb
      @blazerorb Před rokem +36

      Skill issue lool
      (Skill of your IDE, that is, ayy)
      Even the VSCode basic C extension will show tooltips when you mouse over a function that show the signature and grab any preceding comments
      Rest of this is a stupid rant I wrote because I’m procrastinating studying, but I want to post it anyway. Sorry eh
      Also disclaimer, I’m new, and the fullest featured IDE I’ve used is IntelliJ for like 2 months
      I just think it’s kind of sad and ironic how much bending over backwards, or even thought at all, still has to be done in the name of readability, when this is literally how you create a UI. Like some people refuse to admit they’re bound by the same kinds eyes, hands, displays, and memories as someone doing anything else on a pc. Like anything beyond static, possibly colour coded text on solid background is some perversion. Like you should be able to just understand and hold the whole thing in your head, who needs eyes to know what code means?
      “What, a function reference that drops down when you hover or click to show you the definition? Comments being extracted and shown to the side or on hover or any other way than standard inline with the code? Shaded areas instead of a squiggly people can’t agree on because it wastes space wherever it’s put? Brackets that resize like you would on paper instead of alternating colours and fucking with the rest of the colour code? Any other idea you’ve had yourself for rendering the code window and then forgotten?”
      “Hell naw that’s for bitch-ass kids, I will continue to deal with the same basically-notepad limitations and inconveniences that my predecessors did. While I work on the dynamic UI for this CAD tool or map visualizer or browser game or whatever.”
      Like, is scratch not presented the way it is so that the reader can intake information visually, separate from encoding the information in text on the screen you have to read? Isn’t the readability issue one of us being limited in how easily or quickly we can understand the code on screen by reading the text, and wanting to increase it by being able to infer program behaviour or structure based on visual structure? Just feels like it sucks that in the age of OLED, VR, web frameworks, chatGPT, etc,
      some cool tabs can still be peak fkn technique

    • @litpath3633
      @litpath3633 Před rokem +1

      @@uusfiyeyh hmm interesting idea

    • @PaladinJenkis
      @PaladinJenkis Před rokem +21

      Not if your name it properly

    • @nik325007
      @nik325007 Před rokem +67

      It is very frustrating when trying to debug someone's code, you jump from one function to another, to another file, and then you realize that you are looking at the wrong section because the errors is in the previous step that you have to find what is calling that function and what is calling that function and so on. I come across this too often as a web debugger and mod creator, so thanks, i hate it

    • @PaladinJenkis
      @PaladinJenkis Před rokem +17

      @@nik325007 You can't expect engineers writing 8500 line long functions because you "code" in Notepad++.
      Ever heared of an IDE?

  • @the24throguecannon
    @the24throguecannon Před rokem +218

    The blur is really cool, but I think also including the more traditional background highlight rectangle is still helpful because it pops out more.
    (in other words, maybe it still looks cool using both techniques at the same time!)

    • @fabioneto03
      @fabioneto03 Před rokem

      I totally agree!

    • @vibaj16
      @vibaj16 Před rokem +3

      or just blur more

    • @blankRiot96
      @blankRiot96 Před rokem

      Agree on this one, the blur is slightly harder to follow for me

  • @thomasvnl
    @thomasvnl Před 8 měsíci

    The more elegant the code is, the better it reads, the more well understood the problem it needed to solve was by the developer(s) implementing it. I try to advocate this same guard-style "exit-early" behaviour when transferring knowledge to others, and try to avoid nesting as much as possible. You've conveyed the reasons very well and the example was in-depth enough for anyone to (be able to) see the light! Cheers.

  • @sidneyw.mathiasdeoliveira8621

    Exceptionally well done video. Even knowing almost nothing bout programing could get value out of it. Great animations and explanations, huge congrats

  • @tobene
    @tobene Před rokem +917

    Extraction should be done carefully. I've often seen code with lots of once-used & poorly named extracted functions, just to hide nesting. So the code is just as nested as before but you have to jump from function to function to understand whats going on.

    • @VeganSemihCyprus33
      @VeganSemihCyprus33 Před rokem +4

      Truth should be shared 👉 The Connections (2021) [short documentary] 👀

    • @nazeefahmadmeer
      @nazeefahmadmeer Před rokem +177

      I swear. What people don't realise is any added function is one extra layer of indirection. So only add a function if you have a good reason for it. I have seen people adding functions just for the sake of keeping method under a few lines

    • @Gloubichou
      @Gloubichou Před rokem +97

      @@nazeefahmadmeer I find that the right limit for extraction is when you start struggling to name the new functions. If it does not bear any meaning, then it probably does not deserve to be a function on its own. Also, respecting the single responsibility principle helps a lot (in the OOP paradigm, that is). If a class has too many methods, and you can't easily find your way around, it probably does too many things.

    • @MikkoRantalainen
      @MikkoRantalainen Před rokem +29

      The problem is not extraction but the poor naming. Yes, coming to with good names is sometimes hard but if you don't like doing that, maybe programming is not something you should do.

    • @ObjectsInMotion
      @ObjectsInMotion Před rokem +88

      Never extract something that’s only used once is my philosophy. A function needs to be called at minimum twice before it deserves defining. If it were up to me, thrice.

  • @kirlian5399
    @kirlian5399 Před rokem +670

    I used to be a never nester myself. Now I’m more of a it-depends-on-the-case nester. Does extracting code into a separate function make it easier to understand? Well, sometimes. Do early returns make it easier to focus on the actual core of the procedure? Again, not always. It’s good to know these techniques of extraction and inversion, but as everything else in programming, you shouldn’t use them just because you can.
    That said, the video is really well done! The animations make it easy to follow all the moving parts, and the explanation is clear and concise. Great work!

    • @ade8890
      @ade8890 Před rokem +22

      Could you elaborate? I would argue that if you can you should. Reading heavily nested code sucks balls. Reading code can take quite awhile for you to finally absorb what's going on, and minimizing nesting helps keep the high level logic in the foreground for the readers. Things like guard clauses just seem like good coding practices, up there with making sure you comment your code and try to use descriptive/accurate names for variables and functions.

    • @almicc
      @almicc Před rokem +55

      I said in my own comment, and that kinda answers Ade's question, so I'll repeat it here. It does depend, a lot. Sometimes, but not always, extracting code to a function can help, provided everything still remains in one file or one compact section of the file. I've had the unfortunate experience of trying to dig around programs and, in order to understand the full procedure, I end up clicking around to find the function declarations. This is the worst for triple or quadruple nested functions, where you basically have to scroll up and down constantly just to follow the flow of code. Nested code might be bad, but similar to reading a book, I'd rather stick to one or two continuous pages instead of bouncing around dozens of pages just to read a couple sentences here and there. My general rule is that it needs to be a big chunk of code to be it's own function, or so self descriptive and simple that you don't need to keep the implementation in mind. A good example of the big and small functions would be the big "handle http error" and "is even" in the video. However, sometimes I see functions that are two or three lines, and aren't so descriptive that you actually need to keep the implementation in mind everywhere you see it used. An example might be an error logging function, which depending on a boolean variable, may call another function that can affect the code going forward, like terminating the program or changing a variable being used. In that case, it would definitely be better to either split that function in two and just call what you need, or take the nested function call out and call it when needed. Or, best idea, don't use the function if it's only called in one place and just leave the code where it came from originally.

    • @almicc
      @almicc Před rokem +15

      @@ade8890 I definitely think guard clauses are the best way to go, and should be used whenever possible. I can't really think of a reason to not invert code like that. Worst cases, where there's a lot of clauses interspersed between big sections of code, adding a comment just before some part reminding you "Hey, the number cannot be 5 here anymore, that was covered above" is great. I've written code with over five clauses like this, with enough code between to push it out of view, so having those comments to remind me and others is very helpful. This does get a little hairy when you have multiple different variables being filtered, so instead of "number isn't 5 here" it'd be more like "the number isn't 5, the object is null, and this enum color is either RED or BLUE now." But still, that's where I write the comment stating that. Good IDEs also understand this in static analysis, so I sometimes use that to check myself by testing a variable, and pray the IDE tells me "that is always true/false here."

    • @kirlian5399
      @kirlian5399 Před rokem +20

      @@ade8890 For example, you know which parts of the code get executed when everything goes well simply by looking at the indentation. Having a single exit point is tidy and organized.
      Also, sometimes it’s difficult to give a name to a specific part of the code, so it’s better to leave it inlined without a name. A name that is unclear and/or inaccurate can make things worse than just plain inlined code.
      At least, this is what works for me. It’s how my mind thinks and processes information. But that might not be everyone’s case.

    • @ade8890
      @ade8890 Před rokem +2

      @@almicc " Sometimes, but not always, extracting code to a function can help, provided everything still remains in one file or one compact section of the file."
      Yeah I agree with this. You shouldn't extract code to a separate file if where you are extracting it is only ever used in one spot.
      " I've had the unfortunate experience of trying to dig around programs and, in order to understand the full procedure, I end up clicking around to find the function declarations."
      I'm not sure if I understand the issue here. Most IDEs allow you click into a function call to auto-navigate to the declaring section. And aslong as that function is only used once, you can click the function signature to be brought straight back into the calling body. This gives you the best of both worlds, where you can click into more specific logic that you need to understand, or you can jump back out and just focus on the high level details.

  • @wueijun
    @wueijun Před 6 měsíci +1

    I was taught this by my mentor in my first internship and honestly one of the most important foundations of my programming approach to date.

  • @LucaDelloSterpaio
    @LucaDelloSterpaio Před 8 měsíci +23

    Just here to say that the “inverted” (negated) condition of “top > bottom” at 2:21 is “top

    • @bodardr
      @bodardr Před 2 měsíci +1

      Do not, I repeat, never negate (!) numerical comparisons. This straight up harms readability.

  • @TheFrostFyr
    @TheFrostFyr Před rokem +230

    I've generally found people call the block of returns at the top of a function after inversion to be "Guard Clauses" I've always found them to make everything amazingly clear just like the content in your video shows and suggests.
    Keep up the good work, can't wait to see more.

    • @evancombs5159
      @evancombs5159 Před rokem +21

      This style of coding really should be what is taught, but a long time ago the idea that you should only return at the very end of a method was very popular. I'm sure there may have been a good technical reason back then, but it is an objectively worse way to code. Today we don't have a valid reason to stick with the only return once at the end dogma.

    • @Ashebrethafe
      @Ashebrethafe Před rokem +12

      @@evancombs5159 I think it's a misunderstanding of the "single entry, single exit" principle, which is actually something that object-oriented languages automatically enforce: that you should only enter a function or routine at one point (the top) and only exit _to_ one point (right after where you came from). Older languages like BASIC allowed you to jump to any line by using a command such as GOTO or GOSUB, or by changing the pointer stored by GOSUB to tell RETURN where to jump to -- so in the case of BASIC, the principle meant "don't use GOTO; use GOSUB only to jump to lines immediately after a GOSUB, RETURN or END; don't change the RETURN pointer; and RETURN from every GOSUB".
      The one thing it's still useful for is freeing allocated resources (which you have to do before any exit) -- but Java lets you use "try" and "finally" instead of duplicating that code, or allocate the resources in the opening statement of the "try" if they can be freed automatically when it's exited.

    • @jeffreysun7983
      @jeffreysun7983 Před rokem +1

      I've heard it referred to as a "gauntlet pattern." I swear by it.

    • @SI0AX
      @SI0AX Před rokem +4

      ​@@evancombs5159 In my company, I teach beginners the guard clause method because it makes a massive difference in readability. I tell them that else should never be used.

    • @jakemarquez3118
      @jakemarquez3118 Před rokem

      "Guard Clauses" that's a great name for it. Super great pattern, although I notice I implement a second tier of them within a nested scope if the right situation calls for it

  • @shubtakkorathinasapostle1159

    I didn't realize I was subconsciously a never nester but I thank my professors for subtly teaching me good practices

    • @ConnerTurmon
      @ConnerTurmon Před 8 měsíci +17

      Same! When writing graphics code I noticed that if there was some check I needed to do, like if the renderer initialized or not, I would return out of the function rather than nesting all the "happy code" inside passing checks. I didn't realize this was an actual concept lol, I just thought it made it way easier to read.

    • @BetaTester704
      @BetaTester704 Před 6 měsíci +3

      I taught myself programming from scratch, interestingly this is one one the things I figured out myself.

    • @simonvutov7575
      @simonvutov7575 Před 5 měsíci

      same!!

  • @verfran
    @verfran Před 8 měsíci +1

    my struggle has been to convince the team not to nest. This eases my struggle a lot. Thank you so much

  • @cybermist2
    @cybermist2 Před 3 měsíci

    I love the way you explain and visualise the code, love your videos, keep up simple 😊

  • @garethjacobsnz
    @garethjacobsnz Před rokem +210

    I'm an old school programmer that cut my teeth on COBOL and C. We were taught to only nest to 3 levels and use functions to simplify code. This is how I still program today nearly 40 years later and works well for modern scripting languages such as PowerShell which I use extensively.

    • @OpenGL4ever
      @OpenGL4ever Před 7 měsíci +8

      This is interesting. 40 years ago that was the time when compilers did not yet produce good code and every avoidable If condition and every function call was expensive and function inlining was also avoided because memory was also limited.
      In order to save computing time, it made sense not to outsource performance-hungry code to functions and to nest If conditions so that the code was as efficient as possible. A multiple nested if else construct was often more performant or meant fewer steps for the CPU than executing each IF query multiple times just so that you don't have to nest.
      How did you manage to nest on only 3 levels? Was a fast runtime speed not a requirement for the code? Did you have plenty of memory available?
      Today that may not be such a big deal, the compiler optimizes it all away anyway and inlines the functions again, but it just wasn't like that in the past.

    • @sillymesilly
      @sillymesilly Před 7 měsíci

      @@OpenGL4everingenuity

    • @dotti5060
      @dotti5060 Před 6 měsíci +1

      I go 2 levels. 3 only if absolutely necessary.

    • @autochton
      @autochton Před 6 měsíci +5

      @@OpenGL4ever 40 years ago was 1983, so not quite at the punch-cards age. 😉 Compilers didn't have quite the level of optimization they do now, of course -- four decades of improvement are a beautiful thing -- but they could handle function calls and conditionals to a reasonable degree in most languages I'm aware of. Of course, if you were writing highly-responsive or real-time code all bets were off, just like today, but for most purposes, human readable code was a goal then as now.

    • @OpenGL4ever
      @OpenGL4ever Před 6 měsíci

      @@autochton The Microsoft C compiler was improved a lot between the release of Windows NT 3.1 in 1993 and Windows NT 3.5 in 1994. That resulted in a big performance improvement of the newer Windows NT 3.5 solely because of the much better compiler.
      This was 10 years later than 1983. The C compilers in the 80s where still in its infancy.

  • @CodingwithGPT
    @CodingwithGPT Před 11 měsíci +346

    Dude I have been teaching CS for 10 years and honestly this is the best piece of communication on general best practices that I have ever seen

    • @xbzq
      @xbzq Před 4 měsíci +5

      What? Did you just say? What the what what? What was that? Did you say what? 10 years and this garbage is the best? And you... you teach? 10 years and you teach for 10 years and this garbage is the best you have ever seen and you teach.
      That is scary. I guess so your students must be hyper dense.
      Job security for me, I guess. No competition. Lol.
      10 years huh. And this is it.

    • @pixelgreen5837
      @pixelgreen5837 Před 3 měsíci

      ​@@xbzqCongratulations, you win the flexing competition, here's some internet validation

    • @RubixstewYT
      @RubixstewYT Před 3 měsíci +6

      ​@@xbzq brother is stuttering in text. There's no need to be scared

    • @soupman8165
      @soupman8165 Před 3 měsíci +3

      ​@@xbzq are you okay

    • @xbzq
      @xbzq Před 3 měsíci

      @@soupman8165 Why you ask

  • @2012TheAndromeda
    @2012TheAndromeda Před 7 měsíci

    The graphics are beautiful.. It very much helps see what's going on. The hows and whys as we are seeing whats happening is incredibly effective.. Thank you!!

  • @stuartferguson11
    @stuartferguson11 Před 8 měsíci +6

    One issue with extracting nested code into sub-functions is too many local variables that need to be passed by reference. When that happens I've had success turning the algorithm into a class. The shared variables are the class members which no longer clutter up the function signatures. It looks a little weird at first but the code is a lot more readable.

  • @biltongza
    @biltongza Před rokem +223

    The bit about mentally discarding the unhappy path is what I try to drive into my junior devs brains! Less stuff in working space of my brain = less stuff to think about = less stuff to go wrong. The mental model is so important! Very glad you mentioned this and I'll be sharing it :)

    • @guytech7310
      @guytech7310 Před rokem +10

      Not really the case, if you dividing your code into a lot of tiny functions it can make it difficult to read since you spend a lot of time scrolling around for all the functions called, plus if you modify several function & it breaks something, but scrolling around all those functions trying to determine which function is the culprit, and you still have to track it all in your head. Worse is when you use nested functions:
      function A() {
      if (x > y) {
      result = Function B(x,y);
      } //endof if (x> y);
      } //endof functionA
      Function B (x,y) {
      if (x == (y +1) ) {
      z = y +1;
      result = Function C(x,z);
      } //endof if (x == (y +1) )
      else
      result = Function D(x,y);
      } //endof Function B (x,y)
      All your doing to making it harder to read and debug. I would be much easier if all this was in Function A, and not have to jump arround all those functions trying to figure out the bug, especially if the functions are either in different source code files, or your source code file has thousands of lines of code and the functions are located far away from the main function.
      You can use comments to divide your code blocks into groups to make them more readable. Also add comments to all closing brackets to make it more readible\trackable. ie "} //end of if (x == y)" . Code your levels like a FIFO stack, so that for each level you add the closing bracket before inserting the first line of code in the new level.

    • @biltongza
      @biltongza Před rokem +17

      @@guytech7310 this is why we have tools that make it easier for us. Your comments on the ends of code blocks are handled automatically by modern IDEs showing you where braces are related, and you don't have to worry about changing functions and breaking stuff if you have unit tests. "But who has unit tests?" I hear you ask. You, because you didn't write your code to be testable in the first place. Or you inherited a codebase where someone else made that mistake for you. I don't know, I'm not your boss. The point is it's better to leave things better than you found them and this is one way of doing it.
      The gist of this all is, if I know that a certain function or piece of code works, I can *entirely* disregard it from my debugging process. Skip it entirely. Not even a thought is spared for it (unless it has side effects, in which case, you have bigger problems). I don't care about code jumping around because my debugger is handling it for me. If I have to have an entire god function's state in my brain's working memory, that's very taxing and slows me down. Too many possibilities and variables to keep track of. I'll let me brain do what it is good at: think of things logically one thing at a time. Break down the task into smaller chunks. Check my assumptions. "The result of this function should be x, and I got x, so my problem is not here" and I never need to remember that that code even exists. So I move on to the next thing. Keep doing that until a) I find something that doesn't match my assumptions or b) run out of assumptions, in which case, more often than not, the princess (bug) is in another castle.

    • @rahpat01
      @rahpat01 Před rokem +11

      ​@@guytech7310 what makes things hard to read is the inadequate naming. And unnecessary comments are a classic evil trying to compensate the lack of effort on finding expressive name for variables, functions, etc...

    • @davestorm6718
      @davestorm6718 Před rokem +9

      @@biltongza I program in C# and find so much relief that Visual Studio 2022 keeps track of darn near everything (how many references to any function anywhere, no matter if it's in another file, inside a dll, or what-have-you). Even deep nesting display is color coded and you can collapse code at any level (the best feature ever - though most IDEs have this) and keep it collapsed (not to mention, it's all customizable!). This plus intellisense, and keeping track of all external stuff, git, etc, makes programming a lot less stressful. This is the what ALL IDEs should be doing: keeping track of everything. Coming from a background of writing code on a text editor, devs today have no idea how good they have it!

    • @biltongza
      @biltongza Před rokem +4

      @@davestorm6718 precisely!!! Use the tools you have!!! They are there for a reason!

  • @TimTom
    @TimTom Před rokem +59

    I agree that indentation should be avoided when possible, and also that guard clauses are one good strategy to do that, but I think breaking your code into a ton a little functions makes it harder to follow what’s happening and makes it easier for bugs to slip in. John Carmack wrote a memo about this a while ago, look up “John Carmack on Inlined Code” to see a more thorough argument.
    Regardless, excellent video! Can’t wait to see more!

    • @cluelessdev3851
      @cluelessdev3851 Před rokem +12

      I totally agree, I found my self going up and down, up and down around some files because I had all these function calls... Not everything has to be a function, guard statements are often enough, and well designed code will rarely if ever go deeper than 3 levels w/o extracting into functions.

    • @coffeedude
      @coffeedude Před rokem +14

      If functions are well named and tested there shouldn't be problems with understanding code that uses them, in fact they can make it quite easier

    • @cluelessdev3851
      @cluelessdev3851 Před rokem +9

      ​@@coffeedude You do have a point! Nonetheless at least in my line of work that's rarely the case (I seem to eat spaggetti every day) and well I sometimes have a "nag" to see how a function operates if that makes sense?

    • @brawldude2656
      @brawldude2656 Před 6 měsíci +1

      @@coffeedudeI really love when I can tell what the code is doing in 10 seconds

    • @danny234555
      @danny234555 Před 3 měsíci

      I think it's a bit important to note that the kind of nesting you're talking about is mostly visual, and you're completely fine nesting to infinity as long as each function is only visually 3 deep.

  • @TonniTielens
    @TonniTielens Před 2 měsíci +1

    Great video. Just one remark related to the inversion example. The inversion of "top > bottom" is not "top < bottom", but "top

  • @ModusVivendiMedia
    @ModusVivendiMedia Před 8 měsíci +3

    OMG I just actually had a bit of nostalgia for programming. I never thought I'd miss it but somehow this video gave me that feeling. But I agree with this, I've definitely nested way too much but I've also done a lot of extraction, too, and maybe some inversion but without always understanding that it was a recognized technique to fix the nesting problem (ie, I'd use it more now, on purpose).

  • @Accelerando_poco
    @Accelerando_poco Před rokem +150

    I'm all for extracting code into functions as long as these functions are given names which clearly convey what they do. If they are not named properly, I would rather have the code written out explicitly than having to jump though the functions in order to find out what it is actually supposed to do. If one finds the process of naming the functions difficult, it might be a strong indication that the block of code should be extracted in a different way - perhaps it is better to extract the code into two different functions rather than one, or perhaps the rest of the code needs to be sorted out first. Too many times, I see developers hastly jump to the conclusion that "extraction == good" while forgetting the larger goal at hand, which is to improve readability.

    • @jakubjakubowski944
      @jakubjakubowski944 Před rokem +29

      Exacly. The problem with multi-nesting is that you have to understand a lot of code at once while also making big chunks obfuscating flow of code. If we have one very short (thus not obfuscating) nest then replacing it with badly named function actually makes problem WORSE because it forces reader to jump over multiple places to process one procedure.
      Obvious solution is to name stuff descriptively, but naming is hard sometimes. There is no golden bullet.

    • @MrTrilbe
      @MrTrilbe Před rokem +17

      Also comments and documentation helps, I know not everyone likes commenting and likes self descriptive code and not everyone thinks documentation even exists, but sometimes a short sentence of intent helps, even if it's in the reference code and not in the compiled code or the documentation.

    • @NotExplosive
      @NotExplosive Před rokem +4

      Sometimes I need to extract first in order to figure out the name. I'll extract a function and give it a temporary nonsense name like "Banana." Then see how the function is used, what goes in, and what comes out. From that I discover a name and I rename Banana to the name it ought to have had all along.
      If the name is long-winded and complicated, that's a hint that I need to extract it further, or perhaps I extracted the wrong thing.

    • @MrTrilbe
      @MrTrilbe Před rokem +20

      @@NotExplosive 3 weeks and 10 projects later "WTF is 'banana?' " lol

    • @jbird4478
      @jbird4478 Před rokem +18

      And that is a problem you do run into when applying this too much. You'll get a lot of small functions for which it's sometimes damn near impossible to think of a sensible name. Sometimes just keeping the nesting is a fine solution as well; and add a comment if it's somewhat unclear.

  • @jj-big-slay-yo
    @jj-big-slay-yo Před rokem +222

    I think this happy path / sad path disctinction is also called a "guard" clause - in which you guard the important part of a function with the guard(s) that are checking for invalid conditions and then bounce if the conditions are not ok before ever reaching the important parts.

    • @dahlola
      @dahlola Před rokem +2

      Yep. I recently started programming in Swift and there "guard" is an actual keyword. I have been doing much more "happy path" programming before but will refactor some of the code I done in Kotlin.

    • @zackyezek3760
      @zackyezek3760 Před rokem +9

      Guard clauses aren’t “never nest”.
      Guards simply mean you simply have a flat set of “if” validation checks on your inputs (and error handling) before you start using them in the function’s business logic. In effect you’re writing all your functions like they were main(), weeding out as many error conditions as possible as early as possible.
      This is a good design pattern that has nothing to do with obsessively avoiding nested logic. It simply eliminates many wasteful and unnecessary layers of nesting by doing error checks in sequence (with error returns). There are times where 5-6 or even more layers of nesting is perfectly good, efficient code for the business logic. Especially if you’re doing something functional, like creating several layers of nested objects in one statement, where indenting the nested calls on new lines makes the code way MORE readable.

    • @JamesBalazs
      @JamesBalazs Před rokem +7

      ​​​@@zackyezek3760 100% agreed, the thing these videos often ignore is that you have to apply common sense, logic, and your own experience to decide whether to nest or not, whether to split something out into a function, whether to chain calls on the same line, or split it up. Etc etc.
      Obsessively applying some arbitrarily rule to all situations results in code that is consistent, but often consistently wrong. You have to both consider what you gain by making a certain style choice, and the disadvantages as well. Normally readability, performance, and maintainability (ease of making changes in the future) will fall on one side or the other, and you have to compromise. But always prioritising readability at the expense of all other factors is often the wrong choice.

    • @Whitecroc
      @Whitecroc Před 11 měsíci +1

      I like to think of them as getting rid of the boring stuff beforehand so I can focus on the stuff that actually matters.

  • @stopitnowlol6697
    @stopitnowlol6697 Před 8 měsíci +1

    I'm writing a program right now, i realised how messy it was so i started to extract sections of functions that can be removed and put them into separate files that describe what is happening within such as "call API" or "parse data", it's made the code much easier to understand.

  • @ninodolo
    @ninodolo Před 8 měsíci +1

    This is how I refactor but have never been able to articulate my process as well as this. Impressive job!

  • @CoolAsFreya
    @CoolAsFreya Před rokem +121

    Whilst I'll probably never be a strict never-neater this video has certainly helped me consider some ways to make my code more readable!

    • @VeganSemihCyprus33
      @VeganSemihCyprus33 Před rokem

      Truth should be shared 👉 The Connections (2021) [short documentary] 👀

    • @AlexRenfro-ux8th
      @AlexRenfro-ux8th Před rokem +1

      unreadable code is job security, mate 😄

  • @udadni
    @udadni Před 11 měsíci +21

    I'm a new C# programmer doing hobby game design in Unity. I am so glad I got introduced to some of these ideas early in my programming journey, mainly inversion using the term "guard clauses". It's so nice now that I have a little more experience to see this elegant dive a little deeper into the topic. Thanks for the great material!

  • @Anton_Sh.
    @Anton_Sh. Před 8 měsíci +1

    I sometimes like having nested code, even if it's not necessary, when there is some straightforward and not very big problem to be solved. So, having a solid "brick-like" solution for it makes it seem simple and raw reflecting such nature of the problem itself.

  • @pkozelka
    @pkozelka Před 5 měsíci

    Very well presented, thanks for the great work. Also, it's refreshing too see someone else is also thinking this way about code.

  • @SrFrancia0
    @SrFrancia0 Před rokem +33

    YES! when multiple if statements are nested I feel like I need to keep it in mind it's a nightmare. I've always been a never nester without knowing. Great video!

  • @mike200017
    @mike200017 Před rokem +167

    I would consider myself a "never nester" too, but I can also recognize that there are drawbacks to it that might be good to point out, with some tips to avoid them.
    1) The inverted conditions can sometimes be less obvious, especially if there are some logical operators (and, or, not) that can be hard to invert correctly or understand afterwards. I think a good mitigation for that is to avoid compound conditions by either splitting up individual conditions, i.e., instead of "if any of these conditions are not met, return early", itemize each condition with its own early return, which also encourages more helpful error codes or exceptions, or putting the compound condition in a function with a good name.
    2) Although putting all the error conditions up front cleans up the "good path" below, it can also put distance between checking for a problem and the code that would fail. So, either you can't understand the check before you see the code that needs it or you can't remember that the check was already done by the time you read the code below. The way to remedy this is typically to decompose into smaller functions (e.g., instead of 20 checks up front, and 5 chunks of "good path" code below, you split into 5 functions, each having around 4 checks up front).
    3) In a similar vein of scoping issues, decomposing into many functions can encourage broadening the scope of code and variables. This is especially common with object oriented code when decomposing member functions (aka methods). It's easy to create new "decomposed" functions that are not self-contained, i.e., they take in and/or return variables or (self-)objects in a state where they are in the middle of some broader processing (the parent function), and invariants are temporarily invalid. That can be error-prone in future changes or additions to the code. It's also easy to make what should just be local variables of the parent function into member variables of the class or (God help us) global variables to avoid having to pass them in and out of the child function. And finally, it's easy to overly expose functions that are really just implementation details. Avoiding this just takes discipline to minimize the scope of variables and functions as much as possible.
    4) Another obvious issue is that splitting up code into many single-use functions, and often, for other practical considerations, having to scatter them in different places in the code, does create readability problems due to having to jump around, and also because it can be hard to name functions that don't have a well-defined purpose outside of that one call-site. This can sometimes be mitigated by using "local" functions (or closures, or lambdas, or whatever, they go by many different names). A relatively common pattern you see is a bunch of checks up front, then some helper functions defined (typically closures or lambdas), and finally the main "good path".

    • @raducuvlad2187
      @raducuvlad2187 Před rokem +5

      This is exactly what I was thinking, also referencing "A philosophy of software design" about deep and shallow classes/modules

    • @nuckm
      @nuckm Před rokem +5

      @@raducuvlad2187 Best book in the universe for any programmer EVER, it is a must read. In my opinion a lot of these nesting issues aren't so bad when you add a lot more comments to the code, which all of these examples is lacking

    • @nuckm
      @nuckm Před rokem +11

      Also if you deconstruct into a bunch of small methods, that makes it harder to understand in a different manner because it obscures the real functionality. "clearDownloads" doesn't mean anything at all, it's the code inside you need. Don't break up the code into many small functions especially if it's only gonna be used in that one place

    • @youcefnafa2267
      @youcefnafa2267 Před rokem +1

      In addition to your 2nd point. I noticed putting checks upfront goes against the paradigm of try now fail later. Instead of checking whether a file exists, just try to read it and throw your exception (try-catch blocks). The nesting needed is just one level if the language allows multiple catch blocks per try block.

    • @youcefnafa2267
      @youcefnafa2267 Před rokem +4

      @@nuckm CZcams recommended another video from the same channel, titled "don't write comments". Now I feel like I gotta watch it

  • @Eddygeek18
    @Eddygeek18 Před 8 měsíci

    I didn't even realise i was a never nester, i'm always inverting if statesments for early exits and when i get code too nested i'll move it to it's own function to make it easier to read. Great video

  • @robgoffroad
    @robgoffroad Před 8 měsíci +3

    I fall into the Never Nester bucket. If I need to nest further, I have to stop and think about how I can simplify it, as you have described. It's a shame more people don't do this. My specialty (I get a lot of jobs because of this) is legacy apps. I'm good at digging into old, usually poorly-written apps, fixing them, migrating them, etc, etc.

  • @wtcxdm
    @wtcxdm Před rokem +93

    Thanks for the high quality video as always!
    A little suggestion though, instead of blurring other lines, how about highlighting the lines viewers should focus on? It will be easier for eyes on mobile.

    • @CodeAesthetic
      @CodeAesthetic  Před rokem +45

      Thanks for the feedback. I'll play around with some options for the next one and make sure it comes through well on mobile

    • @arturpendrag0n270
      @arturpendrag0n270 Před rokem +6

      @@CodeAesthetic Just blur + grayscale that way you will leave the code you need focus on colored while the rest would be discoloured

    • @reisaki18
      @reisaki18 Před rokem

      @@CodeAesthetic you can use this style. czcams.com/video/6-mk6OpcUdM/video.html

  • @shugyosha7924
    @shugyosha7924 Před rokem +172

    One other positive to this approach is that because you extract pieces of logic into functions, you can give them a function name that describes the logic. This alone goes a long way to making your code more immediately comprehensible.

    • @akulkis
      @akulkis Před 9 měsíci +8

      Sometimes this makes sense. And sometimes it doesn't.
      Also, every function call has significant overhead: Saving the execution frame of the calling function onto the stack, and then throwing all those values onto the stack for the function being called... then when returning, restoring the execution frame from the stack to resume the calling function. Do that inside a loop, and the execution overhead can be ENORMOUS.
      That's this being a hard and fast rule that should never be violated is retarded.
      And let's not forget how much nesting of decisions structures there can be in an interrupt handler. Putting a function call INSIDE an interrupt handler is equally retarded, because interrupt handlers should be as fast as possible. If you can't understand the code, then you're not commenting enough.

    • @shugyosha7924
      @shugyosha7924 Před 9 měsíci +11

      @@akulkis "that should never be violated" → As they say, never say never. In art and engineering I think rules are more like best practices that you have to learn first before you understand when to break them.
      In a lot of cases, I think readability (i.e. maintainability) is more valuable than cutting edge performance. If performance is an issue there are likely algorithmic changes you can make before changing whether something is extracted out into a function or not.
      About comments, I'm personally persuaded by the idea that the code should be as readable as possible without comments. I.e., if the code requires comments, that's a sign that maybe the code is getting quite complex. Sometimes that's unavoidable, but a lot of times it isn't.
      It would be one thing if comments were free but they're not: they require diligent upkeep or else they're liable to confuse rather than help. Learning a good balance between code readability and commenting is just another skill acquired on the journey of becoming a somewhat competent developer.

    • @tkg__
      @tkg__ Před 8 měsíci +4

      @@akulkis most compilers inline functions and even inline loops anyway.

    • @akulkis
      @akulkis Před 8 měsíci +1

      @@shugyosha7924
      "that should never be violated" → As they say, never say never. In art and engineering I think rules are more like best practices that you have to learn first before you understand when to break them.
      -- that's why I wrote that saying it's a hard and fast rule is retarded.

    • @akulkis
      @akulkis Před 8 měsíci

      @@shugyosha7924
      "About comments, I'm personally persuaded by the idea that the code should be as readable as possible without comments. I.e., if the code requires comments, that's a sign that maybe the code is getting quite complex. Sometimes that's unavoidable, but a lot of times it isn't."
      The GREATEST thing that learning to program in various assembly languages is this:
      1. Write the comments for the function BEFORE writing the function itself.
      A. You are creating a "mission statement" for that function
      B. You are going to describe the strategy used to go about solving whatever that function is supposed to use.
      C. If you can't describe the algorithm(s) in plain old everyday language, there's literally no way that you're going to write it in code correctly.
      Too many programmers treat commenting as an afterthought. In assembly language, you literally can't get away with that. You're going to comment before you code, and then do more commenting while you code. ... every single line.
      I haven't written anything in assembly in decades, but those habits described above have always garnered heartfelt appreciation from others who have had to read and/or modify what I wrote.
      Remember this: "Self documenting code" is a myth. Yes, use meaningful variable names, but believe me, what one person thinks is clearly readable without comments will leave someone else scratching their heads. Suppose you have a for loop in C/C++, and for whatever reason, you do this
      loop_variable += skip;
      If you're not commenting SOMEWHERE (I would suggest both before the loop AND next to that line) why you're screwing with the loop control variable, SOMEONE is going to be confused, and chances are, you aren't going to be around to explain it. Or its' 20 years later, and your thinking and problem solving style has changed so much that you literally cannot understand why you yourself wrote something like that.
      I've never seen source-code with too many comments. I've seen source-code with lots of comments that are unnecessary because they tell you what the code itself tells you:
      int counter; /* counter is an integer */
      But that's a different problem -- it's just being redundant. Comments should generally focus on answering the question: "WHY? " and occasionally on "How?" (comment blocks for functions, and generally longer for loops and long if statements and long assignment statements ( x = LOTS of factors and terms)) and occasionally WHAT (data structure declarations)
      And remember, the more CLEVER your code, the more comments you need so that someone can understand what you're thinking without you being there to answer their questions.
      Compiler writers added commenting ability for a reason. If it were simply a matter of teaching "write self-documenting code" then we wouldn't need comments. But the fact of the matter is, a good portion of code is NOT self-documenting, and for most programmers, it's a FAR larger proportion of their own code than what they think.

  • @Peter_1986
    @Peter_1986 Před 9 měsíci +1

    Finally someone other than me who writes both of the curly brackets far to the left, in the same column;
    I always thought that it looked horrible when the left curly bracket was written at the end of a line, or written in other asymmetrical ways.

  • @JasonJBrunet
    @JasonJBrunet Před 4 měsíci +1

    I learned all my coding ways from the company I work for who hired me with zero experience. This video changed my life, and we are currently working towards implementing this on projects going forward.

  • @NeonFraction
    @NeonFraction Před rokem +375

    I’m mostly a self-taught coder so videos like this are invaluable. Thank you so much! 😊

    • @GOTHICforLIFE1
      @GOTHICforLIFE1 Před rokem +34

      You'd be surprised how little attention stuff like nesting, single responsibility functions, etc. are taught at university / college. You will be very lucky if you have a programmer that actually appreciates that as well as good logic and on top of that is your/a teacher.
      I've found that your best option is to find several sources of people that have a lot of experience and tailor to expert/intermediate audiences (even if you are not). That's where you start learning about design principles, abstraction, nesting, composition etc. I'm a python developer myself, and i can tell you that what i got prepared with from uni vs what i met when i started working is vastly different. Was lucky enough to find a channel called ArjanCodes which is exactly the type of channel i'm referring to when it comes to enhancing your coding levels. They help you pick up good habits early on and keep you on the right path of good practices

    • @ritchi465
      @ritchi465 Před rokem

      @@GOTHICforLIFE1 I was about to point out the same things. Uni just gives you the basics of programming. Learning about coding best practices enhances your programmer level to another level.

    • @thunder____
      @thunder____ Před rokem +1

      @@GOTHICforLIFE1 mCoding is another good channel focused on intermediate/advanced programmers (particularly Python and C++ devs), but I particularly want to mention Corey Schafer, especially as he just posted a new video after like a couple years off; I've found that Corey's channel does a great job of at least mentioning more advanced concepts while keeping the videos very accessible and beginner-oriented. I believe his videos are almost all about Python though, but for anyone learning Python, I highly recommend Corey Schafer's channel, and for anyone new to programming who's starting off with a language other than Python, I highly recommend switching to Python (at least while you're learning the basics of programming) and also Corey Schafer's channel.

    • @T1Oracle
      @T1Oracle Před rokem

      I was self taught, but I also kept reading to make up for it. This was eons ago, so books are less popular now, but The Pragmatic Programmer and Code Complete have timeless wisdom. Then there's the "Gang of Four" Design Patterns book. After that I would suggest learning SOLID design principles.

    • @gladwinj3389
      @gladwinj3389 Před rokem

      @@T1Oracle ty for that

  • @tjeerdbakker160
    @tjeerdbakker160 Před rokem +17

    These videos are great! I'm really loving this style of explaining, and there is a serious lack of content that explains project structure and general programming philosophies, so you've hit a bullseye! I wouldn't be surprised if you're at a million subs in a few years

  • @Fiascopia
    @Fiascopia Před 6 měsíci +1

    Hearing someone talking about coding like this is amazing. Finally having people say the things that I have tried to grapple with but don't really have the experience to say definitively which way is better. I like breaking things down into smaller functions so that every part is digestable and the whole code reads better but I always thought that just made me stupid :D

  • @clandsem3629
    @clandsem3629 Před 3 měsíci

    As some who is new I glad that you reinforced and made clear what I was almost doing in the first place. I feel like I was doing some of this without the validation that it was a good idea.

  • @fexofenadinaGenerica
    @fexofenadinaGenerica Před rokem +26

    I'm glad I found this channel. It's so pleasing to see the code being organized. Keep up the great work!

  • @anarelle
    @anarelle Před rokem +3

    This video is amazing. Not only for its contents but also the way information is presented. The animations, the simplicity, the narration at the perfect speed and with the perfect voice tone... Congrats!

  • @edwardmurphy440
    @edwardmurphy440 Před 9 měsíci +1

    It is worth noting that putting the happy path first is often more intuitive. This video is a good example; the inversion in this example is incorrect. if (top > bottom) is the happy case, then it is not inverted if (top < bottom); it is inverted by (top

  • @x0myspace0x
    @x0myspace0x Před 6 měsíci +1

    I wholeheartedly agree that keeping track of deeply nested code logic is overwhelming. I've been using these techniques you've shown in your video for a long time and I started doing it because I found it annoying to read through my own code, so I figured out how to make it more readable by moving things around and breaking up parts of code into separate functions.

  • @timecubed
    @timecubed Před 9 měsíci +10

    This video is a really helpful one. I have recently started trying out rust as my main programming language and although it's basically all I've ever wanted, its syntax and how it's written can quickly turn any app into a big mess, and these techniques really helped in making my rust code more readable. Stuff like the extraction method help with fixing some of the messy syntax and hiding it away somewhere else so that your main function that does all the work looks cleaner and more concise. I will say though, writing code while making sure that it doesn't nest more than 4 layers deep is quite hard, and I usually go with a "make a messy function that does a bunch of stuff first, then denest it" type of approach. Great video!

  • @arjunmehta2853
    @arjunmehta2853 Před 11 měsíci +38

    I used to do a ton of nesting when I was a beginner, but as I invested more time, I automatically learnt better methods of writing code by watching tutorials and reading documentations, and also got used to them, its great to know that I have improved over the years and already use good practices without actively trying to.

  • @ulhaqanwaar1
    @ulhaqanwaar1 Před 8 měsíci +1

    Finally something I can show my colleagues of where I'm struggling exactly with their code.

  • @johnphamlore8073
    @johnphamlore8073 Před 8 měsíci

    This is one of the most useful practical programming videos I have ever seen, and the irony is I am somewhat familiar with Linux kernel coding. Also the Linux kernel uses goto's to structure cleaning up functions.

  • @thomascorbin5371
    @thomascorbin5371 Před rokem +3

    Beautifully presented. I love that you end up with smaller, more concise, more focused functions. This is what Ive been doing for 20 years.

  • @dune2themaker
    @dune2themaker Před rokem +6

    I do this all the time , glad to see someone put it into words and make it so visual. Awesome work!

  • @djtreston
    @djtreston Před 8 měsíci

    I learn this years ago and it made my code so much easier to read and to program as well :D

  • @brian1204
    @brian1204 Před 6 měsíci +1

    I’m beginning to appreciate this. I once held the belief that each function should have just one return/exit. I don’t even remember why; I think I read it somewhere/somewhen? It makes for some complex nesting and code paths!

  • @dankosek4274
    @dankosek4274 Před rokem +4

    Thank you for this explanation of never nesting. It help this beginner see some very bad habits I was creating. The exciting part for me was seeing you refactor via inversion, moving all the conditions and pre-qualifiers to the beginning of the code block and grouping the actual functional code after that… begin able to examine a block of code after putting down all the initial tests and rules will really help me a lot. I am always trying to do something way beyond my capabilities, so this should bring huge benefits to me. Thanks again.

  • @Volatuhl
    @Volatuhl Před rokem +8

    This is already an incredibly high quality channel, please keep it up!

  • @stefanoriffaldi84
    @stefanoriffaldi84 Před 8 měsíci

    mind-blowing. you totally change my approach ... thanks man !

  • @pedroleandrocampossilva2409
    @pedroleandrocampossilva2409 Před 5 měsíci

    This is crucial for people looking for improvement on the basics. Great video!

  • @camelCase60
    @camelCase60 Před rokem +61

    You’ve managed to articulate a code style I’ve stuck with for years far better than I can!
    Regarding your last example with the download queue, you could also point out that it’s much easier to unit test the de-nested code compared to the big block

    • @pierreturpin2901
      @pierreturpin2901 Před rokem

      Actually, on the video sample, it doesn't change much the testing strategy.
      When testing, you want to target an unit which has a functional meaning, with scenario that makes sense. Generally, it is testing public actuators, controlled by public state, and asserted on public observable.
      For instance, with the download sample, one would really want that given some recoverable http error, then the execution is retried many times until a failure state.
      The handleHttpError method, or all other internal extracted methods are not testable as they don't have any particular functionality.

  • @vabondarenko
    @vabondarenko Před rokem +3

    Man, that's amazing. I will use it to train my team. Please continue. I was doing the same on my trainings, now i can just include your video in our code guidelines :)

  • @simon6435
    @simon6435 Před 6 měsíci +1

    I once nested 7 or 8 layers deep in a low code environment and it basically made it impossible for me to go back in and edit it because it took several minutes to open the nests and would occasionally just randomly minimise stuff while I was working, lol. This video was very helpful, thank you. PS that spacing actually made the code so much more readable for my eyes

  • @aldairacosta4393
    @aldairacosta4393 Před 8 měsíci

    This video make my eyes wide open in some many things about my coding style. Thank u very much

  • @redditor17
    @redditor17 Před rokem +5

    you've got some of the highest quality easily digestable programming videos out there dude! Keep it up ^-^

  • @bytekast
    @bytekast Před rokem +3

    I liked that video and that coding style too. It is aligned to some good practices as far as I'm concerned. I liked the fact that the base error case is put first in a function and that relatively long chunks of code are put into separate logical units. I think it really helps to increase code organization and logic, and thus readability!

  • @TheJanstyler
    @TheJanstyler Před 8 měsíci +1

    I've just started watching CS50 and it seems like this is exactly what David Malan meant when he talked about "abstraction".
    It looks so much neater and tidier than all those deeply nested pits of hell. I'll try to learn coding just like you've shown from the start.

  • @jomama55ful
    @jomama55ful Před 6 měsíci +1

    Towards the end of the video, he mentioned Single Responsibility. The S in SOLID principles. This one practice helps so much to make code easier to read, understand and troubleshoot. I teach this very early on in my high school programming classes and show examples of how it helps to make things easier. I also teach the use of guard clauses to put the conditions first and the work last. all these techniques promote less nesting. I'm also a never nester. :D

  • @IterativeTheoryRocks
    @IterativeTheoryRocks Před rokem +386

    I remember working with an ‘ever nester’ once.
    Rapidly scrolling down his code, there were large gaps between function definitions.
    Weird, I thought.
    Scrolling to one of the gaps, then scrolling to the right, I found the missing code. It was nested so far it had disappeared off the right hand side of the screen!

  • @Fidooop
    @Fidooop Před rokem +7

    Wow, you just opened my mind to the realization that I too have always been a never nester. I never thought of it this way, and I never had a disgust-o-meter for function depth, but I do extractions and inversions ALL the time to minimize the length of functions and to keep everything easy to read.

  • @andrewcgs
    @andrewcgs Před 7 měsíci

    I always do this and I never noticed before! Thanks!

  • @TheBusttheboss
    @TheBusttheboss Před 6 měsíci

    This is an awesome video. I will make sure to implement this from now on.

  • @RaineAvina
    @RaineAvina Před rokem +28

    This also gets into the idea of testability. If you have a lot of small functions like you do in your last example, it's easier to write a test case to verify each public API that you split out in isolation.

    • @jankrynicky
      @jankrynicky Před rokem +1

      Unless you are so obsessed with never ever nesting that you end up with way too many functions.
      Most of them called from exactly one place.

    • @peterbonnema8913
      @peterbonnema8913 Před rokem +2

      Wouldn't the extracted functions be private and therefore untestable?
      And no, you shouldn't then make them public instead just so you can test. That would be very bad.

    • @jankrynicky
      @jankrynicky Před rokem +1

      @@peterbonnema8913 They would be private, hopefully, but they'd still have to be named and kept in something resembling an order and you'd still have to jump to and fro while reading the code, just because someone couldn't bear one more level of curlies of a one line loop.
      Yeah, do not overnest! I can't agree more, but the limit is both too harsh and too low.

    • @peterbonnema8913
      @peterbonnema8913 Před rokem +2

      @@jankrynicky you misunderstood. I meant that extracting out functions doesn't mean you can test them separately because they are private.

  • @sebikusik
    @sebikusik Před rokem +216

    Now in my work I'm reviewing some code and excessive extraction is my number #1 obstacle. To verify how some simpliest things are calculated I need to constantly jump across different sections of the code, often having to look for them in various files. It results in having much more to remember in the code, because not only you still need to keep those additional conditions in mind, now there's another matter on whether there are no type conflicts, whether the functions work together, because it's pain in the ass to debug if every function works on it's own, but they don't work together when you run the whole thing.

    • @jonathanellwood2093
      @jonathanellwood2093 Před rokem +30

      Personally for me, I find the extraction to be significantly easier after everything is written. Sure, when starting out, you may end up 4 or 5 deep, but once you have it working, I think refactoring to avoid excessive nesting makes the most sense at least for me

    • @imblackmagic1209
      @imblackmagic1209 Před rokem +11

      I've seen some code with excessive extraction and poor naming, enough said i had to rewrite it all... i didnt even surpass nesting 3...

    • @madpuppet666
      @madpuppet666 Před rokem +36

      I'm not a fan of single use extraction, but also not a fan of deep nesting, so its a constant balancing act.

    • @madpuppet666
      @madpuppet666 Před rokem +6

      probably the main single use extraction I like is to represent proessing that only happens in specific states... ie. a finite state machine.

    • @TheEmolano
      @TheEmolano Před rokem +8

      @@jonathanellwood2093 that's good thinking, it's the same as premature optimization, doing it will usually do more harm than good

  • @waffle8364
    @waffle8364 Před 8 měsíci

    It also makes testing much easier and you can isolate different pieces and paths

  • @MarcLeatham
    @MarcLeatham Před 8 měsíci

    It's like any recipe! They start with a list of ingredients and amounts, and your mind can anticipate those flavors as you go through the ingredients. Then the main section shows the steps and logic for how all those ingredients are brought together.