[HN Gopher] Code only says what it does
       ___________________________________________________________________
        
       Code only says what it does
        
       Author : mjb
       Score  : 95 points
       Date   : 2020-07-06 16:41 UTC (6 hours ago)
        
 (HTM) web link (brooker.co.za)
 (TXT) w3m dump (brooker.co.za)
        
       | deeg wrote:
       | When I teach coding I tell the students to document their code
       | well but don't document _what_ the code is doing it. That should
       | be evident from the code itself (if it 's not, then consider a
       | refactor). Rather, explain _why_ the code is doing it.
        
       | sosborn wrote:
       | The marketing corollary is that metrics only tell you what
       | happened, they cannot tell why. Yet somehow, entire companies
       | have been built on the promise that they can answer the "why" by
       | looking at the metrics.
        
       | ChrisMarshallNY wrote:
       | I comment my code[0].
       | 
       | I don't particularly care what people think about it.
       | 
       | I will say that I have turned over a _lot_ of code, over the
       | years, and virtually _never_ get asked about what it does. When
       | people ask me about my code, I generally tell them where to look,
       | and contact me if they need explanations.
       | 
       | I don't get contacted, so I guess they could figure it out.
       | 
       | I also tend to write a lot of supporting documentation.
       | 
       | We do have to be careful, though. Documentation can easily become
       | "concrete galoshes"[1], so things like header/auto documents are
       | pretty important.
       | 
       | [0] https://medium.com/chrismarshallny/leaving-a-
       | legacy-1c2ddb0c...
       | 
       | [1] https://medium.com/chrismarshallny/concrete-
       | galoshes-a5798a5...
        
       | ChrisSD wrote:
       | A big issue with documenting what the code does is that the code
       | and documentation can very quickly fall out of sync. As this
       | posts says, it's much more useful to document the intent of the
       | code, or _why_ there 's this mess of seemingly hacky code (see
       | issues #80681, #82108, #66065).
       | 
       | Also be wary of unit tests that are overly tied to the specifics
       | of an implementation. These can be worse than useless when it
       | comes to changing code. I.e. asking "why are my tests failing?"
       | and finding out it's only because I breathed near the code.
        
         | mrkeen wrote:
         | System tests too!
         | 
         | The last code-base I worked on had do-everything system tests
         | (with unexpectedly good coverage, I'll admit). They were so
         | slow and passed often enough that I didn't immediately spot
         | flakiness.
         | 
         | I got suspicious when the tests started failing regularly when
         | I added new unrelated code.
        
       | saagarjha wrote:
       | About the only time I use comments are to delineate a block of
       | code that for whatever reason can't be a method or because I am
       | working around some bug and I think I might be tempted in the
       | future to remove that code as "useless". (Think "the
       | dispatch_main here ensures that the code runs on the next runloop
       | iteration, which is necessary for the animation to work".)
        
       | cloogshicer wrote:
       | The huge value that I see in a formal specification language like
       | TLA+ is that we could have a precise way of communicating the
       | problem in a way that is agnostic to the implementation language.
       | 
       | Imagine something like StackOverflow, but instead of posting a
       | question, you post a formal spec. Thinking even further, you
       | could then find a way to combine/interface these specs and build
       | something like a global database of computational problems.
       | 
       | We're currently doing this already with StackOverflow, but we're
       | focusing on the implementations, not the problems themselves.
       | 
       | Please correct me if there's a mistake in this line of thought,
       | I'd love to know.
        
       | trixie_ wrote:
       | If I had a nickel for every programmer who thought their code was
       | so good it didn't require comments... or thinks somehow that unit
       | tests make up for comments... only to come back years later and
       | have no idea why the logic is working how it is.
        
         | dnautics wrote:
         | It's a matter of judgement. I've read code in languages I don't
         | know, even, where I could immediately figure out what was going
         | on without reading any comments. I've also patched libraries in
         | ten minutes without reading comments. It's certainly possible
         | to write code that doesn't need comments, though perhaps, we're
         | not the best people to judge when that's the case or not for
         | our _own_ code.
        
           | trixie_ wrote:
           | Same here. Though if you are putting thought into the code
           | you are writing - the logic, the structure, etc.. Then those
           | thoughts should probably be written down as well as comments.
        
         | baddox wrote:
         | It seems to be fairly common for experienced programmers to
         | point to unit test code as a way to explore or understand an
         | open source software project. I don't doubt that this works for
         | them, but it definitely doesn't work for me. When I'm trying to
         | explore a new software project, the first thing I want to do is
         | find the relevant "entry point," which is arguably the exact
         | opposite end from the unit test code.
        
           | henryfjordan wrote:
           | Tests that target the surfaces of the project (public APIs,
           | endpoints, etc) and code examples start to blend together at
           | some point. "Here's a basic example that should do X" sounds
           | a lot like "Do something basic and assert it does X".
        
             | DreadY2K wrote:
             | One thing that I like about Rust is that they actually
             | allow you to merge those two into one. In your
             | documentation of anything, you can include code snippets,
             | and those code snippets become tests that can ensure that
             | the documented behavior still applies to the current code.
        
             | baddox wrote:
             | I think the biggest problem with using unit tests for this
             | purpose is that unit tests tend to (rightfully) spend a
             | disproportionate amount of lines of code on edge cases.
        
               | dllthomas wrote:
               | Where applicable, this is what doctests are for, and
               | they're magical. ... where applicable.
        
             | dfinninger wrote:
             | Yes, this is how I use them as well. I'll go to the unit
             | tests after I have a decent understanding of the project
             | and am looking for examples that aren't covered in the
             | README.
        
         | selykg wrote:
         | This was a thing at my last job. The lack of comments always
         | made me cringe. While not every line needs a comment, there's a
         | reason why comments would be useful, especially in security
         | software.
         | 
         | I learned a lot of bad habits there and I'm glad I no longer
         | work there.
         | 
         | Their excuses were literally "no one reads comments" "no one
         | keeps comments up to date" "my code is self documenting" etc.
        
           | trixie_ wrote:
           | The self documenting one always gets me. It's not like the
           | person has never read code that is difficult to understand.
           | 
           | Yet they think it is just other people who write 'bad' code.
           | Their own code can't possibly be bad. In fact it is so good
           | that it 'documents itself'. It's just a statement that drips
           | with arrogance.
        
             | selykg wrote:
             | Ya, but with a security product there are important
             | considerations and while we commented on areas where we
             | fixed a bug due to something fixable, it was a pain in
             | general.
             | 
             | Decisions maybe don't belong in code but with a security
             | product I feel there has to be some quality level of
             | comments to explain why and how. Someone coming along later
             | can't be expected to be in the authors head and the author
             | won't remember all this stuff years later when it might
             | matter or need to be rewritten.
             | 
             | Such a shit show
        
         | tigershark wrote:
         | Clear code and clear tests absolutely don't need comments that
         | explain them if they are really clear, at least for me.
         | Comments are extremely useful to explain something unexpected.
         | Commit messages are too limited to explain properly a use case,
         | but linking to a Jira with the proper explanation does the
         | trick. From the tests you can see both the typical use cases
         | and the correct way of using some piece of code and have a
         | guarantee that the code respects the specification. With the
         | comments you have none of this guarantees. I had the opposite
         | experience from you apparently, the people that I worked with
         | that used excessive comments were not up to par with the rest
         | of the team. Also it may related to the mental model, comments
         | just break my flow and make more difficult for me to read the
         | code.
        
           | trixie_ wrote:
           | Right you are exactly the kind of person I'm talking about.
           | You think your code is clear. It is not. The logic your code
           | performs is the distilled by-product of higher level
           | reasoning. Reasoning that should be the basis of your
           | comments.
           | 
           | People reading your code will not be in the same mind state
           | that you were in when you wrote it. That is what the comments
           | are meant to assist with.
           | 
           | If you write comments for anyone, write comments for yourself
           | first. You will not remember years from now the reasoning
           | that went into the code your wrote.
        
         | [deleted]
        
       | sktrdie wrote:
       | What I've noticed is that code is the only medium of
       | communication that is non-ambiguous. Designers, product people,
       | stakeholders, etc, all use _ambiguous_ mediums. It's impossible
       | to understand just how pedantic and explicit you need to be when
       | writing code versus, say, giving your human colleagues
       | instructions.
       | 
       | So it's 0% ambiguity for code. 100% ambiguity for the rest. In
       | other words, communicating with the computer is overly pedantic,
       | and code bares all the frustration. Can we make it more fair?
       | 70-30 perhaps?
       | 
       | Rather than concentrating on mediums that help with communication
       | (as this post mentions: Design Docs, TLA+, comments...) I want a
       | new medium that allows me share the burden of overscrupulousity
       | with the rest of the people in my team, and not just developers.
        
         | webmaven wrote:
         | Pseudocode, perhaps?
        
       | rcshubhadeep wrote:
       | Here is little demo of codeBERT - https://youtu.be/oDqW1JHmaYY
       | 
       | codeBERT is trying to predict if a certain function and its
       | docstring are associated or not.
       | 
       | Thought about sharing it, I guess it is interesting in this
       | context
        
       | bob1029 wrote:
       | If you want your cake and also the ability to consume it, you
       | might want to consider what functional programming can do for you
       | regarding the ability of your codebase to self-document itself.
       | Having type systems that are very closely aligned with the
       | abstract business model is the best way to avoid frustration when
       | you are trying to figure out why something is the way it is.
       | 
       | The trick is understanding that functional vs imperative is a
       | spectrum, and trying to force 100% on one side or the other is
       | how you wind up killing any project. We find that keeping our
       | business-level abstractions functional with the underlying
       | infrastructure code imperative provides the best of both worlds.
       | The code that is changing and analyzed most frequently is in the
       | functional domain, whereas code that we touch maybe 1-2 times per
       | month lives in an imperative domain (but sometimes functional
       | wherever it makes sense here too).
        
         | ajuc wrote:
         | I find functional code much shorter and cleaner, but also when
         | you want to change something along a new axis you need to do a
         | much bigger rewrite than with imperative/procedural/object-
         | oriented code.
         | 
         | OO code: "here's a detailed and llong-winded description of
         | what happens that's hard to understand. Ignore 95% of it and
         | change that 1 little detail and hope for the best"
         | 
         | Functional code: "here's a concise and easy to understand
         | description of what happens, understand it fully, throw it
         | away, and create a new, just as clear and concise description
         | of what should happen from now on"
        
       | corbins wrote:
       | The counterexample here is the declarative style of programming.
       | Most ideally this looks like an executable spec and is
       | documentation itself.
        
         | lmilcin wrote:
         | Only for simple cases. When it becames complex enough the same
         | problems show.
         | 
         | Example: CSS.
        
         | ativzzz wrote:
         | Sure, but then you offload the complexity to the functions used
         | as the declarative building blocks, so you do the documenting
         | in a different place, though you will probably end up
         | documenting complex declarative business logic anyway. (like
         | why is process X that is so similar to process Y require Z
         | different declarative blocks)
        
       | voiper1 wrote:
       | Relevant: Writing system software: code comments. from
       | http://antirez.com/news/124 +
       | https://news.ycombinator.com/item?id=18157047
        
       | client4 wrote:
       | This article fits nicely with the recent post discussing how
       | Linus spends the majority of his time writing emails. For
       | projects with n+1 contributors, inter-contributor communication
       | is just as important as what code is being written. Emails,
       | commit messages, code comments, docs, are all just different ways
       | to communicate.
       | 
       | I always think of the Underhanded C Contest[^1] as my favorite
       | example of readable code that doesn't act as expected after a
       | quick read.
       | 
       | [1] http://underhanded-c.org/
        
       | dllthomas wrote:
       | Code is a mixture of what and how (and with IaC, sometimes who
       | and where).
       | 
       | I agree that "why" is the role of documentation. I've been
       | experimenting with tying the two together with (machine checked,
       | automatically surfaced) cross-references, so we can better know
       | what bits of documentation a test supports, &c. I haven't yet
       | gotten rigorous about it.
        
       | rawoke083600 wrote:
       | Ja to me the "rule-of-thumb" is still: "Code Is The How, Comments
       | Are The Why"
        
       | bryanrasmussen wrote:
       | Should we be looking out for lying code?
       | https://softwareengineering.stackexchange.com/questions/2023...
        
       | phendrenad2 wrote:
       | It gives me no end to pain that "Comments are lies because they
       | aren't code" is a fad that we're currently suffering through as
       | an industry. For decades prevailing wisdom was that comments were
       | a net benefit, and now in the last few years this trend has
       | become prevalent. How much perfectly-good code is going to have
       | to be rewritten from scratch in 10 years because no one remembers
       | what it does?
        
         | wanderr wrote:
         | If no one understands what it does, it's not perfectly good
         | code is it? Of course there are rare cases where code cannot be
         | simplified, made more readable or self explanatory and in those
         | cases comments are vital. But the aim should be for the vast
         | majority of code to be easily readable by humans.
        
           | Jtsummers wrote:
           | Essential versus accidental complexity.
           | 
           | Perfectly good code can be unclear because of the accidental
           | complexity included within it. Memory management, error
           | handling (especially in languages with less expressive type
           | systems), configuring hardware/database/network connections,
           | etc. Those things are important, but they prevent the
           | essential portion of the program from being expressed on its
           | own.
           | 
           | Type systems, a brief example: C versus Ada. Implement a
           | network protocol where the data packet has specific n-bit
           | sized fields with ranges less than the maximum for that size.
           | You can easily do this in both languages. But in C, you'd
           | either need to add bounds checking to all of those fields or
           | risk letting errors propagate. That error handling obscures
           | the essential portion of the program. In Ada, you make a type
           | that is n-bits and only accepts values of the correct range.
           | The errors can still exist in received packets, but the error
           | checking is partially elided from the code because the type
           | system itself can catch it.
           | 
           | There's nothing _wrong_ with the C code, and there 's nothing
           | _wrong_ (many will disagree with that) with choosing C to
           | implement the protocol. But it will increase the complexity
           | due to factors beyond the inherent, essential complexity of
           | the network protocol itself.
        
           | phendrenad2 wrote:
           | I mean it's "perfectly fine" because the people building it
           | know how it works (because they were there when it was
           | built), and think they don't need comments to help out future
           | maintainers.
        
       | softwaredoug wrote:
       | "works as coded"
       | 
       | My last job we used to say that if asked whether our code was
       | correct or bug free ;). Often the devs get thrown under the bus
       | if something doesn't work "correctly" when in reality it might
       | perfectly pass all unit tests based on the best understanding of
       | the problem.
       | 
       | Of course whether we could get any support to help define
       | "correct" from anyone was another matter...
        
         | xsmasher wrote:
         | This fits my theory of programming, and theory of bugs - We
         | take a problem, create a plan, and then write code that
         | implements that plan.
         | 
         | Defects can come from:                  * having/being given
         | the wrong problem             * right problem, but plan does
         | not actually solve it             * right plan, but your code
         | did not correctly implement it
        
       | bobbane wrote:
       | Any thoughts on applying this article to...
       | 
       | programming languages defined by a single portable
       | implementation?
        
       | aequitas wrote:
       | My pathway into software development was through electrical
       | engineering and embedded systems. So I don't know if this applies
       | to other ways into software development as well. But what really
       | stood out to me in the beginning was how useless code comment
       | where. I would almost always see code like this:
       | x = 1;      // assign 1 to x       y = x * 2;  // multiply x by 2
       | 
       | I don't know if it was because they thought electrical engineers
       | needed to be explained everything about code. Or if it was
       | because all teaching material used this style and people just
       | copied it. But I never understood why you would add comments like
       | this, but had to do so anyways otherwise I would not pass my
       | exams.
       | 
       | It took me a while to learn that comments are the tool in which
       | you can express your expectation of what the code should do.
        
       | ris wrote:
       | So many times this.
       | 
       | "Clear code shouldn't need comments" - clear code can make it
       | easy to see _what_ but it can never say _why_. Let me know what
       | corner cases you thought about when you wrote this.
       | 
       | "The comments are in the commit messages" - almost nobody _ever_
       | goes looking for them there, they 're effectively invisible from
       | `git blame` when they _remove_ lines, people rarely make fine
       | grained enough commits to be able to target specific lines or
       | blocks sufficiently with context.
       | 
       | "Nobody ever updates comments, so they're always out of date" -
       | don't hire such people. It is an crucial task _resolving_ the
       | meaning of comments to make sure everything still makes cohesive
       | sense. Neglecting to do this will often lead to commits that don
       | 't quite grok any subtleties of the original design. Don't make
       | the _reader_ of the code do the job of trying to piece together
       | the scattered history of 5 different people 's intentions. Of
       | course, it's also useful to try to keep comments as close to the
       | code in question as possible so that references which need
       | updating are obvious to see.
        
         | cjfd wrote:
         | Clear code needs some comments. Not many, though. If you write
         | a numerical algorithm it probably needs an explanation or a
         | reference to where it came from or something like that.
         | Generally, one needs a comment when it is difficult to figure
         | out why something was written that way. In many cases comments
         | are not needed. I perhaps write a comment once every ten files
         | or maybe even less but then it tends to be a rather long
         | comment because the thing explained is very non-obvious. The
         | kind of comment that I hate seeing is when somebody feels the
         | need to tell me what methods are constructors or similar such
         | nonsense.
        
         | tigershark wrote:
         | Clear code and clear tests shows both the what and the why.
         | With the additional advantage that they can't diverge and be
         | out of sync like the comments because otherwise the tests will
         | fail. Comments should be used to explain something unexpected.
         | Commenting each line of code is a recipe for disaster.
        
         | sanderjd wrote:
         | > _almost nobody ever goes looking for them there_
         | 
         | I've seen this claim a number of times and it's always so odd
         | to me. One of my most common activities each day - certainly
         | more common than the activity of writing new code - is reading
         | the commit history for different files. It's always surprising
         | to me to hear that this is an uncommon thing to do.
         | 
         | Edit to add: But I also think comments and documentation of all
         | kinds are good. I don't advocate good commit messages instead
         | of comments, but rather in addition to comments. The more
         | documentation the better.
        
           | aflag wrote:
           | Which tool do you use to view commit messages and revisions
           | for each file? I think one of the reasons this is uncommon is
           | due to lack of tooling (or wide-spread knowledge of them).
           | I'd really like to be able to easily see all the previous
           | commits that affected a specific line while I'm editing code.
           | But I usually have to resort to interacting with git, rather
           | than having something popping up on my screen (I use pycharm
           | and vim regularly).
        
             | nfRfqX5n wrote:
             | I use gitlens for vscode
        
             | recursive wrote:
             | Visual Studio has this. It's called "Annotate".
        
             | nemetroid wrote:
             | I use tig, which is a terminal UI. The "blame" view has a
             | shortcut to jump to the commit _before_ the one that
             | changed a given line. This makes it easy to quickly dig
             | backwards through the history of a file.
        
             | kevinschumacher wrote:
             | Not the person you were replying to, but in PyCharm:
             | 
             | - right click on the line number, click Annotate; this
             | gives you the commit date and author in the gutter
             | 
             | - hover over the date/author name; this gives you the
             | commit hash and message
             | 
             | - click on the hash itself in the popover; this shows the
             | git commit graph on the Version Control tab
             | 
             | - right click on the date/author name, click Annotate
             | Revision; this opens up the version committed then, with
             | its git blame in the gutter.
        
           | Braxton_Hicks wrote:
           | Agreed. I think the "nobody ever goes looking for them" case
           | is common for code bases where people are not writing good
           | useful commit messages.
        
           | phendrenad2 wrote:
           | Commit messages are much harder to get to for a given line of
           | code than a comment would be.
        
         | Ma8ee wrote:
         | A lot of comments can (and should) be replaced with good
         | naming. Sometimes the only reason to introduce a variable or
         | function is to name something. The advantage is that it is
         | harder to not read a name than it is to not read a comment, and
         | it is more obviously a bug when we try to set a variable, or
         | make a function calculate, something not agreeing with its
         | name.
        
         | phlakaton wrote:
         | > people rarely make fine grained enough commits to be able to
         | target specific lines or blocks
         | 
         | Take your own advice then: don't hire such people. Why would
         | you insist on maintaining documentation and not maintaining a
         | reasonable change log in your commits, if knowing "why" is
         | important to you?
         | 
         | (I make the advice tongue-in-cheek btw. Better to educate and
         | lift developers up wherever you can than just freeze them out.
         | Not everyone has the experience with these things that we do.)
         | 
         | There's not a one-size-fits-all solution here. Different orgs
         | handle their code history different ways, but having tasted the
         | power Git gives you over certain other VCSes to make the commit
         | log really useful as a record of change, and having taken
         | advantage of that feature several times myself, I wouldn't want
         | to go back.
         | 
         | This follows another comment I just made on the topic:
         | https://news.ycombinator.com/item?id=23743973
        
         | thdrdt wrote:
         | The only time I place comments is exactly this: to explain why.
         | 
         | Today I just had this example. I placed a little sleep in a
         | loop. But there is absolutely no way to know why it is there.
         | So I inserted a comment to explain the loop is DOSing a server
         | by constantly requesting it and the sleep will reduce the load
         | on that server.
         | 
         | Those comments are not only for others but also for yourself.
         | Even weeks from now it is easy to lose track on why you did
         | things the way you did.
         | 
         | Comments on why are very helpful.
        
         | pronoiac wrote:
         | > _" The comments are in the commit messages" - almost nobody
         | ever goes looking for them there_
         | 
         | Consider it another tool in the toolbox. I've gone spelunking
         | through git history to decipher the reasoning of something
         | still in use, though comments had been deleted and no one had
         | documented it before me.
        
         | clairity wrote:
         | yes, comments should be considered code too, but for humans, so
         | later coders (including your later self) can effectively
         | simulate (not but necessarily replicate) the prior code-writing
         | process(es). it's as critical as the code for machines.
         | 
         | which is to say, the comments should be kept concise and
         | current too.
        
         | codegladiator wrote:
         | > "Clear code shouldn't need comments"
         | 
         | That's like saying articles don't need summary.
        
           | unoti wrote:
           | Agreed; or like saying "You don't need a map; you can clearly
           | see where this road leads if you follow it far enough."
        
       | keithasaurus wrote:
       | I agree with most of the points made here, though I think some of
       | the bias toward up-front exhaustive documentation is probably not
       | a good fit for most of the projects I've been a part of.
       | Prototyping often reveals necessary changes due to resources
       | constraints, or to unconsidered corner cases. Documentation needs
       | to be a living thing as much as the code, and I think that pushes
       | you toward documenting within the code more than externally.
       | 
       | One of the more important points the author brings up is that
       | authorial intent and the 'why's of comments are the most
       | important. A corollary I'll bring up to that is that the 'what's
       | should be encoded in tests. Tests can be great documentation, and
       | they have the added benefit of informing developers when the
       | goals of the software is being voided (when they fail).
       | 
       | What has worked for me is conceiving of documentation this way:
       | 
       | - Design Documents: Historical use only, not to be updated.
       | 
       | - Readme: intro to project; why it exists, overview of how it's
       | meant to function, how to edit, etc. Tends to be updated when big
       | things change.
       | 
       | - Code comments: why something exists, what considerations were
       | made in that code's creation
       | 
       | - Test descriptions and comments: binding goals of previous
       | development to future development
       | 
       | This approach has done a pretty good job of keeping documentation
       | from getting too out-of-sync with code while enforcing basic
       | business objectives, still tilting the balance toward development
       | rather than documentation.
        
         | jariel wrote:
         | This is quite good actually.
         | 
         | I would add that some elements of design are worth keeping up,
         | like a general architectural overview and the details of some
         | things, like state-machines or specific kinds of statefulness.
         | 
         | It can be done in the comments, at the package level, that way
         | developers can keep it up to date without much fuss.
        
       | foodigger wrote:
       | most people cant read it anyway so what does it matter?
        
       | dkarl wrote:
       | _This is a major problem with code: You don 't know which quirks
       | are load-bearing. You may remember, or be able to guess, or be
       | able to puzzle it out from first principles, or not care, but all
       | of those things are slow and error-prone._
       | 
       | This is a problem from both the negative (not breaking things)
       | and positive (knowing how to add things) perspectives. The
       | positive perspective was written about by Peter Naur in one of my
       | favorite software engineering papers, "Programming as Theory
       | Building," in which he describes how the original authors of a
       | codebase have a mental model for how it can be extended in simple
       | ways to meet predictable future changes, which he calls their
       | "theory" of the program, and how subsequent programmers
       | inheriting the codebase can fail to understand the theory and end
       | up making extensive, invasive modifications to the codebase to
       | accomplish tasks that the original authors would have
       | accomplished much more simply.
       | 
       | I highly recommend finding Naur's paper (easily done via Google)
       | and reading it to understand why divining the "theory" of a
       | codebase is a fundamentally difficult intellectual problem which
       | cannot be addressed merely by good design, and not with 100%
       | reliability by good documentation, either.
        
         | Jtsummers wrote:
         | This is important to understand when moving through the early
         | stages of a project.
         | 
         | Many projects go through a clear prototype stage (where a lot
         | of disjoint things are written, like a set of utilities to
         | print out information on a file based on the format spec, make
         | files with hardcoded content, etc.), then a system starts
         | coalescing, and finally it's released.
         | 
         | The problem I've encountered is when the prototype is _too_
         | good. It 's an 80% solution, it seems to do everything that's
         | wanted, but the people who wrote it
         | (contractors/consultants/too expensive older devs) aren't the
         | ones who are tasked with finishing the last 20%. The original
         | developers may have understood how to create that last portion
         | with what they'd written, or they may have intended to throw it
         | away [0].
         | 
         | The new developers don't know what's present (and so recreate a
         | lot of existing capabilities), don't understand how to extend
         | it properly (so a lot of copy/paste when the original devs laid
         | out a nice extendable system with generics and or interfaces or
         | whatever the language provides), and the whole thing turns into
         | a mess. This communication between developers is critical, but
         | usually absent.
         | 
         | [0] "This is more of a proof of concept, it does everything you
         | want for converting two file formats between each other, but
         | doesn't scale yet because it's all 1-to-1 mappings, we are
         | working on the intermediate representation now that we have a
         | firmer grasp of what's needed."
         | 
         | "Oh, that's fine, you guys can go work on the next project
         | we've got a crack team that can wrap this up."
         | 
         | "...Ok, thanks for the money."
         | 
         | The crack team never makes that intermediate representation and
         | just creates 1-to-n mappings between each format. The explosion
         | in code size becomes unmaintainable, most of the mappings are
         | the result of copy/paste, and bugs proliferate throughout
         | because, while fixed in one section, they don't realize how
         | many other places that same bug resides in.
         | 
         | EDIT: For the record, [0] started off short enough to be a
         | footnote then grew to be too long for it, and I forgot to edit
         | it properly when I came back from getting a glass of water.
        
         | hinkley wrote:
         | I think I have to disagree with Naur on this, in that people
         | using the Scientific Method don't ship their theories, but we
         | do.
         | 
         | As a scientist who has just succeeded in testing a hypothesis,
         | I now need to go back and document a simplified series of steps
         | that should lead any independent party to the same phenomenon.
         | Once we are on the same page, they can confirm or refute my
         | theory based on their own perspectives on the problem space.
         | 
         | During that process I may discover that I based half of my
         | experiment on another hypothesis that I never tested, or was
         | plain wrong. Now I've discovered my 'load bearing' assumptions.
         | I may discover something even more interesting there, or I may
         | slink away having never told anybody about my mistake.
         | 
         | Essentially, scientists still 'build one to throw away'. We
         | haven't in ages. And my read on Brook's insistence that we
         | build one to throw away is that it was aspirational and not
         | descriptive. And notably, he apparently recants in the 20th
         | anniversary edition (which is itself 25 years old now):
         | 
         | > "This I now perceived to be wrong, not because it is too
         | radical, but because it is too simplistic. The biggest mistake
         | in the 'Build one to throw away' concept is that it implicitly
         | assumes the classical sequential or waterfall model of software
         | construction."
         | 
         | So we are very much at odds with the scientific method. And we
         | have the benefit of hindsight. We have seen the horrors that
         | can occur when you take the word Theory out of context and try
         | to apply it to non-scientific theories. We should learn from
         | the mistakes of others and summarily reject any plan where we
         | do it too.
         | 
         | In other words: next metaphor, please, and with all due haste.
        
           | Jtsummers wrote:
           | I think I have to disagree with you on this one, I've used
           | the scientific method (though not in an explicit checkbox-y
           | way) plenty of times to ship and debug code.
           | 
           | In particular, since (as I've said on this forum many times)
           | I work primarily on the maintenance end of software. I don't
           | know what the creators or previous developers were thinking,
           | especially with more recent projects (documentation quality
           | has really gone down hill, people call autogenerated UML
           | diagrams "design docs", but without commentary they only
           | reflect the state of the system, not its design). I have to
           | try different changes based on my understanding of the system
           | and see the consequences. That is, I form a hypothesis about
           | what will happen if I do X, I do it, I collect the results
           | and I've either confirmed my hypothesis, refuted it, or left
           | it in an indeterminate state. I form another and repeat. Over
           | time I build up a model (theory) of how the system behaves
           | and should be updated/extended. Since I can't keep tens of
           | thousands of lines of code in my head, let alone hundreds of
           | thousands or millions, I always only have a model (theory),
           | because I never have the totality of it in my mind. Though
           | good code, with good use of modules, makes it easier to keep
           | large chunks in mind, I still have to have a model of how
           | those modules work and work together.
           | 
           | Hell, this is half (or more) of testing for older software
           | systems. You put in some input and see if you get the output
           | you expected. If you don't, you evaluate why (is my model
           | wrong or is the system wrong) and repeat.
        
             | webmaven wrote:
             | Insofar as "what happens when I do this?" goes, it neglects
             | the null hypothesis. If you don't pay attention to
             | falsifiability can you claim to be doing science?
        
         | hikarudo wrote:
         | On the topic of the "theory" (mental model) of a program, I
         | recommend John Ousterhout's book "A Philosophy of Software
         | Design". You get such gems as:
         | 
         | "... the greatest limitation in writing software is our ability
         | to understand the systems we are creating."
         | 
         | "Complexity manifests itself in three general ways... change
         | amplification, cognitive load, and unknown unknowns."
         | 
         | "Complexity is caused by two things: dependencies and
         | obscurity."
         | 
         | "Obscurity occurs when important information is not obvious."
         | 
         | "The goal of modular design is to minimize the dependencies
         | between modules."
        
         | ponker wrote:
         | I've had that experience describing the plot of a novel to
         | friends of mine. The novel is pretty complex and covers ideas
         | in crime, internet anonymity, memetics/virality, and then some
         | technical things with vehicles and atmospheric science. Some
         | friends I've talked it through with, they come up with ideas to
         | add stuff and it's like "that makes no sense for this novel,
         | but it's not a dumb idea given how little of the _theory_ of
         | the novel I 've communicated to you." Whereas other friends
         | seem to immediately grasp onto the theory and make suggestions
         | that actually fit with the overall concept very well, and
         | usually recommend small changes rather than wholesale plot
         | rearchitectures. It's like an architect coming in and saying
         | "we should move this door two inches so that this door doesn't
         | bang this wall" vs. "We should build this whole house as one
         | story into the side of a cliff."
        
         | mjb wrote:
         | Thanks for sharing that, I'll read it!
         | 
         | I do agree that comments, documentation, and other artifacts
         | aren't sufficient to solve this problem. The closest I've come
         | is with formal specification, where the intent of the program
         | can be communicated very clearly. Multiple approaches are
         | needed. One of those approaches is continuity: Keeping people
         | around who are familiar with the code base and can pass on this
         | knowledge to others.
        
       | kevsim wrote:
       | I think the most reliable thing to see what quirks are load
       | bearing is tests, particularly regression tests. You change
       | something, you break expected behavior, you fix it and you write
       | a test. Now the next person may wonder if some quirk is load
       | bearing, but they'll know for sure when running the regression
       | tests.
       | 
       | Additionally, I'd say naming things, though one of the hardest
       | things we have to do, can go a long way towards explaining the
       | "why". Some programmers I've worked with have a knack for knowing
       | just went to break a giant line into separate lines, giving local
       | variables great expressive names, and all of a sudden the code
       | reads a million times better.
       | 
       | All that being said - I agree with most of the points of the
       | article and do push my teams to do a lot of upfront writing down
       | of designs. These things tend to go stale, but in the moment
       | they're a great tool for fleshing out ideas and sparking
       | discussions.
        
       | macintux wrote:
       | I've had similar arguments here once or twice. There's so much
       | context that isn't deducible from code.
       | 
       | You rarely need to document the "how" (that much should be
       | evident if the code is well-written) but you absolutely should
       | document the "why" (or, often as important, the "why not": what
       | code _could_ be here but isn't).
        
         | throw1234651234 wrote:
         | Give me an example, and I will write you code documenting the
         | business context.
        
           | Jtsummers wrote:
           | And then what? You throw away the example specification so
           | that the why only continues on in the code?
           | 
           | And after 10 years of maintenance, the code has drifted with
           | each iteration so that the why is no longer clear in the
           | code.
        
         | mjw1007 wrote:
         | I agree that you shouldn't document "how", but when I'm reading
         | unfamiliar code, I find I what I miss is "what", not "why".
         | 
         | To my mind, in well-written code each function should be
         | documenting its contract: what it assumes, what it guarantees
         | if that assumption holds.
         | 
         | (And if it turns out that what you'd write is just the
         | function's name and its parameter and return types with a few
         | grammatical particles added, maybe it's OK to omit the
         | documentation.)
         | 
         | Then if you find that in order to do that you have to write a
         | little essay, or you need terminology that doesn't correspond
         | to a named thing in the codebase, or you're repeating yourself
         | in multiple comments, that tells you something you need to put
         | in higher-level documentation.
        
           | gimboland wrote:
           | Yes. Floyd-Hoare logic is worth learning about in this sense
           | -- a formal system for imperative languages where the rules
           | essentially say "given preconditions X and code Y, if X is
           | true before you run Y, we guarantee Z to be true afterwards".
           | I've never ever ever proven code correct using this
           | formalism, but that way of thinking permeates my every action
           | as a programmer.
        
         | lmilcin wrote:
         | Whether or not to document "how" will depend on the target
         | audience.
         | 
         | The code is written for people to read and only incidentally
         | for computers to execute. From that point of view the target
         | audience will matter a lot. I agree that in most cases, you
         | expect the audience to be on level with the code and if you are
         | writing code that is not on level with the audience (for
         | example it is way too advanced) then you are doing something
         | wrong (at the very least not considering who will be working
         | with it).
         | 
         | But not always.
         | 
         | Example: I do with a lot of bright quants. With regards to code
         | that does a lot of complicated calculations, they typically
         | understand "why" but might need help with understanding "how".
         | 
         | Another example: when your audience is mostly junior team you
         | might want to explain "how". My current project starts using
         | more and more reactive constructs and oftentimes I throw in an
         | explanation of "how" when I, for example, get queries to
         | explain during code reviews.
        
       ___________________________________________________________________
       (page generated 2020-07-06 23:00 UTC)