
21 Nested Callbacks - ericz
http://blog.michellebu.com/2013/03/21-nested-callbacks/
======
lelandbatey
I love this. The code may not have been beautiful, but it worked, and the
author figured it out themselves!

I'm simultaneously reminded of two different quotes:

 _Let's argue about whether Haskell or Clojure is better while somebody else
ships products using PHP and duct tape._ \--@agentdero [0]

And the other:

 _< dm> I discovered that you'd never get an answer to a problem from Linux
Gurus by asking. You have to troll in order for someone to help you with a
Linux problem._

\-- Bash.org [1]

You should always try to do SOMETHING over being frozen in indecision.
Additionally, we really should do a better job of explaining things to people,
so they don't have to stoop to trolling for answers :)

[0] <https://twitter.com/agentdero/status/174965036928868352>

[1] <http://bash.org/?152037>

~~~
hazelcough
Blog post writer here. I was going to mention this in the post, but I ended up
deciding against it:

I'm from Middle America. In Middle America, when you ask a farmer what he
feeds his pigs, he tells you what he feeds his pigs, what he doesn't feed his
pigs, why he feeds his pigs what he feeds his pigs, how he feeds his pigs, and
what sunscreen he applies to their skin.

So it was very weird to me that a lot of programmers didn't like to share
their knowledge of programming (except, it seems, when they are trying to
impress other programmers).

~~~
donaq
Hi, I used to write code like your 21 nested callbacks, so I'm baffled by your
friend's assertion that no programmer would be so patient. I've always thought
that the patience to grind endlessly at a problem (or bug) without an obvious
solution was one of the more laudable shared virtues of our tribe. Patience
is, in fact, a vital part of my learning process.

In fact, I think that's probably a part of the reason why some programmers
don't have patience for beginners with a lot of questions. It's because
beginners actually have Google and StackOverflow these days, so it might seem
like laziness to someone who had to learn using books and man pages. It's not
that they don't like to share their knowledge, it's that they think the answer
is already there if you'd bothered to look. I'm not saying that they're right
to have that attitude, by the way. I'm just trying to present things from
their perspective.

~~~
hobs
"I divide my officers into four groups. There are clever, diligent, stupid,
and lazy officers. Usually two characteristics are combined. Some are clever
and diligent -- their place is the General Staff. The next lot are stupid and
lazy -- they make up 90 percent of every army and are suited to routine
duties. Anyone who is both clever and lazy is qualified for the highest
leadership duties, because he possesses the intellectual clarity and the
composure necessary for difficult decisions. One must beware of anyone who is
stupid and diligent -- he must not be entrusted with any responsibility
because he will always cause only mischief."

Granted, Kurt von Hammerstein-Equord was a nazi fuck and was talking about
leadership, but I have found the best programmers are extremely lazy, however
they have a constant drive to figure things out, take them apart, and put them
back together again. They also generally have a need in the same vein of
"write programs so they don't have to do the work of copy pasting 100 times in
the first place" even if they spend 4 hours figuring out to do that.

~~~
Paradigma11
Ahm, nazi? <http://en.wikipedia.org/wiki/Kurt_von_Hammerstein-Equord>

~~~
hobs
Did you read my post?

"Granted, Kurt von Hammerstein-Equord was a nazi fuck"

Nope, you didn't.

~~~
blasdel
Did you read his link?

"He is famous for being an ardent opponent of Hitler and the Nazi regime."

Nope, you didn't.

------
tikhonj
> _(I gathered from these exchanges that programmers have a perpetual
> competition to see who can claim the most things as 'simple.')_

Amusingly, I've noticed the same thing: I do claim that a surprising amount of
things are _simple_. And you know why? Because they are. A whole bunch of
things (most recently F-algebras and F-coalgebras) really _are_ simple: you
start with a very simple concept (say sets and functions) and build up to
them, taking very simple steps along the way. Maybe you have to bring in a
couple of other concepts that are similarly simple.

EDIT: I should have made this clearer: I say something is simple _before_
trying to explain it rather than _instead of_. I mainly do it to avoid scaring
people without reason, and everyone gets far too scared of words like
"F-coalgebra" or even "monoid".

Every single step along the way? Virtually trivial. But put them together and
you get something genuinely difficult to follow.

It turns out that enough trivial steps all building upon each other becomes
difficult to follow for anyone. Yet, once you've finally understood it, you
can't see why it was difficult any more: after all, all the components are so
simple, and it all makes sense! (Now.)

