
Going Fast Slowly - chatmasta
https://varnish-cache.org/docs/6.2/phk/thatslow.html
======
pdonis
From the article: "I no longer think about code lines as an asset to be
accumulated, but rather as an expenditure to be avoided."

The obvious Edsger Djikstra reference:

 _[I]f we wish to count lines of code, we should not regard them as “lines
produced” but as “lines spent”: the current conventional wisdom is so foolish
as to book that count on the wrong side of the ledger._

[http://plasmasturm.org/log/linesspent/](http://plasmasturm.org/log/linesspent/)

~~~
lucideer
Chiming in to say I agree with the sibling (dead) comment (not sure why it
ended up dead).

Djikstra's words (and the article's) are clearly correct, but hardly
revolutionary or contrary to modern belief today.

The real question is: why, despite a prevailing belief in modern software
software engineering that red diffs are beautiful and cathartic things to be
celebrated, and that the great spectre of technical debt is something to be
excised, why do complex overengineered systems still prevail despite all this?

~~~
thaumaturgy
Software-as-art has lost a lot of ground to software-as-business, and in
software-as-business, somewhere up the chain there is a management-level
individual who isn't really sure how to measure either progress or code
quality.

There are myriad tools designed for these people though, and they all chose
the simplest (and wrong) solutions to the problem: progress is SLOC added and
bug reports clsoed per day.

The height of the software-as-art era was the shareware days of the late 90s.
Development certainly moved a lot more slowly overall, but there also tended
to be better relationships between developers and their users and developers
were not yet all working for people who tried to measure their progress by the
only metrics they could understand. The entire industry has been a victim of
Goodhart's Law.

~~~
jamesb93
Do you have any suggested reading around software as art vs business? You
pretty much began to articulate the things I've been thinking about lately.

~~~
thaumaturgy
I wish! If there's a good book out about it, I'd love a recommendation too. I
lived it though, writing my first "software" as a youth in the mid-80s. I've
seen a lot of change in computing. And not all "get off my lawn" bad, just
different.

I see software now as having three different faces: software-as-art, software-
as-business, and software-as-engineering. The 80s and 90s had a lot of
activity in software-as-art. I was mostly following Mac culture at the time,
so I saw this through Bungie, Ambrosia, BareBones, and hundreds of smaller
indie developers. The environment at the time enforced the software-as-art
discipline, because downloading a program happened over 14.4kbps or slower, or
28.8kbps if your parents had good jobs, and came along with yelling that often
sounded like, "get off the phone!" "But I'm downloading!" Installation media
was 700K or 1.4MB, and that had to have all your code, art, sound, and other
resources.

That's mostly all gone now. Bungie of course got married to Microsoft, which
pissed off Mac enthusiasts _way_ more than when Jobs announced a partnership
with MS to get Office on the Mac. They've done well. Panic are the only old-
school indie commercial desktop software developers I can think of off the top
of my head that are still pretty true to their roots.

A lot of software of course just became free. I enjoy so much more high
quality software at no cost now, which is really only possible because of the
massive benefits of scale that have come from all the tools that have trickled
down from software-as-business.

Software-as-business really took off. Apple, Microsoft, Sun, Oracle and others
were always kinda big, but not the impossibly large megacorps that they are
now. Most of them were still vulnerable to serious mistakes, and that was
good, because it meant the users still had some power. Now, mistakes in
software development don't really matter to these companies unless they impact
8 figures of quarterly revenue, and that's a process that has zero room for
software-as-art.

Software-as-engineering is mostly stillborn, languishing in academia or a few
places with rigorous standards (like NASA) or still finding its footing in
modern DevOps. I still hold out hope that eventually this aspect will get some
love too. I think it will be necessary, eventually, but maybe not until after
I've written my last line of code.

------
jchook
“Slow is smooth, and smooth is fast”

Old military saying that I repeat often because I have relearned so many times
that shortcuts cause more work (read: problems and rigidity) in the long run.

Choose one: get it done right, or get it done right now.

~~~
tunesmith
Or from my mom: "The hurrieder I go, the behinder I get!"

