1. 14

  2. [Comment removed by author]

    1. 9

      The comment about sharing approaches that didn’t work made me want to share the docs for my favorite function in the Haskell world, a variant of unsafePerformIO: accursedUnutterablePerformIO

      -- | This \"function\" has a superficial similarity to 'unsafePerformIO' but
      -- it is in fact a malevolent agent of chaos. It unpicks the seams of reality
      -- (and the 'IO' monad) so that the normal rules no longer apply. It lulls you
      -- into thinking it is reasonable, but when you are not looking it stabs you
      -- in the back and aliases all of your mutable buffers. The carcass of many a
      -- seasoned Haskell programmer lie strewn at its feet.
      -- Witness the trail of destruction:
      -- * <https://github.com/haskell/bytestring/commit/71c4b438c675aa360c79d79acc9a491e7bbc26e7>
      -- * <https://github.com/haskell/bytestring/commit/210c656390ae617d9ee3b8bcff5c88dd17cef8da>
      -- * <https://ghc.haskell.org/trac/ghc/ticket/3486>
      -- * <https://ghc.haskell.org/trac/ghc/ticket/3487>
      -- * <https://ghc.haskell.org/trac/ghc/ticket/7270>
      -- Do not talk about \"safe\"! You do not know what is safe!
      -- Yield not to its blasphemous call! Flee traveller! Flee or you will be
      -- corrupted and devoured!
      {-# INLINE accursedUnutterablePerformIO #-}
      accursedUnutterablePerformIO :: IO a -> a
      accursedUnutterablePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
      1. 5

        Notably absent from that comment is any indication of why accursedUnutterablePerformIO is accursed and unutterable, which means if I were performing a detailed documentation audit, I would flag this as needing attention. Maybe it’s obvious to people who can decode Haskell’s sigil soup, but I doubt it.

        1. 4

          For this function it’s really a “if you have to ask, you shouldn’t use it” (it’s also listed as deprecated, another indication that it shouldn’t be used).

          1. 4

            “There are gates you do not open, there are seals you do not breach! The fools who can’t resist meddling are killed by the lesser perils early on, and the survivors all know that there are secrets you do not share with anyone who lacks the discipline to discover them for themselves! Every powerful wizard knows that!”

          2. 1

            I can barely read Haskell but it does explain why: it leads to code that was intended to create multiple distinct mutable buffers to be built to reuse the same mutable buffers instead.

        2. 9

          Once you start writing quality code comments, you can use a tool like Sphinx or Javadoc to include them in your documentation.

          I’ve seen this attempted, but I’ve never seen it work. I would be interested in hearing from people who have had this work on a non-trivial project at your job. So far I’m filing this in the “promising idea that didn’t quite work out” bin.

          In at least the case of library/API documentation, I’ve never seen any other approach work. I’ve also seen this one fail frequently, but it’s at least better than the usual alternative, which is to auto-generate skeleton API docs without useful comments.

          For example, the Java docs, which are auto-generated from comments, are pretty decent, far better than most API/library documentation. CPAN on average is also fairly good, since the Perl community seems to have a fairly strong culture of using POD. Among other things I’ve had the pleasure of using lately, they’ve all been auto-generated too, but by teams that evidently put less emphasis on writing good comments to auto-generate from: Google’s Firebase, Apple’s API docs, etc., all could use a little more time spent on the comments.

          One distinction I sort of like is the Lisp one (adopted by a few other languages) where comments proper and docstrings are both conceptually and syntactically different. In good Lisp style, any function that’s externally callable is supposed to have a docstring at the top of the function, which explains in prose what the function does, and any gotchas/prerequisites/notes/etc. about its usage. This can be both used to auto-generate documentation, and queried at the REPL or whatever IDE you have hooked up. The actual implementation code interior to the function, though, is ideally supposed to be self-documenting, with relatively few comments only where really necessary.

          1. 2

            I think a big part of the problem is that there’s no simple, widespread way to link code to documentation aside from comments. At least in the places I’ve worked, historical discussions, business case documentation, and bug reports are incredibly valuable for understanding and modifying code… if I know they exist and if I can find them. Similarly, most people don’t read the documentation I write. Comments are a terrible way to carry information but they’re also the only way that everybody knows and is supported everywhere.

            It’s a field I keep coming back to and if there’s interesting stuff out there that escaped the “didn’t work out” bin I’d love to research it.

          2. 4

            Marking possible improvements (TODOs) in the code

            This one is a personal annoyance of mine. When in the history of software development has anyone browsed through a codebase and implemented a TODO that some other developer left?

            The two main cases I see TODO comments seem to be:

            1. The developer is acknowledging that they know the code could blow up under some circumstances, but are passing the buck of creating a more robust implementation to the poor sap who gets the bug report about it when it inevitably goes wrong.

            2. The developer intends to actually do the work in the coming days and is using the codebase as a work tracking system.

            1. 2

              When in the history of software development has anyone browsed through a codebase and implemented a TODO that some other developer left?

              Er, a month ago, when I did this. I was adding a new string to the translations JSON file for some component. In the section of strings for that component, I saw a TODO to reorganize them by grouping the strings better. While I was there, I did that reorganization and put my new string in the correct place for that new organization.

              I can’t say whether it was a good idea for that developer to leave that TODO there. Maybe they were being lazy, or maybe writing that comment was all they had time to do. But the comment did point me in the right direction by pointing out what area of code I might have trouble understanding, due to its bad organization. And that TODO did end up getting done, months later, thanks to that comment.

              1. 2

                Also, 3. The developer is passively-aggressively taking a potshot at someone else’s code that annoys them, but not enough to fix it.

              2. 4

                I consider that those who do not write code comments (where applicable), to be either arrogant, lazy or not used to working and considering others, including their future selves.

                1. 4

                  I never thought the intent is to have zero external docs.