I realized this in a pretty direct way: I was trying to explain the
aforementioned algebras to some of the smartest people I know--people with
much more mathematical experience and aptitude than me--and they all found it
a bit hard to follow. Not because they couldn't follow any particular step,
but because putting it all together in your head is difficult.

So really, the ultimate conclusion is: just because something _is_ simple does
not mean it is _easy_. Having some trouble with simple concepts like this is
not an issue at all; everybody does. But that doesn't mean they aren't simple!

Another, more surprising, conclusion is just how shallow the stack of concepts
has to be to cause people trouble. It's not like there are hundreds of parts
in these definitions: there are maybe 10. (Say: set, function, algebra,
identity, category, morphism, functor, dual.) And yet this is more than enough
to confuse.

~~~
wtallis
That's something that I think laypeople never realize about computer science -
it's all really simple things, but combined together at such a scale and pace
that in a few decades we've done the equivalent of building a cat from scratch
out of DNA. Big complex things really can be built out of extremely simple
parts, and we're doing it all the time, but for a lot of people our technology
is indistinguishable from magic.

~~~
meric
Markets too, in the end they are all just information, limit and market
orders.

------
munificent
> "No, no programmer would do something this." He was not sarcastic. I wanted
> to switch back into Molecular and Cellular Biology right then. But then he
> added, "No one would end up with code like this because they simply would
> not have had the patience."

My brother and I learned to program in BASIC on an Apple IIe when we were
kids. At the time, we were also into making little movies with our family's
VHS camcorder. You could draw graphics in BASIC, so we thought it would be
radical to write a program that would draw a cool logo animation for our
movies.

We got a big sheet of graph paper and hand-drew the intended pixel art for our
logo. Then started writing code to draw it one line at a time. We put a delay
between each line so that it would do an animated wipe. We knew how to pause
by doing a busy loop:

    
    
        10 FOR I = 1 to 100
        20 NEXT I
    

What we didn't know was how to define reusable procedures (GOSUB). So between
each of the hundred lines of pixel art, I typed in that loop. And I mean that
literally: this was a line editor. No copy and paste. I wrote it out each
time.

Now I just lament having the much free time and focus to be able to do that...

~~~
JamesAcorn
Supposing you could travel back in time and give your earlier self a book (or
at least, a few sheets of paper) that described 'good programming' (e.g. using
GOSUB, in this context) - would you do it?

Would you have been better off 'doing things right' from day one, versus
experimenting and muddling through?

------
Cushman
> (I gathered from these exchanges that programmers have a perpetual
> competition to see who can claim the most things as 'simple.')

Nobody hits my brother but me.

Programmers are persistently frustrated in our tools-- when you can see how
things work, you start to see just how broken it all is. Things that should be
easy are hard, things that should be hard are nearly impossible. And for every
thing gotten right, there's something a little subtler that's completely and
opaquely wrong, wasting days of your life. We hate our tools, and we love to
complain about them.

But if _you_ complain about our tools... Sorry, who are you? This is basic
stuff.

~~~
rhizome
"A poor craftsman blames their tools."

~~~
qu4z-2
We're in a funny profession where we're both the people making and using the
tools.

In other professions, blaming your tools is essentially a "There's nothing I
can do about it -- the tools just suck."

In programming, we can go "These tools suck, but I can fix them". Of course,
then you never accomplish what you initially set out to...

~~~
rhizome
Who is "we?" I use pretty much vanilla vi/vim and SublimeText (or whatever
comes next) so I'm not ever hamstrung a possible lack of tools.

I see this attitude as being like a lot of hot rod restoration people I've
known: they like working on _cars_ , but seemingly not necessarily _driving_.
They don't ever want to be done, so they keep finding broken stuff, and the
end result is that their "tool" is always broken. The Lego castle can always
use another brick, you know? When do they ever drive, and if they do, are they
happy when they do it or are they complaining inside the entire time? "Engine
feels a little rough" is "my computer seems slow" is "that could really be
automated." To me it's all just stuff that is other-than-coding. Pretty much
just give me a fuzzy-filefinder with `screen` and I'm good, I gave up
tinkering quite a while back.

From OP: _"Programmers are persistently frustrated in our tools-- when you can
see how things work, you start to see just how broken it all is. Things that
should be easy are hard, things that should be hard are nearly impossible. And
for every thing gotten right, there's something a little subtler that's
completely and opaquely wrong, wasting days of your life. We hate our tools,
and we love to complain about them."_

~~~
qu4z-2
"We" is programmers as a group, in

> We're in a funny profession where we're both the people making and using the
> tools.

