points by dang 6 years ago

Peter Naur's classic 1985 essay "Programming as Theory Building" argues that this is because a program is not its source code. A program is a shared mental construct (he uses the word theory) that lives in the minds of the people who work on it. If you lose the people, you lose the program. The code is merely a written representation of the program, and it's lossy, so you can't reconstruct a program from its code.

https://news.ycombinator.com/item?id=10833278

https://news.ycombinator.com/item?id=7491661

Waterluvian 6 years ago

Thanks for sharing this. I've been looking for this for a long time to replace my own poor attempt at saying the same:

The code you write isn't the hard part. It's not the interesting part. And it's not really why you're paid. What I'm trying to imbue into you is the discipline to design and document and plan for the future. Saying you can "whip up a script this afternoon" is not impressive or commendable. It does harm without the other pieces.

  • closeparen 6 years ago

    Here's the thing: when I see people spend all their time on design discussions and documents, their work isn't any better for it. Usually it's worse. The documents are not clear or helpful. The designs encoded therein are not better than the first pass knee-jerk thought. The points raised in reviews are just bikeshedding. The process encourages explosion of complexity, making mountains of molehills, and sometimes can be a refuge for people who don't actually have the skills to hide out in. I do very much respect when someone can plop down some working code this afternoon vs. organize an 8-person kickoff meeting next week.

    If it's a genuinely large project, the working code is a skeleton POC, and we can run a design process using what we learned from it. But most of the time it's not, and that engineer has saved us collectively hundreds of hours of waste talking to death something that just isn't that hard.

    I think one of the critical senior engineer skills is having correct intuitions about how much time and energy should be sunk on a particular task. Sometimes that means asking people to slow down, collaborate, and think. Equally often, it means asking them to put down the calendar invites, make a choice, and bang something out. We have this bizarre cost model where code is expensive and meetings are free; nothing could be further from the truth.

    • EliRivers 6 years ago

      The best software I ever worked on - software in which the customer never reported a single bug, and every requirement was met - could not have been done without the documentation. The documentation was part of the process of creating the software - the larger part, really.

      Requirements, design, implementation, testing; all documented thoroughly, all reviewed and checked, each stage linked clearly to the previous and the next. One could literally trace a requirement from the requirements documentation, through the design, into implementation (which was done using literal programming, producing beautiful PDFs for humans to read - there was very little need for anyone to ever actually look at the actual pure Objective-C code that was fed to the compiler), and then onwards to testing, such that each individual test was linked to proving given requirement(s) that had been written down at the start; sometimes years previously.

      The customer was so impressed that they asked us to take over from another supplier whom they were busy suing for lack of delivery of a piece of the same system. Our software was delivered on time, exactly to spec, fully documented from requirements to design to implementation to testing. The whole project ran for most of a decade.

      It certainly wasn't easy. It required rigor and discipline and review panels and, I gather, somewhere between ten and twenty years' experience of creating software like that. It worked; the only software I've ever worked on in which the customer never reported so much as a single bug. The entire system could be completely understood down to the level of the code by reading the documentation, and when changes were required, the software engineer would begin by reading the documentation and upon opening the literal style source file, would find it just as expected from the design. I've never seen anything like it before or since.

      They went all in, though, and took years to get there. One couldn't just take a modern, agile-style software shop and start doing this. It was culturally ingrained.

      I certainly agree that in other places, I've seen some truly awful documentation that hindered more than it helped. I've seen system diagrams literally consisting of a square box with "server" written in it. Protocol documents that contradict themselves on the same page. I once was double-checking the wiring diagram for a cradle for a processor board, and disagreed with the voltage of a single pin; it turned out I and the other chap read the exact same line of text from the board manufacturer and interpreted it in completely opposite ways - one of us interpreted it as meaning the pin should be grounded, the other that it should be connected to the live rail. The documentation was so bad we ended up having to go back to the manufacturer and get a human on the line willing to go on record with the correct value.

      • jdotjdot 6 years ago

        What company was this? I’d love to see a talk about how this worked

        • EliRivers 6 years ago

          This was a software specialist UK outpost of a second-tier US defence company, about a decade ago. They developed their process while an independent software company, and were subsequently eaten by that US defence company (before I joined) who had the good sense to leave them alone to do what they do.

      • rramadass 6 years ago

        >which was done using literal programming

        I presume you meant "Literate Programming" (one invented by Don Knuth)?

        Regarding this project, can you share some more details as to how everything was done from requirements to implementation? How were they seamlessly linked together?

        • EliRivers 6 years ago

          Yes I did mean that. We used noweb.

          Let me probe my memory...

          Requirements were developed first by the customer and our requirements specialists, working together. That was a big priority. Requirements were broken down into individual elements, examined for contradictions and ambiguities, they had to be discrete, they had to be testable, all that sort of thing. This required domain knowledge as well as just being thorough and having attention to detail. As one would expect when writing software, it turns out that if you don't know what it's meant to do, or you misunderstand what it's meant to do, the odds of building the right thing are very low. This is something I see very commonly in many software companies; it's very common to start building things without knowing what they're meant to do. Sometimes it's impossible to know at the start what they're meant to do, but I do wonder if we could be a little harder up front about demanding to know what it's meant to do. Agile seems to be a way to control against that risk; a way of building software without knowing at the start what it's meant to do but getting there by frequent course correction.

          Once written down and formally agreed by the customer, each little requirement was given a unique identifier. That unique identifier was carried through the design and implementation and tests. The literate programming techniques used and the format of the design documents and test documents typically mean that a sidebar on each page showed the exact requirements that a given section was implementing; an index would show all such places, so if I wanted to know how we were going to meet requirement JAD-431, I could look up all such pages and satisfy myself that the design met it, that the implementation met it, that the tests covered it. Reviews would involve someone having a copy of the requirements any given design or implementation was meant to meet, and ensuring that every one of them was indeed met.

          I remember printing out test documents, and executing them (including the build; each test document specified the versions of source code to be used and the tools used to build it, and often the exact build steps), and on each page where I signed and dated it to confirm that I had conducted the test and it had passed, there was a listing of the requirements being tested (or partly tested). That sure gives someone pause; when I signed my own name in ink to give my personal guarantee that the test passed and was all in order, I sure didn't accept any ambiguities or shoddiness. Those signed, dated test documents would get a double-check by QA and if that was the final test, sealed in an envelope with a signature over the seal, and securely stored against the customer performing a random inspection or against anyone ever needing to come back and verify that for a given version, at a given time, the tests did pass.

          If a requirement ever changed (which did happen, and we sure did charge for it!), it was thus easy to identify everything else that would need to change. The effect of the change would ripple through the design and implementation and tests, linked by the affected requirement unique identifiers; each piece thence being examined, updated and confirmed as once again meeting the requirements, with confidence that nothing had been overlooked.

          • 0x445442 6 years ago

            While I've really enjoyed your posts in this thread you're anecdotes do highlight something very important; quality software is expensive. Also, most clients, be they internal to the org or external don't really know what they want and certainly don't have the wherewithal to supply detailed, testable requirements up front.

            Where I think most shops touting "Agile" miss the mark is the customer collaboration part. Extracting the detailed requirements you've described would take a lot of upfront time and effort that I've found most "Agile" shops don't have the stomach for. Where the rubber usually meets the road is in "Grooming" sessions. These sessions are typically rush jobs to move Stories to "Ready for Dev" but what I've experienced is there's rarely adequate information to proceed to development after a typical Grooming session.

            • EliRivers 6 years ago

              most clients... don't really know what they want and certainly don't have the wherewithal to supply detailed, testable requirements up front.

              Very much so. To do this well, one requires something that is in very short supply; high-quality, competent customers.

          • rramadass 6 years ago

            Nice, it seems like a simple process done rigorously. No highfalutin buzzwords (compared to Agile/Scrum :-) but a systematic approach using commonsense/wellknown processes. In essence, a) Utmost focus on Requirements gathering b) Use Literate Programming techniques to weave Design and Implementation and possibly into Testing/QA c) Use a "primary key" throughout to trace everything to requirements.

      • Too 6 years ago

        What kind of software was this?

        I've been in a similar project where we would get beautiful requirements from the client and implement them flawlessly on time, every time. I've also been puzzled by this a lot and wonder why other projects can't be the same. The thing missing from the story is the complexity of the software and how long the client spent upfront on designing those requirements before handing them off. This was very trivial applications with few states, no UI and clear input and outputs, nowhere near a big modern web service. If our implementation was according to spec but not what the end customer really needed it would still not be counted as a bug, it was the clients responsibility for writing a bad spec, the client was very much aware of this so we also hardly ever got any bug reports in that sense.

        It was waterfall it a nutshell, assuming the first design is correct and resource optimizing every step of the way for it. You couldn't replicate that process onto an app with a big UI footprint and quickly changing requirements which requires more iteration rather than upfront design.

      • 0x445442 6 years ago

        > It certainly wasn't easy. It required rigor and discipline and review panels

        In other words, it took... engineering.

    • Waterluvian 6 years ago

      I hear you. But I'm not convinced that there's ever an okay time to skip writing down design, requirements, etc. Even if they're rough in a wiki page and it takes 30 minutes. It simply doesn't belong in your head alone.

      I'm certainly not advocating for adding insane amounts of process to little jobs. But show your work. It's worth most of the credit.

      • closeparen 6 years ago

        Sure, the author needs to write things down; often commit messages and block comments are enough, sometimes more is needed. If anything we are heavily under-invested in solo documentation-writing.

        What drives me up the wall is starting a long, formal document and having a bunch of meetings about it, seeking input and consensus from 10+ people and committees, for something with the scope of a couple days. That process is designed for large, multi-engineer-month new systems, or decisions that will be hard to back out of and have ramifications for hundreds of people over years. But I often see junior engineers putting the wheels in motion for basic day-to-day maintenance and feature iteration tasks.

        It doesn't help that our promotion process incentives this heavily, because it generates lots of evidence for the committee to evaluate.

  • dang 6 years ago

    I think Naur would say that design documents can't capture the program any more than the source code does. The program lives in the minds of the people who make it. It's like a distributed system with no non-volatile storage. When the last node goes down, end of system.

    • kd5bjo 6 years ago

      Yes, he says this pretty explicitly in the essay. Some relevant excerpts:

      "Programming in this sense primarily must be the programmers' building up of knowledge of a certain kind, knowledge taken to be basically the programmers' immediate posession, any documentation being an auxiliary, secondary product." (emphasis mine)

      "The death of a program happens when the programmer team possessing its theory is dissolved. A dead program may continue to be used for execution in a computer and to produce useful results. The actual state of death becomes visible when demands for modifications of the program cannot be intelligently answered."

  • 0x445442 6 years ago

    But we "Value working software over comprehensive documentation".

