
The Three Great Virtues of a Programmer: Laziness, Impatience, and Hubris - aaronchall
http://c2.com/cgi/wiki?LazinessImpatienceHubris
======
anaolykarpov
I'm a Perl dev for less than 5 years. Since last week I changed the company I
work for. The new company has a project which is 12+ years old.

This project has a code base written in Perl which seemingly violates all
programming best practices: files of 50k LoC,functions of several thousands of
lines, there are frequently 5-6+ levels of nested ifs. It contains all the
technical debt it acquired during these 12+ years.

However, it took me less than an hour from the moment I got access to a
working vm to make the first fix - display the correct currency on invoices
which were not paid in usd. And this, in the context that it was the first
time I logged into the app and I also had to find such a buggy invoice.

Now, tell me again how unreadable and hard to understand Perl is?

~~~
chipsy
I'm increasingly forgiving of that kind of "primitive" code with giant,
heavily nested functions, because the worst that can go _wrong_ with it from a
maintenance standpoint is heavy duplication and overreliance on mutable state.
Those are knowable quantities, and you can attack them systematically.
Otherwise, everything is laid out for you in straight-line order. You can just
read it and see "this happens before that" without having to run the program
or a debugger, and nobody even has to burden themselves with giving "this" and
"that" an explicit name(although a comment can be a real boost to finding what
you want).

Codebases that are cleverly factored to within an inch of their life are much,
much worse. There's no guarantee that the original factoring successfully
decoupled anything, and all the additional content allows for new bugs to slip
in "between the cracks" \- parameters left accidentally unset, a hierarchy of
functions getting called in the wrong order, etc. The original programmer has
to spend more time coming up with ways to name and enumerate these details,
allowing their eyes and thoughts to be taken off of the domain problem.
Because more powerful programming tools are used, more powerful debugging
techniques become necessary. And when the architecture breaks, the call stacks
just get deeper as the heavy metaprogramming guns are brought out to make
increasingly clever workarounds to the resulting issues - after all, nobody
really wants to try to disentangle the code after it hits the point of
architectural meltdown.

Of the two, copy-paste coding is definitely the lesser evil. So I allow some
of that first and then clean up the low-hanging fruit.

~~~
anaolykarpov
Surprisingly, I still have to find duplicated code. They've warned me it is
there, but I haven't seen it yet

------
jfoutz
Beware false laziness. Slamming out a 500 character command line to build
something is ok for a little while, but if it ever falls out of history,
you're doomed. Write the Makefile and expend less energy overall.

~~~
seanp2k2
Why not just copy/paste that into a .sh, put #!/bin/bash at the top, check it
into source control, and call it good enough for now? I guess they call that a
"Dockerfile" these days :)

~~~
sdenton4
True laziness is building your own linux kernel because the length of your
command line flags overran the limit allowed by the OS.

~~~
tormeh
I, uh, don't think laziness is the right word.

~~~
degenerate
I think he misspelled MAXIMUM OCD

------
artlogic
I've found the phrase "long-term lazy" is the quickest way to describe the
first virtue: someone who's willing to work hard today so they can be lazy (or
have more time for other things) later on.

~~~
sweezyjeezy
I don't see how 'lazy' is a good word to use though. I would imagine someone
who is lazy would be much less likely to write documentation than someone who
isn't. Prudent is a much more fitting, if less eye-catching word.

~~~
artlogic
The "long-term" qualifier is important here. The best programmers I know are
willing to go to great lengths to be lazy sometime in the future. Why write
and maintain comments and documentation? Because you know when it breaks in
the future it will be easier to fix, thus allowing you to fix the problem and
go back to whatever "lazy" thing you were doing.

Let's be honest, the term lazy is loaded. I use the phrase "long-term lazy"
because it elicits conversation. "You're looking for a trait that's considered
negative? Why?" It's much easier to pull someone in by saying good programmers
are lazy (in the long term) than good programmers are prudent.

~~~
raiph
This is of course what Larry meant, not the literal meaning.

The whole Perl 6 thing is the ultimate in this form of lazy; 15 years of
design work on both the culture and the technology just so he can die in peace
in his old age rather than worry about having to be reborn to continue
tinkering with Perl 5.

~~~
AdieuToLogic
> ... rather than worry about having to be reborn to continue tinkering with
> Perl 5.

So autovivification such as:

    
    
      my $larry;
    
      $larry->{Please}->{Add}->{Feature}++;
    