I don't mean that every single programmer is making and using the tools, just
that the skillset for making and using the tools is pretty similar.

Note that I said "we _can_ go <bla>". I'm not really advocating stopping what
you're doing to tinker with your tools. It's just that it's often a
tantalising possibility which people in other professions are less tempted by.

As you say, though, if you want to get anything done, you have to resist the
temptation.

------
lincolnq
I love that the author was persistent enough to actually get to a solution --
any solution, no matter how ridiculous -- using nothing more than Google. I
can't count how many times I've tried to help someone get started on the
basics of the web programming stack only to realize that the inferential
distance for this person is so high that I would have to spend hours
explaining things in order to help them solve the problem.

Sorry world. It's getting better. But slowly.

~~~
mbillie1
I recall being a novice and learning Java, and trying to solve
<http://projecteuler.net/problem=5> \- I had nested if statements like "if(x %
20 == 0) { if (x % 19 == 0) {..." and I was thrilled that it worked. I have
since learned far better ways to accomplish things like that; but I probably
wouldn't have if I had just given up in frustration and never become a
professional developer. Cool job by the author in posting the original code.
I'm too embarrassed to post my nested-if business :)

------
kadabra9
Great article.

For a while, I was even hesitant to simply show some of my projects to other
developers I looked up to..I figured the code was so bad, and the project so
trivial, that why bother?

Reading sites like HN, you read about these tremendously talented people....
doing exits, building absurdly cool projects that you think you'll never be
able to build... and it's easy to benchmark yourself against that sort of
ideal and think that your stuff isn't cool enough. When I finally was
confident enough to share some projects with a few people I respected, I was
blown away by how much I learned just listening to their feedback.

Even if you think you're code sucks, you'll improve rapidly by learning WHY it
sucks, and using that in new projects.

------
untog
My real regret after reading this post: my early code is lost. Git didn't
exist. Maybe SVN did but I wouldn't have had a clue.

To my genuine amazement, the company I worked for immediately after leaving
college is still using a program I wrote for them seven years after I wrote
it. When I left, they said that every company operation was going to be
covered by SAP- weird how that didn't work out...

But still, it was written in VB.NET (!) and was a horrible, horrible mess. I
would love to take a look at that code now, but I'm afraid that if I contact
them they'll hold me responsible for updating it.

~~~
domlebo70
Be glad. My forays into programming have been gitified. It's like these
teenagers growing up with social media and cameras everywhere. They'll always
have those years to haunt them :P

------
jcampbell1
I just wasted about 30 minutes writing a short solution, when I could have
written the 22 callbacks in about 5 minutes. I did learn quite a bit about
jquery, and the fn.delay isn't great. The funny thing about programming is
that it does seem simple once you have a solution.

    
    
        function animate_opacity_to(opacity) {
            var elems = $('[id^=row]').get();
            (function x(){
                var el;
                if(el = elems.pop()) 
                    $(el).animate({opacity:opacity},100,x);
            })();
        }

~~~
dandelany
Actually, jQuery animate includes a built-in animation queueing system for
this exact purpose, so callbacks really aren't necessary at all! For example:

    
    
      function animate_opacity_to(opacity) {
          $('[id^=row]').forEach(function(el) {
              $(el).animate({opacity: opacity}, {duration: 100, queue: true});
          });
      }
    

(haven't tested this but I think it should work.) In general, I've found that
using a queue or queue-like structure can often help alleviate the dreaded
"callback waterfall". Instead of saying "do this, then when you're done, do
this, then when you're done, do this", you're saying "here are a list of the
things I want done, do them in order and don't start the next thing in the
list before the previous one is done". If you have some things in the queue
that _can_ be run simultaneously, you can combine them with a Deferred (see
<http://api.jquery.com/jQuery.Deferred/> )

In any case, great article - I definitely remember many similar scenarios that
came up while I was learning to code. Sometimes you just gotta go with the
crappy implementation you know will work rather than the efficient
implementation that is beyond your current understanding :)

~~~
jcampbell1
I tried something like your code, but it doesn't work. The queue parameter
defaults to true, and it only applies to the set of elements in the jQuery
object.

What will work is adding `delay` e.g.

    
    
        $(el).delay(i*100).animate(...
    

But that causes other problems because frantically clicking will cause the
animations to get queued. Setting `queue` to false, breaks .delay().

------
sirmarksalot
Reminds me of the first pseudo-3D thing I wrote back in high school. I'd
borrowed one of my brother's 3D graphics books and came across the simple
algorithm for depth drawing (x = x0/z, y = y0/z), and immediately set to work
writing a wireframe space shooter in Pascal.

I was so eager to get the graphical part out there that I didn't think about
the problems of modeling, or having multiple objects on the screen at once.
The whole thing was a single-file, thousand-line, hard-coded mess. And I still
think it was awesome.

------
cmurphycode
I've been getting pretty sick of the whole "look how dumb I am, but I'm
iterating!!!11" meme, but I _really_ like this post. As a young person working
in a company of people with far more experience, I've asked my share of
stupid-simple questions and made my share of dumb mistakes. Luckily, I've got
enough experience with programmers to get the most out of these interactions
(also helpful to have decent human beings for co-workers!)

The important thing is to remember that there aren't (m)any super geniuses for
which this stuff spews out first try. It's just that some people had the
benefit of working through their ridiculously terrible code at the age of 8,
writing BASIC, or whatever. And while they may have to learn jQuery the same
as you did, they have a massive class of "intuitive" knowledge, which is
really just experience, to help them through most of it.

------
lmm
Programming may or may not be hard, but it's not a good idea to think of it as
hard. You need the laziness that makes you think, as soon as you get to
callback 3, "there must be a better way than this". Occasionally you're
disappointed, but generally if you know programming is easy then it will be.

------
Mahn
We all have written code only to come back to it a few weeks later and think
"oh god, what in the world was I thinking". If only code refactored itself
over the time; small projects aren't an issue, but there's a point in every
devs life when you have this monstrous one-eyed, ten thousand lined class that
works fine in production but no one knows how or why it works and the idea of
making a single change to it gives you pure panic and terror. And you know you
have to rewrite it, but you have a hard time justifying spending two weeks on
getting nothing tangible done, so to speak. The class goes on unfactored for a
while (until it inevitably breaks) but at least you come to this almost zen
realization that beautiful code = simple, short, and self descriptive code.

~~~
danneu
user.rb

------
dirtyaura
I like this quote:

"I gathered from these exchanges that programmers have a perpetual competition
to see who can claim the most things as 'simple.'"

~~~
hazelcough
So many people like this quote that I wish I had structured the sentence less
awkwardly.

~~~
skore
I found it perfectly simple.

------
noahsark769
I used Michelle's website last year when I was looking for examples of how to
write good CSS and HTML - I definitely couldn't have told you then that she
had started web programming less than a year ago!

It just goes to show that if you really have a passion for something and you
really work hard at it, you can become awesome at it (or at least good enough
to know you can be awesome without that much work) in no time. I find that
this usually holds for most things in life, but it lends itself to web design
especially.

------
kushagrawal
I know Michelle, and it's impressive that she started coding just two summers
ago. Testament to the fact that it doesn't take long to become a good
programmer

~~~
nickporter
Depends on your definition of "good programmer".

~~~
radio4fan
Unless I'm missing some wit, that seems uncalled-for.

And judging by her github profile, she's a good programmer by any reasonable
definition.

~~~
nickporter
Sorry, I was not attacking anyone in particular. It's just that there are so
many facets to programming, and being good at it really depends on the
context.

That said, anyone that learns from their mistakes will become great.

------
Choronzon
21 nested callbacks sounds like my current attempt at twisted
programming,except Michelles code is a lot clearer and easier to read! Even
more experienced people write complete rubbish in an new language or worse
port their old language patterns over. No shame in being a beginner.

~~~
rhizome
"Be a better beginner," has served me well over the years.

------
benatkin
Reminds me of <http://prog21.dadgum.com/87.html>

------
gizmo686
This reminds me of some of my earlier excursions into coding. For example,
early on I needed to be able to randomly select from a set of 100 numbers. Not
knowing about arrays, but knowing about classes and the random module I
created a class that had 100 fields, and a method that contained a giant if-
else tree to select one. Of course, I did not want to write out all of that,
so I ended up creating an excel spreadsheet, and used that to mass produce a
bunch of the repeated lines.

------
sergiosgc
To the writer of the post: my thanks. You brought a smile to my face. The awe
at the complexity of programming is something I felt a long time ago, when I
was 9 or 10. It is still vivid, and your post brought back memories and a
smile.

Just goes to show that talent is as much inate as it is countless hours
bashing against the wall. I had a lot of patience when I was 9.

------
sps_jp
This reminds me of a novelty I created early on in my programming career. I
wanted to recreate the color picker from Photoshop (I think version 4) on a
webpage. This was several years before jQuery and "Googling" it would have
produced meager results. After considerable effort and writing equally
"elegant" code as the OP, I had a 256 x 256 grid of divs displaying my color
picker. Little to no CSS in that bad boy, but a ton of javascript hex
conversions. The page loaded soooooo slow and brought my computer to it's
knees, but I was very proud of it. I did actually use recursion, but not to
the degree I could have if I had more knowledge. The achievement was not in
writing perfect and optimal code, but in having an idea and seeing it through
to completion.

------
bjliu
Well...it seems like Eric Z. and the UC Berkeley Hackers@Berkeley club really
can easily vote their way up on HackerNews. It's happened more than once and
its not a coincidence :\ Still, amazing article and learned a lot in 5 minutes
:)

------
kennu
Nowadays whenever I see a callback waterfall forming, my first thought is
<https://npmjs.org/package/node-async>.

~~~
dmix
Yep there's plenty of solutions to callback hell.

My particular favourite is the Lamina library in clojure which takes the
event-driven approach <https://github.com/ztellman/lamina/wiki/Introduction>

------
jwmoz
I find those 21 nested callbacks strangely elegant.

------
yati
This reminds me of the days when I was learning, even before I got into
college. Fortunately, we as an industry have more resources than any other
field for beginners, but as lelandbatey said, "...we really should do a better
job of explaining things to people,..." - +100

------
tomasien
Everyone I know who codes or designs is anxious to help others learn to do the
same. However, it's just common decency and respect to Google it, try to do
it, and then have specific questions about what you couldn't get past.

Just a rebuttal to one point that irked me.

~~~
hazelcough
See, getting value out of Google is something that's learned over time. At the
very beginning it was hard to get very far at all with just Googling and when
I asked others they pointed me back to Google--some of them unhelpfully, but
others showed me how to use better search terms for the subject at hand.

That helped a lot, and I don't resent them for that type of help at all. I'm
sorry if it came across that way in the writing.

~~~
mbillie1
> See, getting value out of Google is something that's learned over time.

This is very true. Especially early on, while learning basic concepts, I found
it very difficult to Google things because I did not know the terms or
concepts involved. When I was attempting to self-teach my first programming
language (Python), I could not understand the difference between parameters
and arguments - but I didn't know that that was how to characterize my problem
either. I just thought "why doesn't 'x' mean what I said it means over there?"

------
joshguthrie
I love this code, reminds me of my seven-level cascade in server-code
javascript.

And it's always funny to go back to our beginnings and see the difference in
code and level after only some years :)

------
robomartin
I hate snob programmers and designers.

It isn't very uncommon to have code that would cause most to projectile-vomit
in products that are massively successful, reliable and, yes, very profitable.

For design, there's always Craigslist.

------
camus
"Programming is hard." No it's not. Resources are everywhere today ,tons of
books , Stackoverflow , tutorials ,etc ... you cant accuse programmers of not
wanting to share their knowledge ,that's not true , they all do.

You have entire and complex projects on github available for free , so no
Programming is not hard , it takes time to become a good programmer yes but
like everything else in life. You want to try something hard ? try to be a
doctor instead.

~~~
bjliu
Programming IS hard. You can ask the PhD. Computer Science students at any
decent college and they will tell you that they are humbled because the field
of programming is so vast and wonderful and full of mystery. I think we can
admit that we have discovered .000000000000000001% of the things that can be
discovered at this point in the field of programming.

~~~
kragen
I think you overestimate our knowledge of programming. Still, it seems like
the pace of discovery has slowed down considerably since the 1960s, for
whatever reason.

------
kailuowang
Programming is hard, but that's where the fun is. Writing 21 nested callbacks
isn't that hard especially with some copy and paste, finding a solution that
does not look that ugly is hard, but otherwise programming will be really
boring. I mean writing code that merely works is boring most of the time. If
finding an elegant solution is not more fun than finding a working solution
for you (those who enjoyed math knows what I mean), then programming maybe not
your thing.

~~~
daleharvey
Thats pretty pointlessly dismissive. Its great that there are people who like
finding elegant solutions to problems but in the same hand its also great that
there are people who care more about solving users problems than generating
pretty code. (I would count myself in the latter group)

~~~
kailuowang
I am not really trying to dismiss people how care more about solving users
problems. In that case, product is your thing, and I love love love to work
with a product person who is passionate about solving user problems. But I
doubt I would enjoy maintaining the code written by product person who doesn't
care that much about "pretty code".

~~~
rhizome
Very rarely would it be your job to enjoy maintaining that code.