im3w1l 6 years ago

I don't fully agree with that, I mean a program will keep running even if no one knows how it works anymore. But yeah knowing how it works and why is highly valuable and expensive to restore if lost.

  • rxhernandez 6 years ago

    > I mean a program will keep running even if no one knows how it works anymore.

    Not if it doesn't compile anymore because of a switch in hardware. I've seen this firsthand; same exact code but results were off by an order of magnitude.

  • greenyoda 6 years ago

    As Naur pointed out in his article, just keeping the existing program running in its original state isn't enough. The program reflects the needs of the people using it, and those needs evolve over time.

    For example, the software that runs a bank needs to be constantly updated to comply with current laws and regulations and to support the new types of accounts and services being offered by the bank. Over time, customers wanted to have access to their accounts through ATMs, then over the web, and later via mobile apps.

caseymarquis 6 years ago

Sounds like Platonic Forms[1], but for applied computer science.

Skimming Naur's essay, the solution to this problem seems like it could involve building higher level code analysis into the language itself (making the linter part of the language and development environment).

Microsoft is doing this to some degree with compiler extensions on the .NET platform [2]. When used creatively, you can effectively deploy a custom linter with your libraries which emits compiler errors and warnings based on how the user is doing things (ie I think you're trying to do X, have you considered using this new functionality instead?). However, I think it is interesting to consider what it would look like if statically typed code and style analysis/suggestions were a first class citizen in a programming language, not just an add on for advanced users. If this exists now, I'd love to check it out.

It's too bad we won't all live to see the inevitable improvement in computational notation over the next few hundred years. Time to binge watch some Alan Kay talks and try to imagine it.

[1] https://en.wikipedia.org/wiki/Theory_of_forms [2] https://docs.microsoft.com/en-us/visualstudio/code-quality/r...