EDIT: Apparently my mom is Lewis Carroll.

------
haasted
Footnote 6 is interesting:

 _“I prefer asserts over comments for this, since the compiler can also see
them. The good news is, the compiler can also see that they don 't do anything
so a lot fewer are present in the binary program. Interestingly, a couple of
them allows the compiler to optimize much harder. No, I won't tell you which
those are.”_

I appreciate the pattern of having “comments” that are equally useful to
compiler and reader. And I’m impressed that some compilers actually use them
to optimise the output. And I’m slightly baffled that the examples of these
are apparently a secret. :)

~~~
FreeFull
In Rust, an assert can turn multiple bounds checks on array indexing into just
a single bounds check. Maybe it's something along those lines here too.

~~~
drewm1980
Interesting! Do have a link to an example?

~~~
FreeFull
Given the following code (and with optimisations on):

    
    
        pub fn no_assert(input: &mut [u8]) {
            for i in 0..10 {
                input[i] += input[i+1];
            }
        }
    
        pub fn with_assert(input: &mut [u8]) {
            assert!(input.len() >= 11);
            for i in 0..10 {
                input[i] += input[i+1];
            }
        }
    

The no_assert function ends up doing a bounds check for every iteration, and
the with_assert function only does a single check.

~~~
tudelo
Still that assert has to be checked at some point right? I would assume that
maybe the compiler could do this optimization without having to be told.

~~~
FreeFull
In practice a small function like this would be inlined, which gives room for
further optimisations. At any point, if the compiler knows that all accesses
are in bounds, it can remove the bounds checks. The trick is actually having
it figure that out.

------
jpm_sd
The strategy of "making haste slowly" dates back to the Roman empire (or
earlier!), where they said "Festina lente"