Won't incant a commit in Perl 6?

:-)

~~~
raiph
Latest Rakudo responds with a compile-time error:

    
    
        ...
        Unsupported use of ->(), ->{} or ->[] as postfix dereferencer; in Perl 6 please use .(), .[] or .{} to deref ...
    

Following the advice leads to:

    
    
        my $larry;
        $larry.{Please}.{Add}.{Feature}++;
    

which leads to another compile-time error:

    
    
        ...
        Undeclared names:
            Add used at line 1
            Feature used at line 1
            Please used at line 1
        ...
    

Those "undeclared names" were probably meant to be string hash keys. So try
that:

    
    
        my $larry;
        $larry.{'Please'}.{'Add'}.{'Feature'}++;
    

Bingo.

By the way, that's an unusual way to write such code. The periods are
optional, so this is equivalent:

    
    
        $larry{'Please'}{'Add'}{'Feature'}++;
    

And the braces, which support any expression, such as strings as used in this
example, are typically not used. Instead, typical code uses angle brackets,
which assume the words within are strings:

    
    
        $larry<Please><Add><Feature>++;
    

Finally, in Perl 6 it's often useful to use an array sigil (@) or hash sigil
(%) instead of the general purpose scalar sigil ($):

    
    
        my %larry;
        %larry<Please><Add><Feature>++;
    

I don't know if I've incanted a commit in Perl 6 by writing this, but ya never
know... :)

\----

An old sig of mine (slightly reworded) from the 90s:

If I could live my life again I think I'd believe in reincarnation.

~~~
AdieuToLogic
(golf clap initiated)

Well played good sir, well played indeed...

:-D

------
aaronchall
From the article:"

Laziness:

The quality that makes you go to great effort to reduce overall energy
expenditure. It makes you write labor-saving programs that other people will
find useful, and document what you wrote so you don't have to answer so many
questions about it. Hence, the first great virtue of a programmer. Also hence,
this book. See also impatience and hubris. (p.609)

Impatience:

The anger you feel when the computer is being lazy. This makes you write
programs that don't just react to your needs, but actually anticipate them. Or
at least pretend to. Hence, the second great virtue of a programmer. See also
laziness and hubris. (p.608)

Hubris:

Excessive pride, the sort of thing Zeus zaps you for. Also the quality that
makes you write (and maintain) programs that other people won't want to say
bad things about. Hence, the third great virtue of a programmer. See also
laziness and impatience. (p.607) "

------
Foy
Just today I was actually thinking laziness was one of my greatest assets as a
developer. Always trying to find a way to make my work do as much of itself as
it can, haha.

~~~
vacri
To be honest, it's not actually 'laziness' as much 'desire for automation'.
I've worked with a few actually lazy developers in my time, and it's not fun.
For example, it's hard to be a software tester when the design documentation,
in it's entirety, is on an A4 sheet in the lead developer's desk, and he's too
lazy to make a copy for you. That was medical software, no less...

~~~
QuercusMax
I think "desire for automation" is in the right direction, but doesn't quite
hit the mark. For me, it's more like "not wanting to solve the same problem
twice". I don't really care if it's automated or not, but once I've solved a
problem I don't want to think about it again (unless there's some new twist).

At my last job I was always getting bugged by support people asking me the
same questions over and over. So I wrote documentation/guides telling how to
solve the common issues.

TL;DR: it's not so much "robots are awesome" as "ain't nobody got time for
that!".

------
SwellJoe
I find it disheartening how much people trash talk Perl, while other languages
that are _extremely_ similar (JavaScript, Python, Ruby all share much more
with Perl than they do with, say, Haskell or Go or ML), get a pass. It's
become trendy to do so, to the point where people who clearly have never
learned Perl or worked with it feel entitled to speak with authority on it.
Taking it to the point of dismissing anything Perl's creator has ever said (as
one of the commenters on this wiki page does) is absurd and means not
listening to an extremely bright technologist (I mean, c'mon, Larry invented
patch, the basis of a tremendous amount of awesome in modern software
development!).

There are misfeatures in Perl, certainly, but there are roughly as many
misfeatures in JavaScript. It's silly to dismiss it as "awful" when there's so
much that is clearly nice about the language for many categories of problem.

