1. 7

    I wonder whether we should give up nested folders and just move to tagging.

    1. 6

      I tried this for a while and it suffers the same problem as nested folders: you still have to tag/categorize everything.

      1. 6

        For things that have no better location, I use a system of weekly folder rotation which works out pretty well since everything current is there and you don’t need to check a lot in the older folders usually.

        Everything that has a better location (e.g. because it’s part of a project) gets moved to that then.

        1. 1

          Yeah, it just seems like it is more flexible. Yes, tagging can be a pain and there is no notion of one categorization being a sub of another. That part is not easily discoverable. Those are two downsides.

          1. 2

            I do think tagging is better, by the way. When I tried it, though, I found I was very inconsistent with what tags I was using so finding that “thing that was like some other thing” was not as great as was made out to be.

        2. 3

          A path is just a list of tags, especially if you have a super fast search engine like Everything.

          I place my files in nested folders, but I don’t navigate them. I open Everything, type parts of the path, and it’s in the top 3 of “Date accessed” 99% of the time. Takes one second.

        1. 10

          Working with befuddled students has convinced Garland that the “laundry basket” may be a superior model. She’s begun to see the limitations of directory structure in her personal life; she uses her computer’s search function to find her schedules and documents when she’s lost them in her stack of directories. “I’m like, huh … I don’t even need these subfolders,” she says.

          This feels like a case of the pendulum swinging too far the other way. If you’ve ever tried to keep everything carefully organized you’ve probably found it to be a chore. That’s because it is for the vast majority of people. I’m a “files and directory” kind of person and I mostly toss things in a “downloads” folder until I feel the need to sift through it a bit and build up the patience to bother doing so. Search, even basic search, is really useful. Directory hierarchies are useful. Neither is all that superior to the other all the time. (Mind you, a good filename goes a long way. Sometimes just renaming it is good enough.)

          The article seems to be deliberately playing the extremes off each other for some shock value. I know various high school teachers who teach in an essentially “paperless” classroom and the students are familiar with, and use, a hierarchical filesystem, even if that’s not what they would call it. Would they know about a “file on the Desktop”? Maybe not, but grasping the concept wouldn’t be totally alien. Folders of documents in OneDrive and their electronic classroom setup are quite similar.

          1. 11

            I know various high school teachers who teach in an essentially “paperless” classroom and the students are familiar with, and use, a hierarchical filesystem, even if that’s not what they would call it

            When I was working on Étoilé, I came across a paper that showed that around 10-20% of people find hierarchies a natural form of organisation. It came out at about the time iTunes was getting awful reviews from geeks and stellar reviews from everyone else. iTunes (prior to iTunes 5, which was the turning point where Apple decided that they hated their users) didn’t use a hierarchy at all for organisation. It used structured metadata, but allowed arbitrary filters, rather than the traditional {genre}/{artist}/{album}/{track} filing that most filesystem-based players used. This was a lot more flexible (what happens if I want to list all ‘60s music? Trivial with iTunes’ filter model, difficult with a hierarchy if decade is not the top layer in the hierarchy) and was popular with most users.

            I’ve wondered for a long time about the self-selection that we get from the fact that most programming languages are strongly hierarchical (imposing hierarchy was, after all, the goal of structured programming). This leads to programmers being primarily selected from the set of people who think in terms of hierarchy (the percentage of people who think in terms of hierarchy and the percentage that find it easy to learn to program seem to be sufficiently similar numbers that I wouldn’t be at all surprised if they’re the same set). This, in turn, leads to programmers thinking that hierarchical organisational structures are natural and designing UIs that are difficult for non-programmers to learn.

            With Étoilé, we wanted to remove files and folders as UI abstractions and provide documents and tags, with a rich search functionality. That can still be mapped into a filesystem abstraction for the low-level interface but it didn’t need to be the abstraction presented to users.

            1. 2

              …we wanted to remove files and folders as UI abstractions and provide documents and tags, with a rich search functionality.

              For the record, I think this is a superior approach. Ultimately, the problem is that actually tagging or categorizing your own data is a chore, so the results are somewhat lacklustre. (Music and photos are kind of an exception here because they often come from a source that provides the metadata that makes a structured search useful.)

          1. 2

            […] nothing in software engineering makes sense except in light of human psychology; the more attention researchers and developers pay to that, the faster our profession will make real progress.

            GCC and Clang have gotten a lot better at providing useful error messages in the last few years. They seem to have taken this (good) advice to heart.

            1. 5

              Dragonfly has gone a long way since; now they’re trading blows with Linux in the performance front, despite the tiny team, particularly when contrasting it with Linux’s huge developer base and massive corporate funding.

              This is no coincidence; it has to do with SMP leveraged through concurrent lockfree/lockless servers instead of filling the kernel with locks.

              1. 3

                This comparison, which seems pretty reasonable, makes it look like it’s still lagging behind.

                1. 7

                  What I don’t like about Phoronix benchmark results generally is that they lack depth. It’s all very well to report MP3 encoding test running for 32 seconds on FreeBSD/DragonflyBSD and only 7 seconds on Ubuntu, but that raises a heck of a question: why is there such a huge difference for a CPU-bound test?

                  Seems quite possible that the Ubuntu build is using specialised assembly, or something like that, which the *BSD builds don’t activate for some reason (possibly even because there’s an overly restrictive #ifdef in the source code). Without looking into the reason for these results, it’s not really a fair comparison, in my view.

                  1. 3

                    Yes. This is well worth a read.

                    Phoronix has no rigour; it’s a popular website. A benchmark is useless if it is not explained and defended. I have no doubt that the benchmarks run in TLA were slower under freebsd and dragonflybsd, but it is impossible to make anything of that if we do not know:

                    1. Why

                    2. What is the broader significance

                    1. 4

                      The previous two comments are fair, but at the end of the day it doesn’t really change that LAME will run a lot slower on your DragonflyBSD installation than it does on your Linux installation.

                      I don’t think these benchmarks are useless, but they are limited: they show what you can roughly expect in the standard stock installation, which is what the overwhelming majority of people – including technical people – use. This is not a “full” benchmark, but it’s not a useless benchmark either, not for users of these systems anyway. Maybe there is a way to squeeze more performance out of LAME and such, but who is going to look at that unless they’re running some specialised service? I wouldn’t.

                  2. 1

                    This comparison, newer and from the same website, makes it look as the system that’s ahead (see geometric mean @ last page).

                    Not that I’m a fan of that site’s benchmarks.

                    1. 2

                      I haven’t done the math, but it seems like most of DragonFlyBSD’s results come from the 3 “Stress-NG” benchmarks, which incidentally measures “Bogo Ops/s”.

                      Here’s the benchmark page: https://openbenchmarking.org/test/pts/stress-ng

                      I don’t know why Phoronix uses a version called 0.11.07 when the latest on the page seems to be 1.4.0, but maybe that’s just a display issue.

                      1. 1

                        Christ @ benchmarking with Bogo anything.

                1. 10

                  I’m not a huge fan of IDEs but this article is mostly nonsense.

                  This in particular I take exception to:

                  Less Code, Better Readability

                  Not having Autocomplete / Code Generation guides you naturally to writing more compact and idiomatic Code in the Language of your Choice. It helps you to learn language-specific features and syntactic sugar. Consider

                  System.out.println(“hello”);

                  printf(“hello”);

                  You see that in C, where using an IDE is uncommon, the languge/libraries/frameworks naturally becomes more easily readable and writable.

                  I see this as a win for IDEs especially in large projects because the cost of avoiding useless abbreviations is minimal.

                  ShoeApi.GetPriceAndFeatures();
                  

                  is way more readable and explicit than

                  Api.GetPrcFeat();
                  

                  Maybe not the most realistic example but you get what I’m saying and we’ve all seen code like the latter and had no clue what it does without drilling into the method.

                  Also since when does having autocomplete equal full-blown IDE?

                  1. 4

                    The reason the C library and Unix functions have such short names is, in part, because the original C linker only looked at the first 8 characters of symbol names.

                    (Likewise, I seem to recall that the original Unix filesystem only allowed 8-character filenames, forcing shell commands to be terse. I may be wrong on this; but most filesystems of that era had really limited names, some only 6 characters, which is why the classic Adventure game was also called ADVENT.)

                    1. 3

                      I think you might be conflating Unix with MS-DOS. The early Unix file systems allowed 14 character names, while MS-DOS limited filenames of 8 (well, 8 characters for the name, plus 3 for the extension).

                      1. 8

                        I guess Ken could have spelt creat with an e after all.

                      2. 3

                        The reason the C library and Unix functions have such short names is, in part, because the original C linker only looked at the first 8 characters of symbol names.

                        This was actually part of the first C standard, and it was limited to “6 significant initial characters in an external identifier”. (Look for “2.2.4.1 Translation limits” here.)

                        This was almost certainly due to limitations from FORTRAN and PDP-11. PDP-11 assembly language only considered the first 6 characters. (See section 3.2.2, point 3.) FORTRAN (in)famously only used 6 characters to distinguish names. If you wanted interoperability with those systems, which were still dominate in the 80s, then writing everything to fit in 6 characters made sense.

                      3. 3
                        ShoeApi.GetPriceAndFeatures();
                        

                        is way more readable and explicit than

                        Api.GetPrcFeat();
                        

                        I see a few independent criteria these comparisons:

                        1. The inclusion of the namespace (System. / ShoeApi. / Api vs… not)
                        2. Low vs. high context names (ShoeApi vs. Api)
                        3. Abbreviated names GetPriceAndFeatures vs GetPrcFeat

                        I prefer to elide the namespace if it appears more than a couple times. (X; Y; Z; over HighContextName.X; HighContextName.Y; HighContextName.Z;)

                        I prefer high context names, especially when there’s already a namespace. (service.Shoes.Api over service.Shoes.ShoeApi)

                        I prefer to not abbreviate. (GetPriceAndFeatures over GetPrcFeat … though both aren’t great.)

                        Best (if I must use a Java-like): Api.Fields(Price, Features).Get()

                      1. 17

                        This is just “Java is a miserable nightmare to program in”, then it just descends into parroting the party line on Unix philosophy with nonsensical statements to back it up. “printf” vs. “System.out.println” is not a great reason.

                        1. 25

                          Yup. I’ve worked in large Java code bases, large Python code bases, and large C/C++ code bases. The reasons given in this article are imagined nonsense.

                          • Remember syntax, subroutines, library features: absolutely no evidence to support this. In all my years I have yet to see even a correlation between the use of IDEs and the inability to remember something about the language. Even if the IDE is helping you out, you should still be reading the code you write. (And if you don’t, then an IDE is not the problem.) This claim is a poor attempt at an insult.
                          • Get to know your way around a Project: If anything, IDEs make this simpler and better. I worked in GCC /binutils without tags or a language server for a while and let me just say that without them, finding the declaration or definition with grep is much less efficient.
                          • Avoid long IDE startup time / Achive better system performance: Most people I know who use IDEs shut them down or switch projects about once a week, if that. This is just whining.
                          • Less Code, Better Readability: Tell this to the GCC and Binutils developers, who almost certainly didn’t use an IDE yet still managed to produce reams of nearly unreadable code. Yet another nonsense claim from the “Unix machismo” way of thinking.

                          The other points made in the article are just complaints about Java and have nothing to do with an IDE.

                          1. 6

                            Avoid long IDE startup time / Achive better system performance: Most people I know who use IDEs shut them down or switch projects about once a week, if that. This is just whining.

                            It’s also not even true. In particular tmux and most terminals top out at a few MB/s throughput and stop responding to input when maxed so if you accidentally cat a huge file you might as well take a break. Vim seems to be O(n^5) in line length and drops to seconds per frame if you open a few MB of minified json, and neovim (i.e. vim but a DIY IDE) is noticeably slower at basically everything even before you start adding plugins. Nevermind that the thing actually slowing my PC down is the 5 web browsers we have to run now anyway.

                            1. 2

                              Vim seems to be O(n^5) in line length and drops to seconds per frame if you open a few MB of minified json

                              Obscenely long lines are not a very realistic use pattern. Minified JSON and JS is a rare exception. Vim uses a paging system that deals very well with large files as long as they have reasonable line sizes (this includes compressed/encrypted binary data, which will usually have a newline every 100-200 bytes). I just opened a 3gb binary archive in vim; it performed well and was responsive, and it used only about 10MB of memory.

                              1. 3

                                A modern $100 SSD can read a few MB in 1 millisecond, $100 of RAM can hold that file in memory 5 million times, and a $150 CPU can memcpy that file in ~100 nanoseconds.

                                If they did the absolute dumbest possible implementation, on a bad computer, it would be 4-5 orders of magnitude faster than it is now.

                              2. 2

                                Oh yes, I didn’t even mention this seemingly ignored fact. I can’t speak for Vim and friends, but Emacs chokes horribly on large files (much less so with M-x find-file-literally) and if there are really long lines, which are not as uncommon as you might think, then good luck to you.

                          1. 28

                            To prevent the problem from getting any worse, we have to stop normalizing CSV as an output or input format for data transfer.

                            I’m not sure the author is aware of how many legacy tools not only rely on CSV, but only know how to export CSV, and how many of the people who work with it are not technical.

                            When I worked at a web startup, one of our clients shipped us customer information as 2GB+ of CSV files every day as an FTP upload. They never compressed it or used SSH because it was too difficult for them. I did manage to at least get them to use the pilcrow character as a field separator so that the mistyped email addresses with commas in them didn’t screw up the import (which was a custom script with all kinds of fiddling to fix various entries). This file was exported from some Oracle database (I think–it was never clear) and the people uploading were a sales team with basically no technical skills.

                            Fighting against this is a complete and total lost cause. Much like anything that is entrenched with lots of rough edges, CSV will take forever to go away.

                            1. 6

                              I’m not sure the author is aware of how many legacy tools not only rely on CSV, but only know how to export CSV, and how many of the people who work with it are not technical.

                              I’m absolutely certain the author knows that. They specifically lament all of these facts, and cite their years of experience dealing with all of these problems.

                              This file was exported from some Oracle database (I think–it was never clear) and the people uploading were a sales team with basically no technical skills.

                              And if some other format were to become universal, as easy to export and import as CSV, that wouldn’t be a problem.

                              Much like anything that is entrenched with lots of rough edges, CSV will take forever to go away.

                              The author states this themselves. And they go on to hypothesize that if Microsoft and Salesforce both supported some other format, the rest of the world would come to adopt it.

                              You’re making all the same points that the author does, but without speculating on how these problems could be solved. The author never claims a migration would be quick, easy, or universal. Only that tackling the core use cases of Excel and database dumps would make future work far less error prone.

                              1. 4

                                Only that tackling the core use cases of Excel and database dumps would make future work far less error prone.

                                I don’t believe this, and I think that’s my problem with the article. You can design a wonderous format and people will always find a way to make it difficult to work with because they often don’t want (or think they don’t want) the restrictions that come with something that makes future work less error prone.

                            1. 23

                              Maybe I just don’t get where the fossil author is coming from but when I was using fossil regularly (and sometimes still do) I’d end up having two copies of the same repo… a short-lived one in whatever work-in-progress state with all the useless commits (“really fix edge case this time”, “friday WIP” etc.) and then a second persistent one where I’d rsync the worktree and make a new commit or, less easily, cherry-pick from the first. I’m not convinced that seeing the sausage being made in the commit history has any benefit over a single commit or small number of clean commits per feature.

                              1. 14

                                I’m not convinced that seeing the sausage being made in the commit history has any benefit over a single commit or small number of clean commits per feature.

                                Yes, the lack of ability to clean up history, even locally, is the one thing about Fossil that ensures I’ll never use outside of work, where I have to use it in some situations.

                              1. 2

                                The importance of being in the right place at the right time cannot be possibly overstated.

                                This is probably one of the most important things to take away from the whole thing. x86 and DOS were not grand architectural achievements so much as they were a benefactor of circumstance. The same is probably true for a lot of tech stuff we seemingly hold in high regard.

                                1. 2

                                  But somehow to me it seems like the PC itself was a stroke of genius: they basically had already sunk a lot of R&D into making small computers and had to minimize cost and time to market in order to be able to compete with the likes of Apple and Commodore. So the idea of using cheap, off-the-shelf components was a great move for making this product a reality.

                                  I’m kind of afraid of what this says for the expected quality of stuff that is successful in the market, though. OTOH, it does mean if you identify situations like this where there’s a lot of useful (but maybe crappy) base ingredients for a complex product, you can fit them together in a short amount of time and beat all competitors who are trying to do everything from scratch using in-house proprietary solutions. Thinks… isn’t that exactly what Amazon is currently doing with open source software in their SaaS platforms?

                                1. 16

                                  I like the point about type keys, but one thing that distracted me was the refactoring in step 3. Honestly, the code in step 2 was more readable. The different approaches in step 3 are an example of the DRY principle taken too far.

                                  1. 3

                                    I came to make the same comment.

                                    As a variant of Sandi Metz’s

                                    Duplication is far cheaper than the wrong abstraction

                                    I’ve recently come to:

                                    “A little duplication is better than one more abstraction.”

                                    The abstraction need not be wrong, or even artificial. It has a cost just by virtue of being an abstraction.

                                    1. 3

                                      createUserWithNotifications? I found that oddly specific as well.

                                      Admins may have different arguments for notifications so maybe you’ll end up encoding a kind of type flag in the call. Or encode a bunch of stuff in the names of four-line functions.

                                      The base premise is valuable but “overfitting the cleanliness” runs the risk of painting yourself in a corner and having to clean your way out again.

                                    1. 3

                                      I think my favourite thing about these older writings is how they have the same complaints that show up now.

                                      The art of thinking (before you code) often seems a lost art. Such safeguards as validating the input before you read it and keeping the user interface constant from one command to the next, are good things whose time has not (we hope) truly passed.

                                      This is dated 1989, now 32 years old. I have read similar sentiments in writings from the 1960s and 1970s. I posit that thinking before you code was never an art that was in regular practice, that looking at the past with rose coloured glasses has been in fashion the whole time, and much of what we think programming used to be like (namely, how great it was) is largely made up.

                                      1. 2

                                        At one point the authors talk about moving the system-specific stuff into their own files, hidden behind an interface. They say,

                                        However, in our experience, it’s much more usual for the different variants to be completely different code, compiled from different source files—in essence, the parts outside the #ifdef disappear.

                                        This is true, but what they don’t mention is now the “#ifdef” part becomes part of the build system. The logic of the variants doesn’t go away, it now gets moved elsewhere.

                                        1. 4

                                          This gets very difficult with C once you realise that you don’t have completely different systems, you have overlapping sets of functionality. You end up needing a generic POSIX implementation and then a bunch of specialised ones.

                                          This is one of the reasons that I much prefer C++ over C. I can write a templated class that uses a set of mostly portable APIs, with the template parameterised on some per-platform tweaks and a per-platform subclass can inherit from the templated class and then export the platform-specific type as the default implementation.

                                          For example, in snmalloc we have a POSIX implementation of our platform-abstraction layer (PAL) that should work on pretty much any *NIX. There’s a BSD subclass that uses a generic BSD extension and another subclass of this for members of the BSD family that provide strongly aligned allocation from mmap. The FreeBSD and NetBSD implementations are identical: we only maintain them as separate things so that there’s an extension point if we want to add platform-specific behaviour. Some systems, such as Haiku are a bit more custom, but the amount of code is fairly small. The only #ifdefs are for selecting which PAL to expose as the DefaultPAL type.

                                          All of the rest of the code that cares about the platform takes the PAL as a template parameter. This means that we can test the POSIX PAL on any POSIX platform and make sure that we haven’t broken it. We can also provide custom ones (e.g. for OpenEnclave).

                                          There’s no dynamic dispatch for any of this and the PAL functions are typically inlined everwhere that they’re used.

                                          Doing the same in C is a complete mess.

                                        1. 2

                                          Granted, I haven’t been involved in a massive project of the type this post is describing, but where this kind of disciplined process falls apart in my experience is that step 0 never finishes even after implementation has already started. New requirements keep coming in and old ones keep changing, and not all the changes can be deferred until after the initial version.

                                          Maybe it’s different when the project is sufficiently huge?

                                          1. 3

                                            New requirements keep coming in and old ones keep changing, and not all the changes can be deferred until after the initial version.

                                            This is why you have to learn to push back. The customer (or whoever it is) must understand that it does take time to figure all this stuff out, especially when the scope is large. Changing things on the fly is going to cost them. If step 0 is changing all the time, then it is very likely you are not in a large project. If you are in a large project and it is in constant flux, then you can be pretty sure your project is doomed.

                                            1. 2

                                              Definitely true that my projects haven’t been on the scale of what the post is talking about with eight-figure development budgets and so forth, so that may be the main difference.

                                              It doesn’t seem to be a matter of which industry you’re in. I’ve seen this happen even at a bank: Last year I had to throw out several weeks of work because all of a sudden the compliance department realized that implementing the product spec (which they had already reviewed multiple times and signed off on) would risk running afoul of money-laundering laws. And the compliance department at a bank, for good reason, has the authority to brush aside pretty much any amount of push-back from the engineering team short of, “It’s physically impossible to do what you want.”

                                              1. 1

                                                This is certainly a risk. It could happen in my work if the hardware teams decide to change something since we’re utterly dependent on them (and they are also our customer!).

                                                It’s important to realize that all you planned and worked on can be tossed with a spec change. The key is who is deciding on that spec. In the case you cited it wasn’t the development team. In retrospect, all the work put in was essentially pointless. The key is that (apparently) no one knew at the time the work was being done. To me, this is not an argument against planning and estimating. (And to be clear, I don’t think you are arguing against this.)

                                                The customer needs to be aware that large spec changes will cause significant delays. What gives planning and estimation a bad reputation is tying this all to hard delivery dates while continuing to absorb spec changes. Or to keep increasing scope of the project. Agile, in the broad sense, addresses this quite well. But I don’t see it as advocating for the banishment of estimation. Or planning. Or even forethought. I’ve always seen it as a way to get something that kinda, sorta works so that you can learn from it, even if it’s not customer facing. Doing that does not imply that mapping stuff out ahead of time is a waste.

                                                And hey, even thrown away work teaches you something.

                                          1. 1

                                            I find this top-level comment a compelling reply and want to expand on it a little bit.

                                            Automate common tasks

                                            In light of @peterbourgon’s remarks, all I’d say is that you automate what you can. If it’s common but not a time sink and the infra to automate it will be a burden, maybe it’s fine to not automate it.

                                            Small frequent releases. […] Weekly at slowest. Daily is great. Hourly is dreamy.

                                            This is highly dependent on the product. Here’s the thing: our customers don’t even want releases anywhere near this fast. Also, our product takes at about 10 hours just of build and test. Full regression tests take days. If a build is considered to be a “release” then we can do daily at best. The number of commits per week to the code base is very low so frequent releases don’t do much for us. Add to this that some of the changes we make are dependent on slow upstream sources means making frequent releases is basically pointless.

                                            So, like pretty much everything in software, small frequent releases? Maybe.

                                            1. 2

                                              Company: Microchip

                                              Company site: https://www.microchip.com

                                              Position: Principal Engineer-Software (for the XC32 compiler team)

                                              Location: remote, but in the Toronto area

                                              Description: Looking for an experienced compiler engineer to work on code size optimizations and other features in the compiler toolchain, implement support for new hardware devices, and various other duties (see link below).

                                              Tech stack: GCC and Binutils, Windows/Linux/macOS

                                              Contact: Submit via this link: https://careers.microchip.com/job/2906/principal_engineer_software. You can ping me here or on IRC if you have other questions. (I am away on vacation for a week so I won’t be able to answer right away.)

                                              1. 4

                                                Why use C89 in 2021? That’s a 32 year old standard. We have C17 now.

                                                1. 9

                                                  Especially with C89 you have a huge variety of compilers available allowing you to run your code on nearly every architecture as well as checking your code for maximum standard compliance (some compilers are more liberal than others).

                                                  With any C standard that is >= C99 you are effectively forced using clang or gcc.

                                                  1. 4

                                                    Can you give an example of an architecture that is only supported by a C89 compiler?

                                                    1. 3

                                                      MS VisualC++ only began to add C99 support in Visual Studio 2013, and I’m not sure they support anything newer. So you’re no longer limited to C89 for Windows code these days, but there’s a long tradition of “keep your expectations very low if you want to write C and be portable to the most popular desktop OS”.

                                                      1. 3

                                                        According to this blog post they were working on C11 and C17 support last year. I don’t know how far they are with things they listed as missing.

                                                  2. 4

                                                    Later versions of the C standard are a lot less portable and a lot more complex. I use C89 when I want to write software that I know will be portable across many different machines and will work with nearly any C compiler. IMO, it doesn’t really make sense to target anything later than C11; C17 doesn’t make enough notable and useful changes to warrant using it.

                                                    1. 1

                                                      Some old code bases, especially in the embedded space, are still written for it.

                                                      1. 2

                                                        This is neat but I have doubts that with any large, complex ELF file that the result will be navigable. The “Hello world” example already has many, many arrows.

                                                        1. 4

                                                          I tried it on a small-ish (460kb) RISC-V ELF. The resulting HTML was just on 2mb. Once loaded, the Chromium tab used 320mb of RAM. The result was not exactly useful, and had some weird graphical glitches which turn out to be arrows that span 200,000px. It’s a neat concept, though.

                                                        1. 1

                                                          The author claims this is shortest:

                                                          b=( "${a[@]}" ) # copy array
                                                          

                                                          But this is 27 characters (including the comment).

                                                          The following is quite a bit shorter, and clearer:

                                                          copy_of_a=( "${a[@]}" )
                                                          

                                                          If you want it clearer still, define a function. Then you don’t need “# copy array” every time you want to copy an array. DRY.

                                                          1. 7

                                                            Then you don’t need “# copy array” every time you want to copy an array. DRY.

                                                            I highly recommend you read the post more carefully. It really seems like you have missed the point here.

                                                            1. 5

                                                              But this is kind of a low-hanging fruit, isn’t it? Now assume that a and b bear some semantic context, say, about the problem domain. So you are basically replacing b by a potentially confusing variable name just for the sake of removing the comments.

                                                              I agree that this might be a better option in some cases—maybe most of them—but it is not a silver bullet.

                                                            1. 10

                                                              Comments can lead you astray, because they get out of date. The code is the only source of truth.

                                                              The reason I’ve never liked this sentiment (and the OP is only quoting it) is that I consider comments part of the code.

                                                              1. 5

                                                                You can also forget to update a piece of code when you’re making a large swooping change, but that will most likely just crash or produce incorrect results, which makes you aware that you “missed a spot”. Comments don’t have this property, so they will more easily be missed as part of an update.

                                                                1. 6

                                                                  Large swooping changes are exactly the scenario where extra time spent on documentation is warranted. Plus, if the comments are co-located with the code, it’s easy to catch missing/incorrect docs in a code review (which again, should be performed for any large swooping changes!)

                                                                  1. 4

                                                                    On the other hand, words-in-sentences-in-comments are better than words-in-variable-names at describing requirements, and assumptions, and what direction the code should evolve in. Incidentally all things that are more likely to start correct and/or remain correct across updates, while code is more likely to contain or introduce defects.

                                                                    Secondly, if I’m gong to figure out the intent and assumptions of a piece of code, I’m basically reconstructing what a comment would say, and I’d rather have the comment to start with.

                                                                    Thirdly, even if the code is updated and the comment is not, having the ‘previous’ comment there is a scaffolding that’ll help me figure out the new code quicker. Diff to the previous intent is likely to be small, after all. Of course I’m going to need to figure out whether the new code is correct or the old comment; but that’s better than figuring out whether the new code is correct without a comment.

                                                                  2. 2

                                                                    My tests can’t check my comments, though.

                                                                    Granted, they can’t check that my function/method/procedure names match what they do either.

                                                                    1. 1

                                                                      Rust can! Sort of. They’re called doctests and they make sure your code samples compile and assert correctly, just like regular tests!

                                                                      I like them because examples doubling as simple tests also encourages you to write more examples.

                                                                      1. 1

                                                                        I almost feel like that misses the point of this article though? If I’m writing an explanation of the happy path of a function, there’s likely not really anything I can put in a comment that doctest would be useful for. It’s most likely just prose.

                                                                        Where doctest does work very well is if I’m writing comments that get turned into API documentation, but that’s an entirely different set of comments than what Hillel is describing in the article.

                                                                        1. 1

                                                                          That’s true, hence “sort of” in my comment. But doctests are better than nothing, even if they can’t check prose comments. You don’t need to refactor a crate into a separate library to document some strange behavior of a particular function with examples.

                                                                          The author does mention two cases where examples could help:

                                                                          • Tips: “This function is currently idempotent, but that’s an implementation detail we intentionally don’t rely on.”
                                                                          • Warnings: “This routine is really delicate and fails in subtle ways, make sure you talk with XYZ if you want to change it.”

                                                                          But otherwise I agree. The “tests” for comments are rigorous code review, which unfortunately falls under the “try harder” class of solutions.

                                                                          Also, even if it’s only tangentially related, I think doctests are pretty cool and worth mentioning.

                                                                        2. 1

                                                                          I’m aware of doctests, but those are code again, even if they are written “in comments” – the comment less, code better crowd absolutely treat all tests (doctest or no) as part of the solution.