Why You Shouldn't Nest Your Code

แชร์
ฝัง
  • เผยแพร่เมื่อ 5 ธ.ค. 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"

ความคิดเห็น • 6K

  • @tristanneal9552
    @tristanneal9552 ปีที่แล้ว +5993

    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 ปีที่แล้ว +275

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

    • @christianschmid1440
      @christianschmid1440 ปีที่แล้ว +55

      Welcome. It's good to have you back!

    • @BiP00
      @BiP00 ปีที่แล้ว +88

      Perhaps the dream became your reality.

    • @voster77hh
      @voster77hh ปีที่แล้ว +24

      it's a learning process. We all start there

    • @maurobrandolt2166
      @maurobrandolt2166 ปีที่แล้ว +9

      LMFAO

  • @PrimerBlobs
    @PrimerBlobs ปีที่แล้ว +7104

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

    • @tomzitiger
      @tomzitiger ปีที่แล้ว +102

      Primer! ❤

    • @linebreaker8751
      @linebreaker8751 ปีที่แล้ว +117

      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 ปีที่แล้ว +9

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

    • @thiagoassisfernandes
      @thiagoassisfernandes ปีที่แล้ว +1

      and easier to test

    • @voster77hh
      @voster77hh ปีที่แล้ว +4

      It's a learning process. We all start there

  • @aleceastman
    @aleceastman 5 หลายเดือนก่อน +710

    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 3 หลายเดือนก่อน +32

      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 3 หลายเดือนก่อน +2

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

    • @greyrifterrellik5837
      @greyrifterrellik5837 2 หลายเดือนก่อน +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 2 หลายเดือนก่อน +1

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

    • @greyrifterrellik5837
      @greyrifterrellik5837 2 หลายเดือนก่อน

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

  • @Komil484
    @Komil484 5 หลายเดือนก่อน +447

    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 5 หลายเดือนก่อน +87

      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 5 หลายเดือนก่อน +6

      spot on 😲

    • @jakosvet
      @jakosvet 5 หลายเดือนก่อน +62

      Inverted > is =

    • @VeritasGames
      @VeritasGames 5 หลายเดือนก่อน +36

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

    • @bryantwalley
      @bryantwalley 4 หลายเดือนก่อน +2

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

  • @CodeAesthetic
    @CodeAesthetic  ปีที่แล้ว +2568

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

    • @Handlessuck1
      @Handlessuck1 ปีที่แล้ว +32

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

    • @lonkwuzhere4433
      @lonkwuzhere4433 ปีที่แล้ว +53

      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 ปีที่แล้ว +6

      Posted the same prior to reading this. Deleted mine.

    • @malloc7367
      @malloc7367 ปีที่แล้ว +13

      My day was ruined until I read this.

    • @SixOThree
      @SixOThree ปีที่แล้ว +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 ปีที่แล้ว +6230

    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 ปีที่แล้ว +579

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

    • @LordBeef
      @LordBeef ปีที่แล้ว +42

      Same for me

    • @dirkniblickable
      @dirkniblickable ปีที่แล้ว +121

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

    • @ChrisAthanas
      @ChrisAthanas ปีที่แล้ว +6

      Yes please

    • @mohammadazad8350
      @mohammadazad8350 ปีที่แล้ว +76

      A highlighting rectangle will help too

  • @toddbarton1049
    @toddbarton1049 8 หลายเดือนก่อน +192

    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 5 หลายเดือนก่อน +27

      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 4 หลายเดือนก่อน +11

      "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 4 หลายเดือนก่อน +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 3 หลายเดือนก่อน +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 3 หลายเดือนก่อน +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"

  • @kilianbalter
    @kilianbalter 5 หลายเดือนก่อน +111

    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 4 หลายเดือนก่อน +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 3 หลายเดือนก่อน +12

      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 3 หลายเดือนก่อน +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 3 หลายเดือนก่อน +6

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

    • @ccampau
      @ccampau 3 หลายเดือนก่อน +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.

  • @johnheaney3349
    @johnheaney3349 ปีที่แล้ว +1194

    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 ปีที่แล้ว +94

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

    • @jebwatson
      @jebwatson ปีที่แล้ว +31

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

    • @idselseno2306
      @idselseno2306 ปีที่แล้ว +29

      Like in welding. Beautiful doesn't mean good.

    • @reasonable1
      @reasonable1 ปีที่แล้ว +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 ปีที่แล้ว +8

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

  • @jakobbarger1260
    @jakobbarger1260 ปีที่แล้ว +1383

    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 ปีที่แล้ว +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 ปีที่แล้ว +18

      @@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 ปีที่แล้ว +3

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

    • @astropgn
      @astropgn ปีที่แล้ว +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 11 หลายเดือนก่อน

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

  • @tomdarank1272
    @tomdarank1272 21 วันที่ผ่านมา +9

    Nobody tell this guy about HTML

  • @PaulSinnema
    @PaulSinnema 8 หลายเดือนก่อน +16

    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 ปีที่แล้ว +877

    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 ปีที่แล้ว +115

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

    • @mrosskne
      @mrosskne 9 หลายเดือนก่อน +23

      @@bufdud4 less straight forward*

    • @janiscakstins2846
      @janiscakstins2846 9 หลายเดือนก่อน +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 9 หลายเดือนก่อน +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 9 หลายเดือนก่อน +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 ปีที่แล้ว +327

    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 ปีที่แล้ว +55

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

    • @kindlin
      @kindlin ปีที่แล้ว +21

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

    • @Finkelfunk
      @Finkelfunk ปีที่แล้ว +14

      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 ปีที่แล้ว +11

      @@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 ปีที่แล้ว +23

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

  • @jmilen
    @jmilen 4 หลายเดือนก่อน +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.

    • @LudvikM
      @LudvikM 2 หลายเดือนก่อน

      +1 :)

  • @Cloudstreet
    @Cloudstreet 8 หลายเดือนก่อน +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

  • @tobene
    @tobene ปีที่แล้ว +915

    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 ปีที่แล้ว +4

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

    • @nazeefahmadmeer
      @nazeefahmadmeer ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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.

  • @frankpoon2605
    @frankpoon2605 8 หลายเดือนก่อน +2

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

  • @LucaDelloSterpaio
    @LucaDelloSterpaio 8 หลายเดือนก่อน +23

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

    • @bodardr
      @bodardr 2 หลายเดือนก่อน +1

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

  • @asdfz0mg
    @asdfz0mg ปีที่แล้ว +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 ปีที่แล้ว +6

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

    • @dylanh333
      @dylanh333 ปีที่แล้ว +3

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

    • @paulkanja
      @paulkanja ปีที่แล้ว

      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 ปีที่แล้ว

      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 ปีที่แล้ว +1

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

  •  ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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.

  • @skaldingdelight
    @skaldingdelight 8 หลายเดือนก่อน +2

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

  • @ajuc005
    @ajuc005 6 หลายเดือนก่อน +77

    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 6 หลายเดือนก่อน +5

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

    • @ajuc005
      @ajuc005 6 หลายเดือนก่อน +22

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

    • @pizzapunt3960
      @pizzapunt3960 6 หลายเดือนก่อน +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 5 หลายเดือนก่อน +15

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

    • @BodomsScythe
      @BodomsScythe 5 หลายเดือนก่อน +16

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

  • @erichobbs4042
    @erichobbs4042 ปีที่แล้ว +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 ปีที่แล้ว +51

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

    • @owenrowell
      @owenrowell ปีที่แล้ว +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 ปีที่แล้ว +9

      Or you can ask GPT to de-nest

    • @thunder____
      @thunder____ ปีที่แล้ว +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 ปีที่แล้ว +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.

  • @ahmed.._.
    @ahmed.._. ปีที่แล้ว +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 ปีที่แล้ว +15

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

    • @marcusrehn6915
      @marcusrehn6915 ปีที่แล้ว +30

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

    • @ThePowerRanger
      @ThePowerRanger ปีที่แล้ว

      Same

    • @christopherw1248
      @christopherw1248 ปีที่แล้ว +1

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

    • @sineme
      @sineme ปีที่แล้ว +8

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

  • @shanehebert396
    @shanehebert396 7 หลายเดือนก่อน +10

    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

  • @ModusVivendiMedia
    @ModusVivendiMedia 8 หลายเดือนก่อน +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).

  • @sebobafett1652
    @sebobafett1652 ปีที่แล้ว +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 ปีที่แล้ว +3

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

    • @papasmurf9146
      @papasmurf9146 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว

      ​@@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 ปีที่แล้ว

      On a PR?

  • @cc3
    @cc3 ปีที่แล้ว +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 ปีที่แล้ว +12

      + also known as the “early return” pattern

    • @911muha
      @911muha ปีที่แล้ว

      Dad d

    • @georgeyoung2684
      @georgeyoung2684 ปีที่แล้ว +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 ปีที่แล้ว +4

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

    • @erichermann1962
      @erichermann1962 ปีที่แล้ว +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.

  • @nicksrub
    @nicksrub 27 วันที่ผ่านมา +1

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

  • @thomasvnl
    @thomasvnl 8 หลายเดือนก่อน

    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.

  • @SJrad
    @SJrad ปีที่แล้ว +604

    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 ปีที่แล้ว +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 ปีที่แล้ว +1

      @@uusfiyeyh hmm interesting idea

    • @PaladinJenkis
      @PaladinJenkis ปีที่แล้ว +21

      Not if your name it properly

    • @nik325007
      @nik325007 ปีที่แล้ว +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 ปีที่แล้ว +17

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

  • @TheFrostFyr
    @TheFrostFyr ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +1

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

    • @SI0AX
      @SI0AX ปีที่แล้ว +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 ปีที่แล้ว

      "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

  • @robgoffroad
    @robgoffroad 8 หลายเดือนก่อน +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.

  • @edwardmurphy440
    @edwardmurphy440 9 หลายเดือนก่อน +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

  • @the24throguecannon
    @the24throguecannon ปีที่แล้ว +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 ปีที่แล้ว

      I totally agree!

    • @vibaj16
      @vibaj16 ปีที่แล้ว +3

      or just blur more

    • @blankRiot96
      @blankRiot96 ปีที่แล้ว

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

  • @garethjacobsnz
    @garethjacobsnz 11 หลายเดือนก่อน +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 7 หลายเดือนก่อน +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 7 หลายเดือนก่อน

      @@OpenGL4everingenuity

    • @dotti5060
      @dotti5060 6 หลายเดือนก่อน +1

      I go 2 levels. 3 only if absolutely necessary.

    • @autochton
      @autochton 6 หลายเดือนก่อน +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 6 หลายเดือนก่อน

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

  • @I.Carnivore
    @I.Carnivore 8 หลายเดือนก่อน

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

  • @stopitnowlol6697
    @stopitnowlol6697 8 หลายเดือนก่อน +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.

  • @CodingwithGPT
    @CodingwithGPT 10 หลายเดือนก่อน +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 3 หลายเดือนก่อน +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 3 หลายเดือนก่อน

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

    • @RubixstewYT
      @RubixstewYT 3 หลายเดือนก่อน +6

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

    • @soupman8165
      @soupman8165 3 หลายเดือนก่อน +3

      ​@@xbzq are you okay

    • @xbzq
      @xbzq 3 หลายเดือนก่อน

      @@soupman8165 Why you ask

  • @shubtakkorathinasapostle1159
    @shubtakkorathinasapostle1159 11 หลายเดือนก่อน +536

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

    • @ConnerTurmon
      @ConnerTurmon 8 หลายเดือนก่อน +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 5 หลายเดือนก่อน +3

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

    • @simonvutov7575
      @simonvutov7575 5 หลายเดือนก่อน

      same!!

  • @TonniTielens
    @TonniTielens 2 หลายเดือนก่อน +1

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

  • @wueijun
    @wueijun 6 หลายเดือนก่อน +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.

  • @biltongza
    @biltongza ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +4

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

  • @Accelerando_poco
    @Accelerando_poco ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +20

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

    • @jbird4478
      @jbird4478 ปีที่แล้ว +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.

  • @sidneyw.mathiasdeoliveira8621
    @sidneyw.mathiasdeoliveira8621 3 หลายเดือนก่อน

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

  • @Anton_Sh.
    @Anton_Sh. 8 หลายเดือนก่อน +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.

  • @wtcxdm
    @wtcxdm ปีที่แล้ว +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  ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว

      @@CodeAesthetic you can use this style. th-cam.com/video/6-mk6OpcUdM/w-d-xo.html

  • @CoolAsFreya
    @CoolAsFreya ปีที่แล้ว +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 ปีที่แล้ว

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

    • @AlexRenfro-ux8th
      @AlexRenfro-ux8th ปีที่แล้ว +1

      unreadable code is job security, mate 😄

  • @verfran
    @verfran 8 หลายเดือนก่อน +1

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

  • @stuartferguson11
    @stuartferguson11 8 หลายเดือนก่อน +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.

  • @jj-big-slay-yo
    @jj-big-slay-yo ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 11 หลายเดือนก่อน +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.

  • @NeonFraction
    @NeonFraction ปีที่แล้ว +375

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

    • @GOTHICforLIFE1
      @GOTHICforLIFE1 ปีที่แล้ว +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 ปีที่แล้ว

      @@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____ ปีที่แล้ว +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 ปีที่แล้ว

      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 ปีที่แล้ว

      @@T1Oracle ty for that

  • @2012TheAndromeda
    @2012TheAndromeda 7 หลายเดือนก่อน

    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!!

  • @cybermist2
    @cybermist2 2 หลายเดือนก่อน

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

  • @udadni
    @udadni 11 หลายเดือนก่อน +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!

  • @shugyosha7924
    @shugyosha7924 ปีที่แล้ว +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 8 หลายเดือนก่อน +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 8 หลายเดือนก่อน +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__ 8 หลายเดือนก่อน +4

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

    • @akulkis
      @akulkis 8 หลายเดือนก่อน +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 8 หลายเดือนก่อน

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

  • @ulhaqanwaar1
    @ulhaqanwaar1 8 หลายเดือนก่อน +1

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

  • @Fiascopia
    @Fiascopia 6 หลายเดือนก่อน +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

  • @TimTom
    @TimTom ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 6 หลายเดือนก่อน +1

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

    • @danny234555
      @danny234555 3 หลายเดือนก่อน

      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.

  • @mike200017
    @mike200017 ปีที่แล้ว +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 ปีที่แล้ว +5

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

    • @nuckm
      @nuckm ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +4

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

  • @ninodolo
    @ninodolo 8 หลายเดือนก่อน +1

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

  • @djtreston
    @djtreston 8 หลายเดือนก่อน

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

  • @fexofenadinaGenerica
    @fexofenadinaGenerica ปีที่แล้ว +26

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

    • @galitan5881
      @galitan5881 ปีที่แล้ว +2

      asmr for the developers lol

    • @fexofenadinaGenerica
      @fexofenadinaGenerica ปีที่แล้ว

      @@galitan5881 gonna put this video while I sleep

  • @timecubed
    @timecubed 9 หลายเดือนก่อน +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!

  • @jomama55ful
    @jomama55ful 6 หลายเดือนก่อน +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

  • @pkozelka
    @pkozelka 5 หลายเดือนก่อน

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

  • @arjunmehta2853
    @arjunmehta2853 10 หลายเดือนก่อน +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.

  • @tjeerdbakker160
    @tjeerdbakker160 ปีที่แล้ว +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

  • @brian1204
    @brian1204 6 หลายเดือนก่อน +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!

  • @Eddygeek18
    @Eddygeek18 8 หลายเดือนก่อน

    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

  • @SrFrancia0
    @SrFrancia0 ปีที่แล้ว +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!

  • @thomascorbin5371
    @thomascorbin5371 ปีที่แล้ว +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.

  • @clandsem3629
    @clandsem3629 3 หลายเดือนก่อน

    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.

  • @simon6435
    @simon6435 6 หลายเดือนก่อน +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

  • @IterativeTheoryRocks
    @IterativeTheoryRocks ปีที่แล้ว +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!

    • @Infiny92
      @Infiny92 ปีที่แล้ว +55

      This should be illegal.

    • @user34274
      @user34274 ปีที่แล้ว +33

      Disgusting. Just reading that sent a shiver of revulsion down my spine.

    • @BarackBananabama
      @BarackBananabama ปีที่แล้ว +10

      Nestscape.

    • @mingyenwu9621
      @mingyenwu9621 ปีที่แล้ว

      XD

    • @VeganSemihCyprus33
      @VeganSemihCyprus33 ปีที่แล้ว

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

  • @dankosek4274
    @dankosek4274 ปีที่แล้ว +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.

  • @JasonJBrunet
    @JasonJBrunet 4 หลายเดือนก่อน +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.

  • @x0myspace0x
    @x0myspace0x 6 หลายเดือนก่อน +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.

  • @sebikusik
    @sebikusik ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +8

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

  • @RaineAvina
    @RaineAvina ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +2

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

  • @Peter_1986
    @Peter_1986 9 หลายเดือนก่อน +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.

  • @TheJanstyler
    @TheJanstyler 8 หลายเดือนก่อน +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.

  • @dune2themaker
    @dune2themaker ปีที่แล้ว +6

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

  • @luciusoflegend
    @luciusoflegend ปีที่แล้ว +16

    Before this video, I never thought about it. But seeing code de-nested, I agree. It's far more readable. I will most likely incorporate these strategies into my coding technique. Thanks!

  • @aldairacosta4393
    @aldairacosta4393 8 หลายเดือนก่อน

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

  • @johnphamlore8073
    @johnphamlore8073 7 หลายเดือนก่อน

    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.

  • @anarelle
    @anarelle ปีที่แล้ว +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!

  • @noxagonal
    @noxagonal ปีที่แล้ว +143

    I generally agree, after 3 or 5 indentation levels it gets harder to understand how deep you really are in the indentations, but I'm not really against nesting past 3 levels. I am against spreading the code around however, eg. "else" statements that are far apart so you have no idea what they're for at a glance.
    In fact I'm more likely to add an indentation or an immediately invoked lambda to contain relevant code in its own block. Mostly in situations where the block is relatively small, semi complicated but doesn't quite make sense to put it in its own function.

    • @cook_it
      @cook_it ปีที่แล้ว +1

      Back when I knew less I wrote some code with the else so nested and far from the if that I had to add comments just for knowing to which if the else belongs.
      With this video I could probably easily fix it but I'm afraid something will break so... my old code will just stay the way it is, at least until I get determined enough to do another larger update XD

    • @TubeTAG
      @TubeTAG ปีที่แล้ว +6

      Cohesion is important. Extraction only works when the thing you're extracting is a *cohesive* chunk of code.

    • @absolutewisp
      @absolutewisp ปีที่แล้ว +1

      @@cook_it That is how you know it's either time for guard clauses or a new function, or both

    • @cook_it
      @cook_it ปีที่แล้ว +2

      @@absolutewisp Inversion/guard functions would perfectly solve it and make it way easier to read.
      The problem is that it's part of my updater subroutine which checks if there's an update and starts the update sub if there is, which means if I mess _anything_ up I can't send out anymore automatic updates, which would require all users to manually upgrade to a hotfix version, which is just... no.
      So I will probably do it if I do a major refactoring of all modules, which won't be anytime soon as I don't get to work on that all that often and there are more important things to update first.

    • @evancombs5159
      @evancombs5159 ปีที่แล้ว

      @@cook_it don't be afraid, just do it. It's a bad idea to let code rot. Just need to create some good tests to make sure any chance doesn't break anything.

  • @stefanoriffaldi84
    @stefanoriffaldi84 8 หลายเดือนก่อน

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

  • @AlaaMahran1
    @AlaaMahran1 8 หลายเดือนก่อน

    Great video. Just one point regarding putting the non-happy scenario first and return, this might affect the performance if the function is usually executed on the happy scenario as an extra if statement will be executed every time without need

  • @camelCase60
    @camelCase60 ปีที่แล้ว +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 ปีที่แล้ว

      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.

  • @_gheo
    @_gheo ปีที่แล้ว +45

    I'm extremely fascinated by the never nesting technique. I actually started using inversions and premature returns and I sure feel satisfied of my codes. There are always ways to improve since I'm a self taught, but damn, the elegance and readability sure feel great.

    • @timecubed
      @timecubed 9 หลายเดือนก่อน +1

      They really do. Especially in cases where you're using rust or something. Although rust is quite awesome, the syntax can get quite messy at times and using these techniques really do clean up code and makes all of my rust code quite concise and elegant and easy to read, especially the extraction one.

  • @JoeyZhuNovatronDrakaeneon
    @JoeyZhuNovatronDrakaeneon 7 หลายเดือนก่อน

    it's a tradeoff between complexity of ur dependencies versus the complexity within a single one. there is some conserved, lower-bounded amount of abstraction depth in whatever task you are trying to do. You're maximizing the intuitive information from the dependency structure and structure within each dependency, and minimizing the amount of clutter and chaos on either side(2nd law of thermodynamics applies to codebases), and your parameter is how many depths you go before you start making new files, and maybe also files to directories.

  • @waffle8364
    @waffle8364 8 หลายเดือนก่อน

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

  • @jeremieh5009
    @jeremieh5009 ปีที่แล้ว +5

    As a chronic nester this advice was very helpful! Hopefully I’ll be able to make my code clean as can be!

  • @vabondarenko
    @vabondarenko ปีที่แล้ว +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 :)

  • @ferrchane
    @ferrchane 9 หลายเดือนก่อน +2

    I love the way that you showed here to make the code more readable and it looks easier to debug in the future, but I think this trick will only work if you develop a program for OS like Windows or Linux, but I'm not sure about mobile apps, especially Android OS because there's a limit to how many functions you can create per apps. Sure it will work well if we apply Inversion, but Extraction will cause method-limit error if you apply this to your code in Android Studio without any control over your method. So, I think only do Extraction when you find that the function you create will be use by another code.

  • @andrewcgs
    @andrewcgs 7 หลายเดือนก่อน

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