~~~
hangonhn
I loved Perl when I first learned it. I loved it for the same reason I love
Python now. It's very easy to express ideas I have in mind without worrying
about the details. It's a great prototyping (as in prototyping ideas, not as
in the type system) language. It was my introduction to "higher level"
languages. That said, Perl suffers from having too many magical operators that
makes it hard to reason about a snippet of code. I feel Python strikes the
right balance.

Your comparison to Javascript is apt but I think a lot of us also find
Javascript to be a bit of a horror. Recently I learned that Javascript doesn't
handle modulus on a negative number correctly among other things.

~~~
adrusi
_Perl suffers from having too many magical operators that makes it hard to
reason about a snippet of code._

Certainly a matter of personal preference, but a sprinkling of operators isn't
so bad once you're acquainted with the language. Yes it's possible to weave a
mess in perl, but most of the time you're just dealing with code that might
have a few sigils preceeding an identifier, not ASCII soup.

I'd say the real issue is weak typing (implicit conversions between
primitives, using strings for many things where some more specialized data
type would have been more appropriate) and variable scope problems. These can
lead to hard to locate bugs. Worse is the culture in the perl community of
manipulating the VM's internals and generating code at runtime and all kinds
of other extremely dynamic behaviors. It's amazing what perl lets you
accomplish there, but when some package you got off CPAN does something weird
and then something goes wrong, it can get really weird.

 _Recently I learned that Javascript doesn 't handle modulus on a negative
number correctly among other things._

That's not really true. Javascript doesn't have a modulus operator, it has a
remainder operator, and it is completely valid as a remainder operator. The
"%" operator is usually called the modulus operator, but it originated in C
where prior to C99 its behavior on signed integers was undefined, and on
signed integers modulo and remainder are equivalent. So javascript didn't want
undefined behavior so they picked one definition and ran with it, it just so
happens that C99 chose the other definition and it stuck.

~~~
jbert
I'm interested in the details of the variable scoping problems are. I'd have
thought that perl's explicit declaration of lexicals with 'my' was better than
"declare at first use" of javascript/python/ruby.

[There's a class of mistake where you typo a variable name which you can make
in those languages which gets caught in a language where you have to declare
variables.]

~~~
SwellJoe
I share your confusion over that assertion. I actually miss Perl's excellent
block scope capabilities when working in almost every other similar language.
I imagine most other languages have gotten it, by now, but a few years ago
when I was using Python for a few years for a client it didn't have block
scope and I missed it. A brief googling actually hints that maybe Python still
doesn't have block scope, which is pretty weird, so I assume I'm googling
wrong.

But, perhaps discussion of scope problems in Perl is just when talking about
very old code. Perl had some scope atrocities back in Perl 4 and some
weirdness in early Perl 5 days. But, for the past 15 years or so, it's been
very predictable and has improved (like the syntactic sugar of "my"
declarations in foreach or while expressions).

~~~
fanf2
One weirdness I encountered recently with nested functions:

    
    
      sub a {
        my $v;
        sub b {
          # captures only the first
          # instance of $v
        }
      }
    

This is because named subroutines are created once and variable captures are
resolved at that time. I expected the more normal capture semantics you get
with anonymous subs, like

    
    
      sub a {
        my $v;
        my $b = sub {
          # a new $b each time
          # captures each $v
        }
      }

~~~
AdieuToLogic
The lexical scoping rules are precisely what causes this behaviour. The first
example defines a nested function which has access to the variables in scope
when defined (as you remark).

It's little different than this block defined outside of any function:

    
    
      {
      my $v;
    
      sub b { ... }
      }
    

Whereas an anonymous function is "defined" each time the enclosing scope is
evaluated.

For more info, see:
[http://www.perlmonks.org/?node_id=389319](http://www.perlmonks.org/?node_id=389319)

HTH

------
amelius
I'm not sure if laziness is a virtue of a programmer. Often, writing the
program takes a lot more work than the actual use (by that particular
programmer) of it would warrant.

Take for example the developers of a word processor. Would all that effort
spent on that office-automation software really cancel against the probably
few letters and/or documents that a developer would write using it?

------
AdieuToLogic
I was going to click the link, but it takes way too much time to RTFA and I
already know where this is going to end up.

Too soon?

~~~
raiph
I got it even if no one else did. :)

~~~
AdieuToLogic
Vielen dank!

Getting hammered by the votes was quite disheartening. I assumed indirect
reference to one of Larry Wall's most famous quotes would be obvious.

Ah well, I guess what happens when I "assume" is it makes an ass out of micro-
me ;-).

