00:00I have to admit I'm a never Nester
00:06but there are more of us than you think
00:08dozens even Linus torvill does one I
00:12mean I haven't asked him but I'll show
00:14you what I mean in a little bit
00:16you might be wondering well what is a
00:19I never Nester never nests their code
00:22okay not never but we do have a
00:26disgusting meter which grows
00:27uncontrollably as the number of Tabs go
00:31nesting code is when you add more inner
00:33blocks to a function we'll consider each
00:36open brace to be adding one more depth
00:41so this function is one deep because
00:43there's no inner blocks
00:45and if we add an if statement we've made
00:49if we add a loop we've now made this
00:54and this my fellow programmers is the
00:56maximum and never Nester can handle
00:59a never Nester doesn't dare to go for it
01:02now the perverse among you might wonder
01:04what four deep even looks like and while
01:07it brings me great pain to do I
01:10understand that I must show you for
01:26we've now taken a reasonably readable
01:29function and dramatically increased the
01:31amount of conditions your brain must
01:35but what can we do about it
01:37well there's two methods you can use to
01:42this is where you pull out part of the
01:43function into its own function
01:47which is simply flipping conditions and
01:49switching to an early return
01:52let's look at extraction first
01:55we can extract the inner part of the
01:56loop into its own function
02:01now we can apply inversion
02:05when you put the happy path of code
02:07within deeper and deeper blocks it
02:09creates a lot of nesting instead we'll
02:12invert the condition and put the unhappy
02:16first we'll flip our if else by
02:18inverting the condition
02:21now since we can return here we know
02:23that the else block isn't actually
02:25needed so we can flatten our else into
02:29now if we hit our unhappy case condition
02:32here we simply get out of the way and
02:35then the main part of the code can do
02:39when you have a lot of conditions to
02:41check like this we can apply inversion
02:44over and over again and we end up with a
02:46sort of validation gatekeeping section
02:50which sort of declares the requirements
02:54and then we have the Crux of the real
02:58and you'll notice that the happy path
03:00moves down the function and all the
03:02error paths they're indented
03:07when reading this code I find I can
03:09mentally discard the condition and focus
03:12on the core code versus when it's nested
03:14I find myself having to hold these ideas
03:17I'm curious if you experienced the same
03:21let's look at a larger example
03:24all right look at this beauty
03:27before we go refactoring it let me walk
03:31you through what's happening
03:34the goal of this code is to download a
03:36bunch of files from the web
03:38it talks with this download class that
03:43it's an async download so when we start
03:46the download we have to call Process
03:50and each time it gives you one of these
03:54if it returns in progress we'll need to
03:57keep calling process more
03:59on top of that you want to download
04:01multiple files at once in the background
04:04so we've created a thread that manages
04:09the way new downloads enter the system
04:11is through this append download method
04:13which puts the requested URLs onto a
04:17thread then wakes up and grabs the URLs
04:19from the queue and then adds them to
04:21this list of current downloads
04:25each download is given a state which is
04:27either pending in progress or complete
04:31so on each cycle of the main Loop the
04:33thread walks through each download and
04:35checks what it needs to do with it
04:40you start a new download
04:42if it's complete we simply remove it
04:49we call that process method we mentioned
04:52earlier and figure out what's happening
04:55if it's completed successfully we mark
04:57it as complete so it can get removed
05:00and in progress means we do nothing
05:01because it's still ongoing
05:04but things get interesting if we hit an
05:08the connection was okay but we got an
05:10unhappy HTTP response
05:12we determine whether the air is
05:15if it is we retry up to three times
05:17setting the download back to pending
05:21once it's failed plenty we ejected from
05:24our download list and push it to a
05:26failure queue for someone else to deal
05:29for connection air we retry three times
05:31then we set this special connection
05:33disabled flag and this causes us to
05:36basically give up on every download and
05:41okay so there's a lot going on here and
05:44it's all heavily nested in this function
05:46which makes it hard to follow
05:48so let's apply extraction and inversion
05:53the first two big candidates here are
05:55the two big branches of download
05:57processing pending and in progress
06:01so let's extract these out
06:03we'll move the pending part to process
06:12and in progress to process in progress
06:24but this in progress function is still
06:26too deep for my liking
06:28the worst offender is this HTTP air
06:31section so let's move that out as well
06:34now we'll keep extracting further in our
06:38we have four major sections of our code
06:42where we process incoming requests from
06:46where we deal with our current downloads
06:49where we clear out the in-progress
06:53and where we wait for the signal that
06:54there's new downloads to look at
07:09so now our main function clearly
07:11outlines the steps that are happening
07:14you can see the high level logic I
07:18and if you were to dig into any of these
07:19functions there are also concise
07:24at the beginning of this video I
07:26mentioned that Linus torvald is a
07:28suspected never Nester
07:31and I say this because in the Linux
07:32kernel Style Guidelines they state if
07:35you need more than three levels of
07:37indentation you're screwed anyway and
07:40should fix your program
07:43the kernel dudes are always so dramatic
07:47they visually enforce this by making the
07:49tab size 8 characters wide this is what
07:52eight characters look like with heavy
07:58I'll admit I'm not that committed to the
08:01cause but I am into limiting indentation
08:05I believe that constraining how much you
08:07Nest forces you to write better code
08:11if you notice instead of one large
08:13function that handles many things we now
08:16have small concise functions that have