[https://en.wikipedia.org/wiki/Festina_lente](https://en.wikipedia.org/wiki/Festina_lente)

This was also used as a catch-phrase or motto in "Mr. Penumbra's 24-Hour
Bookstore", which is a fun read, especially if you're familiar with the
Silicon Valley tech scene.

[https://en.wikipedia.org/wiki/Mr._Penumbra%27s_24-Hour_Books...](https://en.wikipedia.org/wiki/Mr._Penumbra%27s_24-Hour_Bookstore)

------
bt848
10 LOC/h is spectacularly good over a long time period. Congratulations, from
a varnish user.

I recently tried to set expectations in a coding interview that was scheduled
for 3 hours. I told them that was enough time to read the spec, develop a
simple test case, and begin or possibly complete an implementation of part of
the spec. I also told them that I wasn't interested in a shop that hired
people based on their ability to dash off broken, untested code in half a day.
It seems to me that this kind of coding test (especially for someone with 25
years of open-source contributions) can only lead to bad things. I'd be glad
to meet people like the author who have a practical view on Brooks and LOC/h.

~~~
josephg
I've been doing tech interviews professionally for a large tech interview
platform that you would have heard of. We have a timed coding challenge, but
code quality is something we explicitly look for. Making slow but steady
process with good testing is a great signal for us too, even if they don't get
very far through our challenge within the allocated time.

That said, occasionally we have people who work very quickly and somehow still
have great code. Thats an even better signal.

~~~
p1necone
I hope it's communicated that they're not expected to finish. If I was given a
coding challenge with a time limit I would assume I was expected to finish
inside the time limit and make any sacrifices that needed to be made to
achieve that - including ignoring testing and hoping I just don't make too
many mistakes.

~~~
aidenn0
Assuming GP is talking about what I think he is, then yes they tell you ahead
of time.

------
nineteen999
> This is why Varnish is written in "pidgin C" style and lousy with asserts
> which don't do anything, except clarify programmer intent, and in case of
> mistakes, stop bad things before they get out of hand.

Today I learned a new name for my C coding style.

~~~
jacquesm
'Assert early and often'. Check your assumptions all the time, nine out of ten
times that's where your bugs will hide.

~~~
nineteen999
My C programs always start as a few skeleton .h files with include guards, and
a few .c files that are basically an ever growing list of asserts() on any
pointer to a structure or variable, or on any value where it is expected to be
within a certain range.

Gradually I feed my structs and typedefs into the .h files and replace the
asserts with (hopefully) working code.

------
zokier
About the numbers, I feel like going through the commit diffs and counting all
the + lines would be better (in some sense) metric than counting the final
lines of code if we'd want some proxy for the amount of labor.

~~~
nemo1618
Indeed. Reminds me of arcfide's Co-dfns compiler:

>I think the first copyright on this compiler is around 2011. That's 6 years
for 750 LoC. That's about 125 lines of code per year.

>But that doesn't tell the whole story. If you look at the GitHub
contributions that I've made, I've made 2967 of about 3000 commits to the
compiler source over that time frame. In that time I've added roughly
4,062,847 lines of code to the code base, and deleted roughly 3,753,677 line
of code. And there's the real story...It means that for every one of those 750
lines, I've had to examine, rework, and reject around 5400 lines of code.

[https://www.sacrideo.us/smaller-code-better-
code/](https://www.sacrideo.us/smaller-code-better-code/)

~~~
kardos
Is this [1] the code he speaks of?

[1] [https://github.com/Co-dfns/Co-
dfns/tree/master/cmp](https://github.com/Co-dfns/Co-dfns/tree/master/cmp)

~~~
jacquesm
It's an APL compiler, written in another APL dialect, which is about as dense
as you can get in terms of lines-of-code. APL is one of the few really high
level languages.

~~~
jeremyjh
It looks like a lot of the lines of diffs are to HTML/XML files related to the
certification of the code, rather than executable code. So, definitely not
very dense.

[https://github.com/Co-dfns/Co-
dfns/commit/78d0e38f8ba2e1de9f...](https://github.com/Co-dfns/Co-
dfns/commit/78d0e38f8ba2e1de9f2b0e9ec22df4e1f17f4fe6)

~~~
arcfide
Here's a rendered version of that document at some point in time:
[https://1drv.ms/b/s!AvaVLzoc2_8MiNdqkVZ1ScoRjYeOZQ?e=ApQSFw](https://1drv.ms/b/s!AvaVLzoc2_8MiNdqkVZ1ScoRjYeOZQ?e=ApQSFw)

I notice that my discussion about the churning on the GitHub repository has
been repeated a number of times. I can provide some historical clarification
on why there was so much churning there.

The actual compiler proper as it stands right now is found here:
[https://github.com/Co-dfns/Co-
dfns/blob/master/cmp/e.cd](https://github.com/Co-dfns/Co-
dfns/blob/master/cmp/e.cd)

The documentation for those 17 lines of code are in a hopefully soon to be
published thesis of about 70k words that includes performance information and
the like.

However, during the development of this project, I didn't start writing it in
APL on Dyalog. I explored a significant number of other architectural designs
and programming methodologies. Some more popular I tried were habits like
Extreme Programming, Agile methods, Java, Scheme, Nanopass, SML, Isabelle, and
even a custom extension of Hoare Logic on top of dfns. I believe that I also
explored implementing the compiler in C++/Boost and prototyped some stuff (I
don't know if it ended up in this Git repo) and C.

In other words, the compiler has not been a single code base, but has been a
series of complete rewrites using different methods, approaches, languages,
techniques, and architectures. I have used heavyweight machine support (mostly
around C++ with Visual Studio's infrastructure) as well as some very hardcore
UNIX style low-level handiwork. Multiple different IDEs, text editors, and
operating systems were all explored, as were multiple different backends,
targets, and the like. At one time I had targeted LLVM, and another C, another
OpenACC, and another ArrayFire.

The whole project has been a somewhat wide ranging exploration of the design
space, to say the least.

What you are seeing of the XML stuff was from a particular design effort that
was an attempt to apply strict Cleanroom Software Engineering as a methodology
to the compiler design, to see what would happen. In the end, I abandoned the
attempt, for what I hope will be obvious reasons, but during this time, I
predominately worked on RHEL with the ed(1) text editor editing XML files for
the DocBook publishing suite. Parts of the churning are the incorporation and
removal of various dependencies that had to be brought in and out of the
repository depending on what infrastructure I was relying on. In the case of
DocBook, some of those files are large.

However, a significant amount of the work of Cleanroom Software Engineering is
"coding via documented process." This includes the certification steps as well
as the function specification, increment development, sequent analysis, and so
forth.

Thus, for a very real portion of the Co-dfns work, I was literally programming
in XML using ed(1) to model relatively complex state machines and function
specifications that provided very fine-grained behaviors of the compiler. For
example, a significant amount of work went into the following file:

[https://github.com/Co-dfns/Co-
dfns/blob/92e07bd84b5c8be08e2f...](https://github.com/Co-dfns/Co-
dfns/blob/92e07bd84b5c8be08e2f6d46a70d8e6d69ac7142/Function%20Specification.xml)

This file is about 45k lines of XML, and was written and edited entirely by
hand using ed(1). I had a video demonstration of this a while back which
demonstrated how I did this, and particularly how I did a lot of this with
ed(1), but I lost the script file recording.

Over time, as I continued to explore patterns and development approaches, I
continued to discover that the code was faster, better, and easier to work
with as I removed more and more "stuff" from the various processes and
possibilities.

It wasn't until relatively late in the game that I actually realized that not
only could the compiler be written in dfns well, but also that the compiler
could be written in dfns in a way that was fully data parallel, which is the
core insight of my Thesis. This had significant ramifications on the source
code, because it meant that the compiler could not be tackled not only as a
self-hosting project (at least in theory) but also in a fundamentally
idiomatic way.

The result is that the compiler has generally continued to be more featureful,
less buggy, and more dense at each major stage, with the latest leading to 17
lines of code. This is accomplishing essentially the same result as the 750
lines of code in a previous HN discussion, but does so partly by recognizing
some passes as irrelevant and unnecessary to the current needs.

I do expect that after the publication of the thesis, the compiler will grow a
little bit to add some new things that need to go in. However, at this point,
I have a fairly efficient methodology.

So, the GitHub repository is not just a record of the code, but a record of a
lot of different approaches to how to do what I was trying to do. Much of that
XML you see was very much "coding" in the sense that I was providing for the
core behavior of the system and was the primary specification of its behaviors
in a formal, rigorous manner.

~~~
arcfide
Oh, and yes, a few times I did in fact explore programming in Word as well.
Just as an example:

[https://github.com/Co-dfns/Co-
dfns/tree/13e2624d6f5897a0f0c9...](https://github.com/Co-dfns/Co-
dfns/tree/13e2624d6f5897a0f0c97bdc2b6b788b394aaa4e)

I did also explore more traditional approaches, of course, but I have spent a
lot of time exploring the "form" of representing the code.

------
314
While it is true that SLOC is not a good measure, this does not mean that no
good measure uses SLOC. Much of the variance comes a lack of information about
coding style and algorithmic approach. But it's not the 90s anymore. In the
presence of a style guide _and_ code reviews to ensure that the local style is
being followed properly SLOC counts do become locally comparable as a
reasonable measure. I'd still use the churn rate (lines added + line removed)
as a rate of productivity though, over just lines added.

------
kevinb7
I wonder if this project, at least VCL compiler part of it, could've benefited
from the use of a parser generator. I understand going slow, but using a
parser generator would've allowed for faster development of VCL freeing up
time to add more features so it isn't so hard to write for.

------
tanchoux
Slow enough to not offer Varnish for Buster, 2 months after Debian release...
;-)

~~~
xemdetia
What are you talking about that they did 'not offer Varnish for Buster?' Was
there a packaging problem or more context you could add here?

~~~
nobodyusing
It looks like Debian 10 (Buster), which was released 2019-07-06 contains
Varnish 6.1 instead of 6.2, which was released 2019-03-15.

~~~
693471
6.3.0 is already out...

~~~
tanchoux
Since 2 days yes, but not for Buster.

~~~
josephg
Its opensource and maintained by volunteers. If this matters to you, don't
whine on HN. Write a PR.

