Threads for hherman

  1. 2

    this is how you know its going to succeed. you dont get much HN/lobste.rs hate for failing/unpopular projects. for example mastodon (not exactly failing, but not living up to many people’s hopes for it either)

    1. 3

      In go, single character variable names are idiomatic, especially when the scope is small.

      1. 3

        I’ve read that, and I try to follow idioms as much as possible, but I’m having a really hard time with this one because I really can’t find any justification for it (i.e. what makes Go so special that decades old advice is suddenly irrelevant?). I can see it if “small scope” means 1 or 2 lines, but beyond this I’m having a really hard time keeping track of them.

        But even if one accepts the idiom, how do you solve my issue when the scope is not small?

        1. 4

          http://doc.cat-v.org/bell_labs/pikestyle

          Ah, variable names. Length is not a virtue in a name; clarity of expression is. A global variable rarely used may deserve a long name, maxphysaddr say. An array index used on every line of a loop needn’t be named any more elaborately than i. Saying index or elementnumber is more to type (or calls upon your text editor) and obscures the details of the computation. When the variable names are huge, it’s harder to see what’s going on. This is partly a typographic issue; consider

          1. 8

            This is such a dishonest argument, though, because it presents a false dilemma between very short names and “huge” names.

            In Python I routinely write loops like:

            for entry in BlogEntry.query():
                # do thing with entry...
            

            This is more readable than a single-letter name would be, and doesn’t fall into any “huge name” trap I’m aware of.

            It’s not the 1970s anymore. Our computers have the disk and memory space to let us use names like “format” instead of “fmt”. And so we should, and should leave the 1970s conventions in the dustbin of history where they belong.

            1. 5

              I’m not sure how this is a dishonest argument.

              Your Python code is equally well expressed if entry is named e, as far as I can see. It is not obvious that entry “is more readable than a single-letter name” of e, at least without more context.

              Preferring fmt over format is not a decision made from 1970s-era technical constraints. It’s possible to prefer the shorter form over the longer form, even if our servers have bajillions more available resource-bytes.

              1. 4

                I’m not sure how this is a dishonest argument.

                Because, as I said, it presents a false dilemma. If the only possible choices were single-character names, or “huge” unwieldy names, there might be a point. But there are in fact other options available which aid in readability by providing context without being “huge”.

                It is not obvious that entry “is more readable than a single-letter name” of e, at least without more context.

                Single-letter names rarely provide context. If a file contains multiple functions, each of which contain at least one loop, single-character names fail to differentiate which loop (or which function) one is looking at.

                Also, I find it somewhat amusing that single-character loop variables are extremely likely to lose context or even collide during refactorings, yet as far as I’m aware the reason why Go stylistically discourages some other naming conventions (such as a “this” or “self” parameter name for functions which receive an instance of a struct defined in the same file) is that refactoring might cause loss of context.

                But mostly, the single-character thing just feels to me like another instance of Go’s designers attempting to stand athwart the history of programming language design and practices, and yell “Stop!”

                1. 3

                  Single-letter names rarely provide context.

                  The normal guidance in Go is to name variables with expressivity (length) proportional to their lifetime, and the constraints of their type.

                  The name of a variable that’s only in scope in a single line block needs to provide far less context compared to the name of a variable that’s in scope for an entire e.g. 100 line function.

                  A variable of type SpecificParameter can be named sp because that meaning is unambiguous. A variable of type string that represents an e.g. request ID should probably not be called simply id, better e.g. reqID, especially if there are other string parameters that exist with similar lifecycles.

                  If a file contains multiple functions, each of which contain at least one loop, single-character names fail to differentiate which loop (or which function) one is looking at.

                  It’s not the job of a variable name to disambiguate at the file, or really even function, level. An index variable for a one-line for loop is probably appropriately named i no matter how many times this situation is repeated in a function or file.

                  1. 4

                    A variable of type SpecificParameter can be named sp because that meaning is unambiguous. A variable of type string that represents an e.g. request ID should probably not be called simply id, better e.g. reqID, especially if there are other string parameters that exist with similar lifecycles.

                    Or name them SpecificParameter and requestID. Pointlessly shortening variable names far too often leads to names that confuse rather than communicate. Is reqID a request ID? A requirement ID? A requisition ID? If I see that name out of context – say, in a debug log – how am I supposed to know which one it is?

                    And even in context it’s not always clear. Going back to the “self” param debate, as I understand it the standard Go approach if I want to write, say, a function that takes and operates on a Server struct, is to declare the parameter as s. Some obvious and more communicative names are ruled out by other aspects of Go’s naming rules/conventions, but how exactly is that informative? If I’m not directly in that file, and just see a call to the function, I’m going to need to either go look up the file or rely on IDE lookup showing me the type of the parameter to figure out what it’s supposed to be, since outside of the original context it might be s for Server, or might be s for Socket or for SSLContext or SortedHeaders or…

                    (and the loop-index case does still lose context, and also needing to name loop index variables is an indication of a language with poorly-thought-out iteration patterns)

                    But really it just comes down to a question of why? Why does requestID need to be shortened to reqID? Is the target machine going to run out of disk space or memory due to those four extra characters in the name? No. So there’s no concrete resource constraint requiring an abbreviated name. Is there any additional clarity provided by naming it only reqID? No, in fact clarity is lost by shortening it. What is the alleged gain that is so overwhelmingly important that it requires all variable names to be shortened like this? As far as I can tell, it really is just “that’s the way we did it with C in the 1970s”.

                    And it’s not even consistent – someone linked below a buffered I/O module that’s shortened to bufio, but the Reader and Writer types it works with are not shortened to Rdr and Wrtr. Why does it have a function Discard and not a function Dscrd? Why NewReaderSize and not NwRdrSz? There’s no principle here I can detect.

                    1. 4

                      Once I’m familiar with the convention, it’s a lot easier for me to recognize the shape of reqID than it is to parse the text “requestID”.

                      Right now I’m working in a codebase where we have to write sending_node_component all over the place and it’s so miserable to both type and parse that the team unanimously agreed to just alias it is snc.

                      1. 1

                        You put my feelings into words, thank you

                      2. 2

                        Why are you abbreviating ‘identifier’ throughout your post? What about SSL? Communication is full of jargon and abbreviations that make sense in context. They’re used to make communication smoother. Code does the same. Variable names are jargon.

                        But really it just comes down to a question of why?

                        Because to many people, it’s simply more readable.

                        1. 3

                          “SSL” is an initialism, not an abbreviation.

                          Variable names are jargon.

                          So there’s an agreed-upon set of standard names which all programmers everywhere are trained on, aware of, and understand? Cool, so why does this thread – asking about how to name variables – exist in the first place?

                          They’re used to make communication smoother.

                          And I gave examples of how abbreviated variable names fail at this, where slightly-longer versions do not have the same issues. I note that you haven’t actually engaged with that.

                          1. 2

                            I simply don’t find your examples compelling. I simply don’t find your supposed failures harder to understand.

                            And if you insist on being pointlessly pedantic, single letter variable names are also initialisms of single words.

                            1. 2

                              So, suppose we look at a set of possibilities:

                              • requestIdentifier
                              • requestIdent
                              • reqIdentifier
                              • requestID
                              • reqIdent
                              • reqID
                              • reqI
                              • rqID
                              • rqI
                              • rI
                              • r

                              Do you honestly believe that all of them are basically equally useful and informative, even when viewed out of context (say, in a log or error message when trying to debug)?

                              1. 3

                                I never see variable names in log files, let alone without additional information.

                                Do you typically dump raw variable names into logs, with no additional context? Don’t you think that indicates a problem with the quality of your logs?

                                It seems pathological to focus on readability of variables in the context of poorly written log messages.

                                1. 2

                                  Log messages are one example of when a name might appear out of context.

                                  Do you believe all of the above names are basically equally useful and informative, even when viewed out of context? Because if you work someplace where you never have to debug based on small amounts of context-missing information, perhaps you are lucky or perhaps you are THE ONE, but the rest of us are not. So I’d appreciate your input on the hypothetical missing-context situation.

                                  1. 3

                                    I think the basic disagreement is whether the names need to make sense without context because I don’t think they have to. The context is the surrounding code.

                                    1. 2

                                      Or maybe the names of local variables matter a lot less, and the way the code scans when skimming matters more than you acknowledge.

                                      It’s easier for me to read code with shorter lines. The shape of the code matters about as much as the names, maybe more.

                                      even when viewed out of context?

                                      This is a non-consideration. I don’t view them out of context. Short names tend to read better in context.

                                  2. 1

                                    Nobody is suggesting this.

                                    The claim is that the verbosity of a variable name ought to be a function of the lifetime of that variable, and the ambiguity of its name versus other in-scope variables.

                                    Variable names always exist in a context defined by source code.

                            2. 1

                              If you have a for loop over SpecificParameter values which is 3 lines of code long, there is no purpose served by naming the variable in that loop body as specificParameter, in general. It’s laborious for no reason.

                              Variable names always exist in the context of the source code in which they are written. There is no realistic way that the literal name of a variable as defined in source code could end up in a debug log.

                              1. 1

                                What is the alleged gain that is so overwhelmingly important that it requires all variable names to be shortened like this?

                                So why did you use the abbreviation IDE instead of spelling it out?

                                1. 3

                                  “IDE” is not an abbreviation, it’s an initialism. If you’re going to be pedantic like this you have to be correct about it.

                                  1. 2

                                    According to Wikipedia, an initialism is a type of abbreviation.

                                  2. 1

                                    “IDE” is a lexicalized abbreviation. “req” is not: you wouldn’t say “I sent you a req”, would you?

                                    1. 1

                                      Sure I would. Especially in the context of hiring.

                              2. 1

                                Single-letter names rarely provide context. If a file contains multiple functions, each of which contain at least one loop, single-character names fail to differentiate which loop (or which function) one is looking at.

                                I would say if the name of the function is not visible on screen at the same time, your function is probably too long. But what’s your point here? That local variables should have names that are unique in a source file, although they are not in global scope?

                                But mostly, the single-character thing just feels to me like another instance of Go’s designers attempting to stand athwart the history of programming language design and practices, and yell “Stop!”

                                This one I don’t understand. Newer languages do not have/allow longer variable names than older languages (for the most part). So I don’t see how the length of variable names has anything to do with the history of language design.

                                1. 2

                                  I would say if the name of the function is not visible on screen at the same time, your function is probably too long.

                                  I’d argue there’s no such thing as a function that’s too long, only too complex. Do you think this function would be worthy of splitting, being over a hundred lines long?

                                  In my opinion it’s not, as it’s just a linear list of tasks to be done in order to generate a chunk of bytecode for a function. It’s like a cake recipe. It’s a list of steps telling you how to mix and bake all the different ingredients to produce a cake.

                                  Now obviously, some cake recipes are fairly complicated, and they can be split into sub-recipes - but that is a result of deep nesting being hard to keep track of, not length. In Unreal Engine for instance there are lots of functions which go incredibly deep in terms of nesting, and those could probably be factored out for readability, but I still wouldn’t be so sure about that, as moving out to smaller functions tends to hide complexity. It’s how accidental O(n²) happens.

                                  Which is why I tend to factor code out to separate functions if I actually need to reuse it, or to make a “bookmark” showing a future extension point.

                              3. 2

                                equally well expressed if entry is named e

                                If it was for e in BlogEntry.entries(), I’d agree (and I’d say it should be renamed to this because query is too vague) because then you know you’re getting an entry back from that method. But a generic BlogEntry.query() doesn’t give you any hint as to what’s coming back - which is where for entry in ... is helpful because it signals “hey, I’m getting an entry object back from this”. Means you don’t have to hunt down BlogEntry.query and find out what it returns.

                                1. 2

                                  I’d argue if that’s not clear then it’s not e that is the problem, but .query that is. Also if you use some form of IDE the “hunting” down is usually okay. You anyways want to know whether it returns an error. And sometimes you want to know whether it’s some response type rather than the actual data or something. But in this example I think e would be as clear as entry - at least it is for the scenarios I can think of.

                              4. 1

                                100% with you on this, but if this thread shows something it’s that this is way more subjective than I thought.

                                TBH I don’t mind it as much when it’s in the standard library, a few well known exception to the rule are not too bad.

                                1. 1

                                  The quote compares i to index. You are misrepresenting the argument.

                              5. 3

                                what makes Go so special that decades old advice is suddenly irrelevant?

                                Go is a reaction against earlier mainstream languages, in particular C++ and Java, and part of the reaction is to “reset” what are acceptable and what are not.

                                1. 1

                                  (i.e. what makes Go so special that decades old advice is suddenly irrelevant?).

                                  Even older advice and experience, from the people that wrote Go. They (and I) find it more readable to use short names, so they did.

                                  For example: https://github.com/golang/go/blob/master/src/bufio/bufio.go

                              1. 2

                                Why not simply run the service on a wireguard network and connect to that? Why pipe you private data through some unknown entity when you don’t have to?

                                1. 2

                                  So the public at large can connect to your service?

                                  1. 1

                                    Then you should run it on a proper server in a proper datacenter!

                                    1. 6

                                      why should I when I could use tailscale funnel and its easier?

                                      1. 4

                                        Then you should run it on a proper server in a proper datacenter!

                                        This is solely a question of scale, and not everything on the internet has to be scaled for millions of users, any more than every telephone number needs to be answered by a call center.

                                        I keep a copy of my wedding video on a site that is accessible outside my private network (with appropriate credentials), because sometimes I want to show it to others. I don’t want it to be publicly accessible, I don’t want it hosted on youtube which will complain about copyrighted background music, and I certainly don’t need it often enough that it’s worth paying someone else for hosting.

                                        Accepting these sorts of services is, I think, a key to building a more decentralized internet. I’ve been obsessed with availability and uptime forever - I remember bragging posts about uptime on usenet - but actually, those things don’t matter in the way I expect when the set of affected users is small.

                                  1. 3

                                    i feel uncomfortable with the direction this is going in. it feels like we’re headed towards embracing inheritance or something like it.

                                    it feels like there is a lack of consensus or firm opinion on the right way to solve extension/inheritance in go. I hope russ writes a long blog post about it or something :P

                                    1. 1

                                      I think the advantage of this versus inheritance is that it’s bespoke, so it can be tailored to the needs of the code instead of shoehorning everything into working the same way (or worse, not working the same way because of metaclasses), but I take your point.

                                    1. 8

                                      I thought the opt out telemetry sounded reasonable to me, but this also strikes me as a good take. As a thought experiment, I can ask myself what if the proposal had come from the Chrome team (lol, too late, they spy on everything) instead of the Go team, and I think I would be much less positively inclined. I trust the Go team. I don’t trust “Google”. I extremely distrust the Blink team. But for someone who doesn’t interact with the Go team, they’re all just “Google”.

                                      1. 1

                                        I think I would be bitter that Russ went back on opt out telemetry, except I actually do think the mandatory opt in during install will get a fair number of users, and so it won’t be a complete wash.

                                      1. 6

                                        Challenge for those opposed to this proposal: name a single real negative consequence that could have come from it.

                                        “It violates my rules” is not a consequence.

                                        1. 6

                                          A feature I rely upon is removed because the majority of users don’t use it.

                                          1. 2

                                            IMO that can be good for the world, at some personal cost. Depends on the feature though.

                                        1. 38

                                          The opinion of Russel Cox, in the linked article from the 24th of February, is surprising. He writes:

                                          In the GitHub discussion, there were some unconstructive trolls with no connection to Go who showed up for a while, but they were the exception rather than the rule: most people seemed to be engaging in good faith.

                                          I have read a good chunk of the comments, also the ones which were collapsed for moderation reason. I didn’t see any trolls. Of course the debate was heated and Google got criticized but I didn’t see any troll trying to derail the conversation on purpose.

                                          Also the comments would be from users “with no connection to Go”. Well I’m glad Russel Cox can know which users have a connection to Go or not just from their Github profile. That makes him prescient so I wonder why he needed the telemetry proposal in the first place.

                                          That one would need to trust Google to not log your IP (thus also location) and time usage of the Go tools is also ignored once more.

                                          I feel the proposal and specially the way it was presented damaged the reputation of Go in a significant proportion. But for this only time will tell us if it’s true, no telemetry.

                                          1. 4

                                            Btw, where did you find Russ Cox’s full name? I was curious since “Russel” seems like an unusual spelling.

                                            1. 3

                                              Thanks, it’s a mistake on my part but now it’s too late to edit the comment.

                                              1. 1

                                                Honestly, I was just curious where the “Russel(l)” came from, regardless of the spelling. I’ve only even seen “Russ.”

                                            2. 3

                                              I have read a good chunk of the comments, also the ones which were collapsed for moderation reason. I didn’t see any trolls. Of course the debate was heated and Google got criticized but I didn’t see any troll trying to derail the conversation on purpose.

                                              You clearly didn’t look that hard.

                                              I feel the proposal and specially the way it was presented damaged the reputation of Go in a significant proportion. But for this only time will tell us if it’s true, no telemetry.

                                              There’s no proposal yet.

                                              1. 5

                                                There’s no proposal yet.

                                                Some of the rebuttals to criticisms in this thread have been “read the proposal!” and others have been “there is no proposal”.

                                                I’m not sure what, exactly, is going on here, but it’s making me even more suspicious than I would have been to begin with.

                                                1. 4

                                                  There are a set of blog posts on Russ Cox’s personal website which outline a design for telemetry. They were posted with the intent of gathering feedback. Then a bunch of weirdos (who obviously didn’t read the blog posts) started giving speeches about morality and Google’s evil plans to use Go for data harvesting.

                                                2. 0

                                                  I think their sentence would be more accurately rendered:

                                                  I hope the proposal and specially the way it was presented damaged the reputation of Go in a significant proportion. But for this only time will tell us if it’s true, no telemetry.

                                              1. 4

                                                Conc is bad tho?

                                                I made a much simpler API: https://github.com/carlmjohnson/workgroup

                                                I tried to write some comparisons to conc, but all of the conc code is too convoluted and does the wrong thing, so I couldn’t.

                                                1. 5

                                                  Conc is bad tho?

                                                  That’s not a very charitable take on conc.

                                                  but all of the conc code is too convoluted and does the wrong thing, so I couldn’t.

                                                  without anything to back this up, this reads like FUD.

                                                  The workgroup library you published might be better than conc, but no need to disparage the work of someone else to promote yours.

                                                  1. 3

                                                    “is bad tho?” is comic hyperbole. Sorry, I don’t mean to dismiss their work. I just am not impressed that their patterns are particularly elegant. It seems like just as much boilerplate as errgroup and not especially more power. (It’s better than pure stdlib of course, but that’s a low bar.)

                                                  2. 1

                                                    Looking at your examples, I’d reach for x/sync/errgroup for all of those.

                                                    1. 1

                                                      You can also do all of them with pure channels/sync.WaitGroup. The point is to do them concisely. errgroup is pretty good, but still too much boilerplate. Also it only returns the first error in a set, so it does something different, and it doesn’t really help you write the code in the third example where you’re collecting results and spawning new tasks.

                                                      1. 2

                                                        would be neat to see comparisons with errgroup in your readme, since my immediate impression was also “the main benefit is that it returns errors”. might help emphasize the other benefits

                                                  1. 4

                                                    The author gives two reasons why they think that their proposal will be opposed:

                                                    The first is the significant privacy cost to users of collecting and storing detailed activity traces. The second is the fact that access to this data must be restricted, which would make the project less open than most strive to be.

                                                    There are more! The third is the complication of all workflows; tools which previously worked offline now sporadically enter codepaths which can break and require additional capabilities to run. The fourth is the possibility of users sending garbage data simply because they can. The fifth is the massive sampling bias introduced in the second post by the fact that many distros will unconditionally disable this telemetry for all prebuilt Go packages. The sixth is that removing features based on percentage of users enjoying the feature will marginalize users who don’t use tools in ways approved by the authors, removing choice and flexibility from supposedly-open-source toolchains.

                                                    Not the most ridiculous proposal from the author, but clearly not fully baked. An enormous amount of words were spent explaining in technical detail how the author plans to violate their users’ privacies without overt irritation. Consider this gem from the third post:

                                                    The Go build cache is a critical part of the user experience, but we don’t know how well it works in practice.

                                                    How do they know that it’s critical, then? So much ego and so little understanding of people as individuals.

                                                    Finally, I hope it is clear that none of this is terribly specific to Go. Any open source project with more than a few users has the problem of understanding how the software is used and how well it’s working.

                                                    The author is explicitly telling us that they should not be trusted to publish Free Software.

                                                    Edit: I explicitly asked the author about the fourth reason. The author doesn’t understand the problem, and intervention may be required in order to teach them a lesson.

                                                    1. 8

                                                      The author doesn’t understand the problem, and intervention may be required in order to teach them a lesson.

                                                      A) Russ clearly understands that users can submit garbage data.

                                                      B) It’s pretty anti-social to be so opposed to telemetry that instead of merely opting out or boycotting a product you actively send junk data. It’s fine to take direct action against something that is harming you. For example, removing the speakers that play ads at gas station pumps in the US now is a positive good because those ads violate the social contract and provide no benefit to consumers who just want to pump their gas in peace. But this telemetry is meant to benefit Go as an open source tool, not line Google’s pockets. You can disagree about if it’s too intrusive if you want, but taking active measures against it is an uncalled for level of counter-aggression.

                                                      1. 5

                                                        We must have different life experiences. Quoting from the Calvin and Hobbes strip published on August 23, 1995:

                                                        Calvin: I’m filling out a reader survey for Chewing magazine.

                                                        Calvin: See, they ask me how much money I spend on gum each week, so I wrote, “$500.” For my age, I put “43,” and when they asked what my favorite flavor is, I wrote “garlic/curry.”

                                                        Hobbes: This magazine should have some amusing ads soon. Calvin: I love messing with data.

                                                        We don’t need to send data to an advertiser so that the advertiser can improve their particular implementation of a programming language. If this sort of telemetry is truly necessary, then let’s find or establish a reputable data steward who will serve the language’s community without preference to any one particular toolchain.

                                                        1. 7

                                                          A) Calvin is meant to be an anti-social twerp, not a role model.

                                                          B) Do you think the Go tool is going to start serving DoubleClick ads? There’s no analogy here.

                                                          1. 7

                                                            Twice you’ve used the phrase “anti-social”. We aren’t in the UK and your meme doesn’t work here. If you want to complain about a collective action being taken against a corporation, then find a better word, because the sheer existence of Google is damaging to the fabric of society.

                                                            Point (B) deserves to be addressed too. You seem to think that an advertiser only causes harm when they advertise. However, at Google’s size, we generally recognize that advertising causes harm merely by collecting structured data and correlating it.

                                                            1. 3

                                                              If the problem is that Google exists at all, then get people in SF to throw eggs at the Google buses or bribe some Senators into letting the million and half pending anti-trust lawsuits go through. I don’t see how hurting the telemetry data for Go has any connection whatsoever to the goal of a world without Google. All it does is harm people who would benefit from a better Go compiler/tools. You can hate Google all day, and you probably should. I deliberately have never applied to work at Google because I don’t believe in their corporate mission. However, none of that has anything to do with the issue at hand, which is adding telemetry to Go. If you can show that they’re going to secretly use the telemetry to send Big Mac ads to developers, then you can be mad at them, but you haven’t shown that.

                                                              1. 1

                                                                I don’t see how hurting the telemetry data for Go has any connection whatsoever to the goal of a world without Google.

                                                                I’d argue that collecting data via ET Phone Home telemetry without explicit consent is a grievous breach of the Social Contract. While I myself am a non-belligerent person, you can bet that there are people who share my outlook about consent and say that one bad turn deserves another. Poisoning telemetry data is a tactic in line with the traditions of Luddism and sabotage. It’s throwing a monkey-wrench into the grinding gears of the machine. While I’m not gonna sit here and encourage it (I’m not stupid), I do understand the mindset.

                                                                “Rub some telemetry on it” is definitely in line with Google culture. Poisoning the stream won’t stop that.

                                                                Yeah, kids, be good and don’t poison the datastream. The ethical approach is to stop using Go if they add opt-out telemetry to their toolchain.

                                                                1. 1

                                                                  A marketing company that calls your home phone number at dinner time is scummy, but you don’t get to yell at the person on the other end of the phone because they’re just taking the best low paying job they could find. Instead you have to get the https://en.wikipedia.org/wiki/National_Do_Not_Call_Registry enacted and get funding to enforce the law.

                                                                  1. 2

                                                                    A marketing company that calls your home phone number at dinner time is scummy, but you don’t get to yell at the person on the other end of the phone because they’re just taking the best low paying job they could find.

                                                                    Legally, I sure do. If somebody invades my personal space, I’m well within my right to yell at them for it, even though they’re just some poor schlub doing a job. Morally / ethically, it’s a different story. The compassionate person will refrane from yelling at the aforementioned poor schlub. Even then, it’s worth noting that the most saintly of us has bad days and doesn’t always do the moral / compassionate thing. My point? People who script-read for telemarketing are going to be verbally abused by people whose right to be let alone has been violated, and we cannot pretend otherwise.

                                                                    At what point does “I’m just doing my job” go from being a reason for compassion to an excuse? I don’t have the answer to that, but I do try to be a compassionate person.

                                                                    These two scenarios aren’t equivalent anyway. The telemarketing equivalent of poisoning the telemetry stream isn’t yelling at some unfortunate script-reader. The equivalent is lying to the marketing company, wasting its resources, or possibly defrauding it. Think: trolling the Jehovah’s Witnesses and Mormons who invite themselves to your door to share their religion. This can be lots of fun, and it wastes the other person’s cycles while simultaneously preventing them from harassing somebody else.

                                                                    In 2000, someone called me up from one of those multi-level marketing scams, after a friend referred them to me. I spent three glorious hours on the phone on a Sunday night trolling some scammer. It was better than whatever was on TV at the time, no doubt.

                                                                    I’m sure there are people who do this sort of thing to telemarketers. It isn’t abuse, but it does cause them to waste cycles while getting paid and possibly entertained, yet preventing them from doing active harm to others.

                                                                    For lack of a better term, I’ll call this array of tactics “psychological warfare countermeasures”, to contrast them with electronic warfare countermeasures.

                                                                    Of course, poisoning an opt-out telemetry stream is an electronic warfare countermeasure: the equivalent of deploying chaff to confuse enemy radar.

                                                                    And I’ll end with the “Kids, don’t poison a telemetry stream” disclaimer I used yesterday.

                                                      2. 4

                                                        The author doesn’t understand the problem, and intervention may be required in order to teach them a lesson.

                                                        Are you really trying to rally lobsters into sending junk data to the Go telemetry?

                                                        1. 1

                                                          No. You aren’t correctly reading what I wrote. I’m saying that somebody will send them junk data in the future, and I anticipate that nothing short of that future situation will make them understand their mistake.

                                                          1. 3

                                                            The plain reading of “intervention may be required in order to teach them a lesson” is that you’re rallying people to intervene, ie spam the system. If that’s not what you mean, then I’m sorry for misinterpreting you, but alyx apparently has the same misinterpretation.

                                                            1. 1

                                                              Maybe my final comment in the GitHub discussion will make it clear to you and @alyx that, although I am thinking adversarially, I am still a whitehat in this discussion. I made similar comments during Audacity’s telemetry proposal, and did not develop any software to attack Muse Group.

                                                              Perhaps what irritates you is that I find the whole situation amusing. I don’t really respect the author’s understanding of society, and I think that often the correct thing to do in case of disaster is to learn a lesson. The author may not learn a lesson until somebody interferes with their plans, and I expect that the fallout will be hilarious, but I am not necessarily that somebody.

                                                              Nor, frankly, do I have thousands of spare USD/mo to waste on cloud instances just for the purpose of distracting Google. What do I look like, the government?

                                                        2. 1

                                                          The sixth is that removing features based on percentage of users enjoying the feature will marginalize users who don’t use tools in ways approved by the authors, removing choice and flexibility from supposedly-open-source toolchains.

                                                          This is good. The tool chains are still open source, that is a fact. This will:

                                                          • Make the code base more maintainable, thus over time making it less buggy
                                                          • Focus the thinking of those involved on use cases that matter the most, making more people happier
                                                          • Make the system overall simpler, and easier to understand for all users.

                                                          The world cannot be built around power users/tech elite. That would be bad.

                                                          The fifth is the massive sampling bias introduced in the second post by the fact that many distros will unconditionally disable this telemetry for all prebuilt Go packages

                                                          The fourth is the possibility of users sending garbage data simply because they can.

                                                          The data can be interpreted with its limitations in mind. That seems better than simply having no data whatsoever about the world.

                                                          So much ego and so little understanding of people as individuals.

                                                          I don’t see how this follows from Russ’ belief the build cache is critical to Go’s UX.

                                                          1. 6

                                                            Focus the thinking of those involved on use cases that matter the most, making more people happier

                                                            I don’t think it’s valid to conclude that the use cases that occur the most are the use cases that matter the most. Blind and vision-impaired people make up a small portion of all computer users; do you think it would be valid to ignore their needs in favor of making experiences better for users without vision impairments?

                                                            1. 3

                                                              True, I agree with you. But I think its a safe default to reject supporting use cases with few users. There are some concerns in specific cases which reasonably can overrule this principle, but I think the bar should be high for spending effort on rare uses.

                                                              1. 3

                                                                Mandatory XKCD? https://xkcd.com/1172 :-)

                                                              2. 3

                                                                Every project has limited resources to spend. This by definition means that some work will not be done. If you have two bugs with same severity it might be useful to know how many users each is impacting and factor that in decisions about what to work on and in what order.

                                                                1. 1

                                                                  Vision impaired users are an interesting comparison. There are lots of vision impaired people in the world. A neighbor of mine happens to work at an association for the blind/vision impaired. Many people wear glasses. Many people become blind or near blind in old age. All of us are vision impaired when it is dark, or when we use our eyes to look at something else while trying to use a computer simultaneously. Even if the absolute percentage of blind people is not that high, it ends up being a lot of people, especially factoring in situational blindness.

                                                                  One can imagine a lot of other conditions that might also be good to accommodate for, but which are less common and more difficult to adapt to. In the end, I think the ADA’s “reasonable accommodation” standard is broadly correct. There has to be a balance to try to include people when the costs are bearable without making things so expensive that it’s not possible for the majority to use it either.

                                                          1. 7

                                                            Go’s simplicity often just means that it’s lacking type hinting / systems that have been in modern languages for years. The “interface” is a hack, often times the programmer has to just throw their hands up an make an empty interface and infer the type later. Even though Go claims to have good concurrency primitives, I’ve had to track down multiple bugs that lead to undefined behavior when dealing with more complex concurrent structures.

                                                            I’ve never programmed in Rust, but I’ve used plenty of higher level languages that have proper type support (i.e. Erlang / Julia) AND good concurrency support via the former.

                                                            1. 1

                                                              What undefined behavior?

                                                              1. 2

                                                                Given

                                                                when dealing with more complex concurrent structures.

                                                                I’d presume race conditions.

                                                                I love go, but it’s approach to concurrency is “lets do things the old way, but make it less unpleasant”.

                                                                “The old way” is terrible; it takes forever to converge on correctness. The race detector is cute, but it won’t find obscure races, or races that only happen on an OS / CPU design you don’t personally test it on.

                                                                1. 1

                                                                  The race detector is cute

                                                                  Do you know if there are any fuzzing libraries for scheduling? Something where I can feed in a program and run it 1000 times and the scheduler will try a bunch of edge case schedules?

                                                                  1. 1

                                                                    The race detector randomizes the scheduler decisions.

                                                                    1. 1

                                                                      That’s just for threads, though, right? What about processes?

                                                                      1. 1

                                                                        Sorry, I was responding specifically in the context of Go. The race detector there will randomize the Go runtime’s scheduler decisions (which goroutine to schedule, which thread it will run on, etc.). I don’t know about similar options for processes and the decisions the kernel scheduler makes.

                                                                  2. 1

                                                                    Is it not the case that “the old way” is necessary for reasonable performance?

                                                                    1. 2

                                                                      “Performance” is a many-headed beast (eg erlang has a great latency story). However, it’s true that there are problems with tight throughput requirements & highly-interrelated data that’s not amenable to partitioning.

                                                                      However, Rust (well, safe rust) combines “manual mutexes” with compile-time static analysis which guarantees that you got it right via the ownership model.

                                                                      Personally, I find the rust ownership model unpleasantly restrictive (though I hear it’s able to infer more and more these days). However, if I were going to write something that used manual synchronization, I’d reach for rust before anything else, because “borrow checker says no” is a much easier problem to solve than “user reports segfault every few weeks”.

                                                                      1. 1

                                                                        I guess I just don’t have enough experience with code that can “segfault every few weeks” to speak to this point 😔

                                                                        1. 2

                                                                          I really, really wish I didn’t either 😅

                                                                    2. 1

                                                                      I’m curious if you’ve had this experience with some Go code you were writing? Especially of the form “I deployed this to prod and discovered the issue in some nasty/hard to debug way”

                                                                      1. 2

                                                                        My first job out of uni was fixing race conditions in a distributed database engine (which was a horrible multithreaded thing full of manual synchronization, AKA “the old way”). This gave me a pretty good eye for what sort of locking patterns were likely to be erroneous.

                                                                        When I worked on a go team, I spotted (& verified the existence of) a couple of race conditions a year, mostly during code review, mostly based on “that looks like the bug I fixed all those years ago…”.

                                                                        If I needed that kind of in-process concurrency, I’d be much happier with the way it’s done in rust, or the way it’s done in erlang.

                                                                    3. 2

                                                                      Go’s type system does not have any notion of transferable ownership. When you start a go routine, the closure captures (by reference) everything in scope. All of these things are now shared between two concurrency contexts. In Go, all data races are undefined behaviour and so if you accidentally write to both then you are in UB land. This can trivially break memory safety because slices are a value type and writing to a slice is not atomic, so a store racing a load can result in the base and bounds getting out of sync. Now, somewhere later in your program, you get memory corruption. At this point, you may as well just write C++, because at least there’s mature tooling for debugging this kind of problem in C++. In contrast, the Rust equivalent of this would require either the Send or Sync trait to be able to either copy or move the reference to another concurrent context.

                                                                      1. 2

                                                                        At this point, you may as well just write C++, because at least there’s mature tooling for debugging this kind of problem in C++.

                                                                        Are you saying that built in race detector is not mature?

                                                                        1. 1

                                                                          Go’s type system does not have any notion of transferable ownership

                                                                          Transferable ownership is hugely beneficial with regards to safety, but it’s no panacea. Specifically, it prevents by construction a large class of high-performance design patterns.

                                                                    1. 11

                                                                      Having worked professionally with both Rust and Go, I don’t agree that Rust has “worse overall productivity” than Go; indeed, I’ve spent a huge amount of time tracking down strange concurrency issues, poorly documented interfaces, and tooling issues with Go, and that hasn’t been an issue for me with Rust. That said, I worked with Go in the context of Docker internals, so that might be the root of the problem rather than the language itself.

                                                                      1. 7

                                                                        100% yes, the more I use Go the more I discover it’s just a syntactic wrapper around C. Trying to maintain a project with transient dependencies is a nightmare (I’m looking at you /x/stdlib). It’s type system is so rudimentary that I struggle to parse json in a fashion that doesn’t have me writing functions like doThingInt and doThingDouble. And don’t even TRY to write any statistical / numerical modelling software with it, since it’s type system can’t even do basic conversions like Int -> Int64 automatically / intuitively.

                                                                        1. 2

                                                                          And don’t even TRY to write any statistical / numerical modelling software with it, since it’s type system can’t even do basic conversions like Int -> Int64 automatically / intuitively.

                                                                          Those conversions are performance-sensitive; doing them automatically means unpredictable memory layout changes.

                                                                          Personally, that kind of performance tweaking is totally irrelevant to the software I write, but if I were writing numerical modelling software I’d definitely want to know which integer type I were working with very early on.

                                                                          1. 1

                                                                            I’ll provide a more concrete example. Let’s say I’m trying to model ocean flows, I’ll use a grid system where temperature / inflow / outflow are variables within the grid. The data type is extremely important, but once it’s defined in a structure, type conversion should be automatic. For different parameters, we’ll want to precisely control the floating point precision / size etc, but when doing numerical computations, we shouldn’t care what type the values are! We should be able to write a function that automatically performs the conversions while computing AND it should be able to perform the last conversion to the output variable that we’ve defined a float/int type for.

                                                                            Edit: Floating point issues removed for brevity :)

                                                                            1. 1

                                                                              Right - I had assumed that for numerical computations you would want to get the data into matching types ahead of time, instead of doing the conversion inside the loop. However, I can see that would sometimes involve an unacceptable memory use overhead.

                                                                        2. 3

                                                                          I think this is a matter of what you’re working on. If the performance differential (in memory or CPU use) between Go and Rust is not that important, then bothering with lifetimes/the borrow checker seems like a substantial cognitive load cost. If you do care, getting granular control over mem/cpu in Go may be more frustrating than in Rust.

                                                                          1. 5

                                                                            Maybe there is a third option. I don’t use it for memory management or performance, but mainly because I want things to be correct. And the way Rust forces me to think about error handling and option leads me personally in the right direction. And yes, that also means I’m not as fast in prototyping as I am in other languages, like Dart.

                                                                        1. 6

                                                                          I agree with parts of the article, but heres one thing it overstates: it says the first way of using C# await is almost never correct, and implies by contract that one’s first stab at using goroutines usually is correct. That’s not true. There are a lot of surprises around goroutines and channels. They’re nice tools for the job, but they don’t just make it super simple.

                                                                          1. 1

                                                                            I think it would be interesting to explore which is easier to iterate on. It seems true that the first stab at any modality is usually wrong (with some wiggle room) but I bet theres more leverage on iteration.

                                                                          1. 19

                                                                            “Go is a better Java / C#, while Rust is not”. (Emphasis mine)

                                                                            As a Go programmer, I wish such drivel was at the top of the article, rather than in the conclusion. It would have saved me the time I wasted reading it.

                                                                            1. 19

                                                                              Huh? From where I stand, Go does 100% look like a better(both in the sense “they solve similar problems” and in “actually better” sense) Java, up to repeating generics trajectory. It is similar to Java because

                                                                              • targets the same “general & server-side programming” niche
                                                                              • has the same original design goal of being a simpler language
                                                                              • has a close perf profile of a statically typed GC language
                                                                              • places a lot of emphasis on the tool chain, rather than the language

                                                                              It directly improves upon Java by:

                                                                              • using fast (optionally cross) compilation to a statically linked native binary. This:
                                                                                • solves “easy to run” goal of Java better than Java’s approach with VM
                                                                                • removes dynamism from the runtime, which historically became a major source of complexity in the Java ecosystem.
                                                                              • adding first-class support for important performance optimizations: value types and stackful coroutines, something Java also now tries to add
                                                                              • simplifying the toolchain by packaging it up in a single-binary-interface: formatter, profiler, package manager, etc, are readily available as go commands.

                                                                              C# also followed “better Java” trajectory, but it did so by adding stuff, not by removing stuff. I don’t know about C# enough to confidentially say that Go is better, but it surely does look like a defensible position.

                                                                              And Rust is most definitely not a better Java, as the domains are wildly different.

                                                                              1. 12

                                                                                I feel people think of Go as a better Java / C#, but it isn’t. And that false belief results in a lot of Go projects that should never have been Go projects, and suffer for it.

                                                                                It’s fun and easy to meme on Java, but it succeeds as an application language and runtime because it’s actually good for building applications.

                                                                                1. 6

                                                                                  I definitely do maintain such a belief! I’d be very curious to hear specific arguments why Java would be a better language, and some specific examples of go programs which should have been Java programs. Of the top of my head:

                                                                                  • if you are building a platform with dynamically loaded plugins (think Eclipse or IntelliJ), you obviously can’t do that in Go, you need a fairly dynamic runtime!
                                                                                  • somewhat related, if you are building a desktop GUI, sucks to be you because the ecosystem is in general a train wreck, but Java is definitely among the least bad options here.
                                                                                  • there’s a line of argument that Java is faster because JIT, generational GC and many runtime knobs. This in turn is countered by value types. Benchmark results do not seem to imply that Java is in general clearly faster.

                                                                                  but it succeeds as an application language and runtime because it’s actually good for building applications.

                                                                                  It absolutely was the best “general purpose” language in 2000-2015. I think it is not that today.

                                                                                  1. 7

                                                                                    This is why asking the question is rude. Somebody wants to show everybody an hilariously shaped rock they found gardening, and neckbeards in the room start arguing about what colour the handle of your shovel should be painted, and how blue is obviously better for digging hard ground while green is far superior for moving large volumes of leaf litter.

                                                                                    1. 5

                                                                                      I don’t understand this comment (like, literally don’t understand relation between metaphor and the current conversation thread). Given upvotes, it probably is useful for me to understand, could you elaborate a bit?

                                                                                      1. 2

                                                                                        It seems to me that the core implication (which may be exaggerated for effect) is that programming languages are as interchangeable as colors of paint, and practical differences between them exist only in people’s heads. (I don’t think I agree with that implication.)

                                                                                        1. 2

                                                                                          Not at all. The core implication is that a) it’s ok to allow an entire conversation to run its course without interrupting everybody in the room to tell them why your favourite programming language is the best, and b) the arguments themselves are meaningless shouting about orthogonal points, and usually only matters of taste or opinion dressed up and presented as if they were proven facts.

                                                                                          1. 1

                                                                                            Oh, and I think it’s meant in reference to this other thread. (I hadn’t realized the comment was outside that thread.)

                                                                                          2. 2

                                                                                            Somebody writes a post about how they’re sick of nerds hijacking every single discussion to shout past each other about their current favourite programming language, and the comments in here instantly became exactly that; Nerds ignoring the topic and blasting the room with “facts” they made up justifying why their current favourite programming language is the best.

                                                                                            1. 1

                                                                                              Thanks :-)

                                                                                        2. 5

                                                                                          The Java ecosystem is closer to Django / Rails than anything in the Go ecosystem. If you want to make a new web app there are tons of tried and true Java web frameworks. The Go ecosystem is more a collection of libraries.

                                                                                          I also think Java the language is more expressive for building complex business logic abstractions. I’ve worked on a Go project where adding workflows required updating no less than 5 different boilerplate files. Could a different design have been better? Absolutely. But like all business logic it grew organically, and typical Go code doesn’t grow and adapt to new complexity without a lot of refactoring.

                                                                                          For more “systems-y” things, I would definitely prefer Go. For example, a scalable websocket server for an application otherwise written in Python. I’m also a big fan of Caddy. And I think Go makes an excellent language for command line tools. On the spectrum of C to Python, Go falls closer to C and Java falls closer to Python.

                                                                                          1. 1

                                                                                            Thanks, this is an update for me: it does seem believable that, if you are building a rich web app with heaps of business logic (which is a common case), than you might get more mileage of JVM libraries and expressiveness(my understanding is that’s stuff like annotation processors, reflection, and other things which could make Java feel like Python, not the the nuts and bolts of more OO design)

                                                                                          2. 2

                                                                                            if you are building a platform with dynamically loaded plugins (think Eclipse or IntelliJ), you obviously can’t do that in Go, you need a fairly dynamic runtime!

                                                                                            Go has plugin support in the standard library: https://pkg.go.dev/plugin.

                                                                                            1. 5

                                                                                              better not to talk about “plugin”. I don’t know that anyone uses it in prod

                                                                                              1. 2

                                                                                                Thanks, didn’t realize Go has that! Though, it’s a thin wrapper over dlopen, and unix only, so probably not a good idea to try to build an Emacs out of that.

                                                                                                1. 1

                                                                                                  This package was always experimental and is (AFAIK) abandoned, useful for PoC code but nothing more.

                                                                                                2. 1

                                                                                                  if you are building a platform with dynamically loaded plugins (think Eclipse or IntelliJ), you obviously can’t do that in Go, you need a fairly dynamic runtime!

                                                                                                  The whole hashicorp ecosystem disagrees vehemently with you.

                                                                                                  On the other hand, the hashicorp ecosystem is the only example of plugin architecture in go I can think of. But then, I don’t know a lot of go stuff.

                                                                                                  1. 4

                                                                                                    From a quick look, it looks like hashicorp plugins are separate processes using IPC for communication. For this bullet, I had “shared memory plugins” in mind. It’s an open question whether shared memory plugins are a good idea at all. For example, in VS Code plugins communicate with the editor’s core via IPC. At the same time, plugins can communicate amongst themselves via shared memory, as all plugins are in the same process. Fuchsia is heavily IPC based, and that does seem like a good “from first principles” approach. And WASM with interface types confuses the picture even more, as it really blends IPC vs shared memory boundary.

                                                                                                    1. 2

                                                                                                      And WASM with interface types confuses the picture even more, as it really blends IPC vs shared memory boundary.

                                                                                                      I think it’s new enough that there are no mature applications with a WASM plugin architecture, but to me it’s such an obvious fit that I can’t wait to try it.

                                                                                                      1. 1

                                                                                                        It’s not only new, it’s not really sufficiently there yet. You really need something like wasm components to get into the standard to describe meaningful plug-in APIs. Without this, plug-ins reduce to C ABI, which sucks.

                                                                                                        In other words, a plug-in is a box with a computational device which does something, plus a bunch of toggles on top of the box as an interface. Today, WASM is great for describing the contents of the box, but it barely has anything on the interface side.

                                                                                            2. 3

                                                                                              The original article also had emphasis on that word (italic). Maybe that was supposed to mean something like that it’s a newer language that competes in the same space as Java / C#, while Rust is a better C++ instead. I’m the post author btw.

                                                                                            1. 27

                                                                                              Every language has its zealots but I have run into more Rust zealots lately. That makes sense, of course, since Rust’s trajectory and growth is amazing.

                                                                                              That being said, it is frustrating when I get asked (or scoffed at) for writing something for fun in a non-Rust language. It’s weird, and it’s happened more than once.

                                                                                              Regardless of your favorite programming language, if someone is excited to tell you about something they worked on…just be happy for them.

                                                                                              1. 7

                                                                                                I write Ruby and Rust these days and I’m happy for you.

                                                                                                1. 11

                                                                                                  You should take up R instead. It will save you time when telling people about your favorite programming language. Also, I’m happy for you.

                                                                                                  1. 6

                                                                                                    Completely off topic, but I feel like theres a pressure on tech forums to be happy for one another. But often times I do not feel happy for my fellow commenters, but quite angry at them.

                                                                                                    1. 1

                                                                                                      or the dominant emotion, pity

                                                                                                      1. 1

                                                                                                        For your contrarianism I feel contrarily at you, but I still respect you as a colleague.

                                                                                                  2. 6

                                                                                                    Totally agree. I had an experience recently where a younger guy I know started taking a course online in python and databases because he really wants/needs to find a better job. And he called me worried because he talked to some in-law of his who was telling him he should be learning X, Y, Z languages and tools, so my buddy thought he just wasted money and time on these courses. I was able to calm him down, and have been spending time showing him linux command-line stuff to help him figure out his own environment issues (always the hardest part when you are starting, right?! even now!) which made him feel way more competent than he had before. So, definitely just be happy for people, and be encouraging when they are learning new things and encourage to not give up.

                                                                                                    1. 4

                                                                                                      I went to a Rust meetup a few times and had this a lot. I’m much more a product builder than a programmer so my mentality is often “get it in front of people asap” so I’m usually hopping between languages to use whatever is the right tool for the job. Meanwhile, those who scoffed at me would be discussing compiling complex Rust code to the frontend just to avoid React for the simplest tasks. It was an odd experience but fun nonetheless, I’m happy for them!

                                                                                                      1. 4

                                                                                                        I’ve gotten a few “why not Rust???” when mentioning I’m writing a game in C… It’s frustrating.

                                                                                                        1. 3

                                                                                                          Why is it frustrating? Was it asked in a rude way or are you finding it frustrating regardless of the way it is asked?

                                                                                                          1. 6

                                                                                                            My guess is that “the number of times you are asked” is a significant contributor. For the person asking the question, that’s a new info why not Rust for this particular project. For the person answering this same question for the tenth time there’s no information sharing, just tiring repetition.

                                                                                                            1. 12

                                                                                                              Regardless of frequency it’s also just…kinda rude.

                                                                                                              “I’m making broccoli cheese soup tonight.”

                                                                                                              “Why not barley vegetable? It is so much healthier, after all.”

                                                                                                              It’s vaguely presumptuous and condescending, implying that the person doesn’t know what’s good for them or that they don’t know their own tastes and skills.

                                                                                                              1. 3

                                                                                                                Hm, not sure it’s rude in and of itself: I think it’s generally ok to offer people information you consider helpful, even if not explicitly asked about that. This helps to avoid the situation where you don’t know that there’s something you don’t know.

                                                                                                                Or, more precisely, this depends on interlocutor of course: some people in some context loathe receiving unsolicited advice, some like it sometimes. But if you don’t know for sure (this is not a repeated interaction), you need to choose something, even if that’s asking to ask.

                                                                                                                So, in general, I think politely asked “why not X?” is a great way for at least one participant to learn something.

                                                                                                                Where this gets tricky is 1:N interaction, where you have a bunch of folks independently asking the same stupid question politely!

                                                                                                                1. 5

                                                                                                                  This helps to avoid the situation where you don’t know that there’s something you don’t know.

                                                                                                                  In general, I’ve had success approaching this by (EG) “Oh cool! I often make a barley-vegetable soup which I really like; let me know if you want to trade recipes sometime”.

                                                                                                                  I think the important differences are:

                                                                                                                  • Communicates that information / help is readily available should they wish to avail themselves of it (‘Why not X?’ is not an offer of help)
                                                                                                                  • Avoids implying the other party is ignorant of X (for all you know, their knowledge/expertise may be vastly superior to yours)
                                                                                                                  • Avoids demanding the other party do the work to explain themselves (offering to contribute comparable effort instead of dropping a question that’s easier to ask than to answer)
                                                                                                                  1. 5

                                                                                                                    “Oh that’s nice I actually do this other thing” often still comes off as pushy, and engineer types do it A LOT. A more socially well adjusted (hypothetical) person would probably say “oh cool I’ve only had the bad canned type of broccoli-cheese, how do you blend in the cheese?” (something that demonstrates an interest in what they’re doing). Then after they have shared a bit more maybe say “I’ve been into barley-vegetable, yours seems delicious but I’m scared of the calories” even then it can seem pushy and is better to err on the side of not sharing your stuff because people always overestimate the value to the other person of their shit. ESPECIALLY engineers lol.

                                                                                                                    In the case of someone doing a project in C in 2023, it’s safe to assume they are aware of the purported benefits of Rust. “Oh cool what made you decide to do it in C” would be a pleasant way to ask for information if they are actually curious.

                                                                                                                    1. 3

                                                                                                                      I wonder how much of what you call “socially well adjusted” is specific to American culture. In my central European country everyone seem to be much more direct and open to criticism 🤷

                                                                                                                      1. 1

                                                                                                                        “Oh cool what made you decide to do it in C” would be a pleasant way to ask for information if they are actually curious.

                                                                                                                        Yeah I wish I had more of this kind of discussion. I’m actually quite interested in Rust, I just kind of want to learn stuff from bottom-up. Seeing the benefits of Rust, Zig etc. will be easier when I have dabbled with C and C++ at first.

                                                                                                                      2. 3

                                                                                                                        I’ve heard people generally don’t like either of these kind of responses, because they’re taking the conversation (A is eating delicious soup) and making it about yourself. The “correct” answer is “Oh, cool.” maybe followed up by “What made you go with broccoli cheese?”. People love the opportunity to talk about the things they enjoy, and they love the opportunity to ask about the things others enjoy.

                                                                                                                  2. 4

                                                                                                                    Correct. It just keeps happening!

                                                                                                                  3. 1

                                                                                                                    Sometimes it’s rude, but when I say I am doing this as a learning project, I get the whole “But Rust is much safer you should learn that now since it’s hot” spiel. Maybe I read into it too much.

                                                                                                                    1. 1

                                                                                                                      Maybe I read into it too much.

                                                                                                                      Sorry, I didn’t mean to make you feel this way! I didn’t want to question how it makes you feel, I was just wondering if there is something specific that you are able to pin point (it’s fine if there is no such thing). People tell me I’m often perceived as too direct and you could call me rust fanboy so I was hoping to learn something here.

                                                                                                              1. 13

                                                                                                                This article would shoot to number #1 on HN if the author had instead talked about how the Go team are evil and stupid and hate kittens, instead of just linking to an issue in the Go repo and another repo from Uber that fixes it.

                                                                                                                1. 10

                                                                                                                  Yeah, this article is way too constructive. He’ll never get anywhere with that attitude.

                                                                                                                  1. 4

                                                                                                                    i flagged this as offtopic because comments complaining about some unrelated website seem offtopic.

                                                                                                                    1. 3

                                                                                                                      Rob Pike famously said that all Hacker News users are terrible programmers and not smart enough to do anything useful. Thats why they don’t deserve to know about CFS quotas.

                                                                                                                      1. 11

                                                                                                                        He also came into my house and turned off all my syntax highlighting :-(((

                                                                                                                    1. 7

                                                                                                                      I wasn’t even aware they had a proxy service (Google), as I am not a Go user. However, that is a neat way of them actually building a database of available packages, doing caching of course.

                                                                                                                      Count on the Go team to have something which follows the UNIX philosophy instead of some clunky service. That’s really neat!

                                                                                                                      1. 40

                                                                                                                        It’s neat to do full git clones of every git repository hundreds of times per hour across a ton of servers instead of a simple HTTP service? Really?

                                                                                                                        It’s the pinnacle of anti-efficiency, antisocial, “just throw more money at hardware” anti-elegant solution I’ve seen.

                                                                                                                        1. 5

                                                                                                                          Perhaps I misunderstood then from what I read further…

                                                                                                                          I meant I found the Google Proxy cool

                                                                                                                          1. 3

                                                                                                                            It sounds like a cool idea, but badly implemented.

                                                                                                                        2. 15

                                                                                                                          Perhaps we should find names for this pattern, so that we stop thinking of it as a good thing. I see the same pattern that you do: Eve convinces people to use their proxy, and gathers metadata about the network without active participation. We don’t see how Google is using this data, and it’s clear that they will not allow cleanly opting out of the proxy feature without disrupting the ecosystem.

                                                                                                                          1. 12

                                                                                                                            You can personally opt out of the proxy system by setting the GOPROXY=direct environment variable.

                                                                                                                            1. 20

                                                                                                                              The fact you need to do this, and I bet 99% of everyone doesn’t even realize it’s there or why it might be desirable, is a symptom of how bad this pattern is.

                                                                                                                              1. 2

                                                                                                                                Features in other languages and ecosystems? Awesome! The user has control! Features in the Go toolchain and ecosystem? Clearly a symptom of how bad the problem is.

                                                                                                                                1. 16

                                                                                                                                  Most other languages and ecosystems aren’t backed by companies that literally exist to harvest peoples’ information.

                                                                                                                                  1. 6

                                                                                                                                    “Features” is too vague to be useful in this conversation. If GCC has a feature to let you statically analyse your code, that can be good, even if it’s bad that Go has an enabled-by-default feature which proxies all traffic through Google servers. If Rust adds a feature to make your head explode if it detects a typo, that would also be a bad feature.

                                                                                                                                    1. 3

                                                                                                                                      Fair enough. It’s fine to have a more nuanced conversation about the merits of the feature/architecture.

                                                                                                                                      I think the proxy architecture is superior to centralized architectures with respect to being able to opt out of centralized collection. Consider that in Rust (and every other package manager I can think of off the top of my head) the default is to get all of your packages through their centralized system, and the way to opt out is to run a copy of the system yourself which is much more difficult than setting an environment variable (you almost certainly have to set one either way to tell it which server to connect to) and still doesn’t allow you to fully avoid it (you must download the package at least once).

                                                                                                                                      You may have rational or irrational fears of Google compared to other faceless corporations, but that’s not an indictment of the feature or architecture. Additionally, the privacy policy for the proxy even beats crates.io in some ways (for example, crates.io will retain logs for 1 year versus 30 days).

                                                                                                                                      1. 3

                                                                                                                                        Consider that in Rust (and every other package manager I can think of off the top of my head)

                                                                                                                                        Another exception would be deno: https://deno.land/manual@v1.29.2/basics/modules#remote-import

                                                                                                                                2. 0

                                                                                                                                  More evidence that the issue people are upset about here is psychological and has almost nothing to do with the facts at hand.

                                                                                                                                  1. 9

                                                                                                                                    It should be opt-in, not opt-out.

                                                                                                                                    1. 3

                                                                                                                                      From Google’s perspective it’s reasonable to use opt-out here, otherwise nobody would have configured those GOPRIVATE, GONOPROXY, GONOSUMDB, making the sumdb and package index pretty pointless. However, from a user perspective I feel that opt-in would have been the friendlier option.

                                                                                                                                3. 5

                                                                                                                                  Not everything is that black and white. While I don’t think Google would pass on using any metadata they can get their hands on, there are also benefits for the community. They list some here in How Go Mitigates Supply Chain Attacks

                                                                                                                                  Having witnessed several drama stories in the Node and Python package ecosystem, I think I prefer Google’s approach for now.

                                                                                                                                  1. 4

                                                                                                                                    Maybe packages were a mistake. Maybe there are better ways to share software.

                                                                                                                                    1. 3

                                                                                                                                      Sounds compelling. Do you have any suggestions?

                                                                                                                                      1. 5

                                                                                                                                        I don’t have a complete concrete proposal. I am currently hacking on a tacit expression-oriented language which is amenable to content-addressing and module-free code reuse; you could check out Unison if you want to try something which exists today and is similar to my vision.

                                                                                                                                        I’ve tried to seriously discuss this before, e.g. at this question, but it seems that it is beyond the Overton window.

                                                                                                                                  2. 2

                                                                                                                                    How is this situation any worse than a registry based system like npm or cargo?

                                                                                                                                1. 11

                                                                                                                                  This is a weird way to measure a language. Look at GitHub and how productive a single developer can be with Go. Some programs are editors, computer games or command line utilities. Not every program needs the type of defensive programming the article promotes.

                                                                                                                                  Inherent complexity does not go away if you close your eyes.

                                                                                                                                  This is true. But not all projects has this particular type of inherent complexity.

                                                                                                                                  Successful projects, quick compile times, an ecosystem that lets you add a dependency that works, not having broken code just because 3 years has passed; these are also nice things.

                                                                                                                                  One should not close the eyes to the quick development cycles and low cognititve overhead experienced Go developers can achieve, either.

                                                                                                                                  1. 13

                                                                                                                                    This is a weird way to measure a language. Look at GitHub and how productive a single developer can be with Go.

                                                                                                                                    You could apply this argument to literally any language.

                                                                                                                                    1. 8

                                                                                                                                      No, you couldn’t, and there is no comparison. Look at active repos in Common Lisp, Scheme, Forth, Smalltalk, Ada, you know, the languages everybody talks about nicely. Then look at Go. If there’s 2 types of X, the ones everybody complains about, and the ones nobody uses, Go is certainly in the first group.

                                                                                                                                      Go is very popular, and getting more popular, and there is no denying it: https://madnight.github.io/githut/#/pull_requests/2022/3. Tons of people are learning go in their free time and using it to get stuff done, because it is easy to learn and easy to get stuff done with.

                                                                                                                                      1. 12

                                                                                                                                        Now you’re arguing by popularity, which is a fallacious argument and a very different thing than “you can get stuff done with it”. Clearly you can gst stuff done with the other languages too.

                                                                                                                                        1. 4

                                                                                                                                          Github and the popularity of the language in the platform proves that many single developers can and are getting stuff done with it. Which is a proof that you don’t get with other, unpopular languages. You might claim that they are just as good, but you are not getting proof of it from github.

                                                                                                                                          1. 12

                                                                                                                                            Popularity is not a good measure of anything. Tobacco smoking is popular. Eating Tide-Pods used to be popular.

                                                                                                                                            1. 7

                                                                                                                                              Tobacco smoking and eating tide pods do not produce anything (well, except damage to the person doing it). I think corasara is implying that projects on github demonstrate that people get stuff done with Go. To put it differently, TikTok and Insta measure popularity. GitHub showcases code that actually does something (well, most of the time). And the fact that there are many repositories on GitHub implies that many people do get stuff done with Go. Now, there might be an issue that users of other languages do not advertise their work on GitHub…

                                                                                                                                              1. 4

                                                                                                                                                My point is that the people that get stuff done with Go could be just as well getting stuff done with other languages, but most of them haven’t really tried many other languages besides the ones that are obviously worse for productivity, such as C.

                                                                                                                                                1. 4

                                                                                                                                                  I think this is wrong. I think developers that have tried many different programming languages are the ones that most appreciate the things that Go gets right.

                                                                                                                                                  1. 4

                                                                                                                                                    but most of them haven’t really tried many other languages besides the ones that are obviously worse for productivity, such as C.

                                                                                                                                                    This belief reveals a great deal about you and I’m not sure reflects anything true about Go programmers.

                                                                                                                                                2. 5

                                                                                                                                                  Wow, look at the replies you’re getting. These people are coming out of the woodwork to defend their questionable career choices. One could base a whole career on Go criticism.

                                                                                                                                                  1. 5

                                                                                                                                                    This is ridiculous. You are comparing a decade of individual’s spending their rarest resource, their free time, to a claim that a 4chan meme was real and chemical addiction.

                                                                                                                                                    Get over it, some people use go because it’s the best choice for them.

                                                                                                                                                    This is not your schools debate club.

                                                                                                                                                    1. 2

                                                                                                                                                      How do the people know whether it’s the best choice for them?

                                                                                                                                        1. 30

                                                                                                                                          for me, the most exciting thing about golang is that i can easily walk junior engineers through a codebase with 0 prep. i love accessible code that doesn’t require a krang-like brain to intuit. rust is so non-intuitive to me that i’ve bounced off of it several times, despite wanting to learn it - and i’m a seasoned engineer!

                                                                                                                                          i didn’t go to school for CS, and i don’t have a traditional background - there are a lot of people like me in the industry. approachability of languages matters, and golang does a fine job.

                                                                                                                                          it obv has warts. but between the inflammatory title & the cherry picked “bad things”, the article winds up feeling really cynical, and makes me feel like fasterthanli.me is probably cynical too.

                                                                                                                                          continues to write fun, stable code quickly in golang

                                                                                                                                          1. 9

                                                                                                                                            What to you makes the code written in Go’s monotonous style fun?

                                                                                                                                            1. 27

                                                                                                                                              For me—and for most who choose Go—the fun lies in watching your ideas for software come to life. Go is so easy to think in; it enables building stuff without having to fight the language.

                                                                                                                                              1. 24

                                                                                                                                                I’d rather work with a stable language, so that I can be creative in the approach to the problem (not the language expression) than a language where I have to spend significant valuable background mental effort on the choice of words

                                                                                                                                                1. 6

                                                                                                                                                  And you don’t mind having to spend valuable background mental effort on typing if err != nil over and over?

                                                                                                                                                  1. 10

                                                                                                                                                    I do mind, but I think you can argue it produces low cognitive load

                                                                                                                                                    1. 5

                                                                                                                                                      The Rust folks had a similar issue with returning Option and Result and fixed it with the question mark operator.

                                                                                                                                                      The Error type can be named anything, but the community very quickly settled on naming it err, following the convention started by the standard library. The language designers should have just made that the default, and created a similar construct to the question mark.

                                                                                                                                                      1. 5

                                                                                                                                                        after the first few times, it comes naturally for me and i don’t really think about it much. In fact, in situations where it is unnecessary I often have to stop and think about it more.

                                                                                                                                                    2. 20

                                                                                                                                                      bc go code mostly looks the same everywhere thanks to gofmt and a strong stdlib, i spend a lot less time thinking about package choice & a lot more time doing implementation. yesterday i wrote a prometheus to matrix alert bot from scratch in 30 minutes - i spent most of that time figuring out what the prometheus API layout was. now that it’s deployed, i have faith that the code will be rock solid for basically eternity.

                                                                                                                                                      what’s not fun is writing similar code in ruby/python and having major language upgrades deprecate my code, or having unexpected errors show up during runtime. or, god forbid, doing dep management.

                                                                                                                                                      part of that is thanks to go’s stability, which is another good reason to choose it for the sort of work i do.

                                                                                                                                                      having a binary means not having to worry about the linux package ecosystem either - i just stick the binary where i want it to run & it’s off to the races forever.

                                                                                                                                                      to me, that’s the fun of it. focusing on domain problems & not implementation, and having a solid foundation - it feels like sitting with my back against a wall instead of a window. it saves me significant time & having dealt with a lot of other languages & their ecosystems, golang feels like relief.

                                                                                                                                                      1. 4

                                                                                                                                                        it’s a language created at a specific workplace for doing the type of work that those workers do. Do you think bricklayers worry about how to make laying bricks fun?

                                                                                                                                                        1. 4

                                                                                                                                                          continues to write fun, stable code quickly in golang

                                                                                                                                                          That’s why I was asking why they found writing Go fun, it wasn’t out of nowhere. I have received some satisfactory answers to that question, too.

                                                                                                                                                          1. 3

                                                                                                                                                            If it was possible for brick laying to be fun, I’m sure bricklayers would take it.

                                                                                                                                                            1. 8

                                                                                                                                                              Fun fact, Winston Churchill took up brick laying as a hobby. He certainly seemed to think it was fun!

                                                                                                                                                      1. 34

                                                                                                                                                        I think most people don’t realize how radical the “Bell Labs gang”’s conceptualization of simplicity is. It is rooted in a deep suspicion of any kind of abstraction and a defeatist attitude when it comes to building them:

                                                                                                                                                        • The abstractions you build will always be leaky, and your users will be forced to understand the underlying system sooner or later, so don’t bother with creating a complete self-sufficient system of abstractions.

                                                                                                                                                        • Any abstraction complicates the system, so build as few abstractions as possible, and make the abstractions themselves as simple as possible.

                                                                                                                                                          (It’s worth stressing that “making abstractions themselves simple” is about the concept provided by the abstraction, not the implementation. For example, the implementation of GC and goroutines are very complex, but the concepts they introduce are simple. In fact, GC doesn’t so much introduce new concepts than take away the concept of memory deallocation.)

                                                                                                                                                        This attitude has long been criticized for resulting in leaky, incomplete, “half-assed” (as called by the author in a previous article), because it does. The UNIX-HATERS handbook labelled it as “worse is better” (which ironically got reclaimed by the Bell Labs gang). These criticisms are based on the anticipation that high-level abstractions should form a coherent system that completely covers a low-level system, and not require the user to understand the low-level system. But the Bell Labs gang says “you won’t get it right, so don’t bother”.

                                                                                                                                                        Dennis Ritchie said that “UNIX is very simple, it just needs a genius to understand its simplicity”. I don’t think it would take a genius to understand the simplicity of Unix, but it does require you to have a mental model of the system Unix runs on and what Unix’s abstractions are actually abstracting over.

                                                                                                                                                        Instead of passing judgements on which one of the Bell Labs gang and its critics are right, I think that it’s important to think of the design of computer systems as the constantly revolving field it is, with movements and counter-movements, instead of a monotonic approach towards an ideal state. Indeed, Unix and C were created as reactions against Multics (and presumably PL/I). Go was a reaction against C++ and Java. Rust is still too young to have its “Bell Labs gang” style reaction, but it would be very interesting to see one in future.

                                                                                                                                                        1. 7

                                                                                                                                                          (It’s worth stressing that “making abstractions themselves simple” is about the concept provided by the abstraction, not the implementation. For example, the implementation of GC and goroutines are very complex, but the concepts they introduce are simple. In fact, GC doesn’t so much introduce new concepts than take away the concept of memory deallocation.)

                                                                                                                                                          The “worse-is-better” philosophy described in Richard Gabriel’s essay [0] actually prioritizes implementation simplicity over interface simplicity. Maybe GC and goroutines don’t reflect this, but you wouldn’t expect every principle to be operative in every decision.

                                                                                                                                                          [0] https://people.cs.umass.edu/~emery/classes/cmpsci691st/readings/Misc/Worse-is-Better.pdf

                                                                                                                                                          1. 3

                                                                                                                                                            Thanks, you are right that it was Richard Gabriel who coined the term.

                                                                                                                                                            But I quibble with the characterization that the Bell Labs gang prioritizes implementation simplicity over interface simplicity. Unix’s fork() was not simple to implement (at least not a performant way) but it presented a simple interface for controlling process creation. Neither was a single-root filesystem at that time, but again the interface is relatively simple. C’s printf() is also not simple to implement but the API was nice and simple (for the time).

                                                                                                                                                            1. 10

                                                                                                                                                              Unix’s fork() was not simple to implement

                                                                                                                                                              Yes it was. The systems that it was designed for had one resident process in core at a time. Context switch meant writing that process out and reading another one in. With fork, you just skipped the second step, keeping the existing one and just updating some kernel data structures to say that this is really a new instance. It only became difficult to implement on systems with MMUs and multiple resident processes, but that was a decade later, by which time it was ingrained.

                                                                                                                                                              1. 2

                                                                                                                                                                I stand corrected then, perhaps Go shifted a bit more in the direction of interface simplicity.

                                                                                                                                                              2. 2

                                                                                                                                                                His example in the essay is how interrupted system calls are handled. In the “better” OS, there is a bunch of tricky work to do state switching in the kernel so the userspace API sees a simple call-return API no matter what. In Unix, the OS just throws everything away, returns an EINTR error, and expects userspace to put a loop around every system call so it can retry.

                                                                                                                                                                BTW, in early Bell Labs Unix, I’m pretty sure the implementation of fork was quite simple and performant, because there was no virtual memory. The performance tricks arrived with BSD, if I recall correctly. So that actually is an example of choosing a worse interface (fork is really quite a bizarre API compared to “create a new process”) for implementation simplicity.

                                                                                                                                                                1. 9

                                                                                                                                                                  fork is really quite a bizarre API

                                                                                                                                                                  I’m still not entirely sure it isn’t some sort of epic joke.

                                                                                                                                                                  https://rachelbythebay.com/w/2014/08/19/fork/

                                                                                                                                                                  Guess what happens when you don’t test [fork] for failure? Yep, that’s right, you probably treat “-1” (fork’s error result) as a pid.

                                                                                                                                                                  That’s the beginning of the pain. The true pain comes later when it’s time to send a signal. Maybe you want to shut down a child process.

                                                                                                                                                                  Do you kill(pid, signal)? Maybe you do kill(pid, 9).

                                                                                                                                                                  Do you know what happens when pid is -1? You really should. It’s Important. Yes, with a capital I.

                                                                                                                                                                  Here, I’ll paste from the kill(2) man page on my Linux box.

                                                                                                                                                                  If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init), …

                                                                                                                                                                  See that? Killing “pid -1” is equivalent to massacring every other process you are permitted to signal. If you’re root, that’s probably everything. You live and init lives, but that’s it. Everything else is gone gone gone.

                                                                                                                                                                2. 2

                                                                                                                                                                  Abstraction and software in general is about creating a relatively simple interface with a relatively complex implementation. The philosophy of prioritizing implementation simplicity only makes sense within a spectrum of decision defined by other factors, so examples only make sense in comparison to some other system or group of engineers with similar goals and constraints.

                                                                                                                                                              3. 7

                                                                                                                                                                These criticisms are based on the anticipation that high-level abstractions should form a coherent system that completely covers a low-level system, and not require the user to understand the low-level system.

                                                                                                                                                                I haven’t seen that happen in the years that I’ve been around, at least. My experience with ambitious systems of that sort is:

                                                                                                                                                                • 97% are trash.
                                                                                                                                                                • 3% are actually quite pleasant, and good enough that you can mostly use them on their own terms.
                                                                                                                                                                • 0% are so good that you never need to source-dive, monkey-patch, or start reading CPU-level performance counters.
                                                                                                                                                                • “Having a mental model of the system it runs on and what its abstractions are actually abstracting over” will get you superior results 100% of the time.

                                                                                                                                                                In practice, I would generally rather have something that attempts less, that I can use as a solid part of the solution to my problem, than to use a library that attempts everything, which almost-but-not-quite solves my problem, and which has such an extensive vocabulary of its own special abstractions that interfacing it to something else to provide the missing part requires reverse-engineering the authors’ brains.

                                                                                                                                                                1. 4

                                                                                                                                                                  This is an understandable viewpoint, but Go’s design is not simple. I usually start with the numeric types – which hardware was it designed for, and what safety properties are its abstractions designed to protect?

                                                                                                                                                                  1. 6

                                                                                                                                                                    I don’t understand what your point is, but I suspect you are using a more specialized definition of simple than the workman definition. In other words, talking past the Op.

                                                                                                                                                                    1. 2

                                                                                                                                                                      I typically assume that “simple” and “complex” are relative to the speaker’s experience. Let me sharpen the point: on which hardware does Go’s assortment of numeric types make sense? Are they abstracting over the hardware? I might pick on e.g. complex128, which I don’t think is a native type of any hardware, or uintptr, which enables unsafe actions that undermine the GC’s safety guarantees.

                                                                                                                                                                      1. 6

                                                                                                                                                                        Neither of those types are commonly used in production Go code.

                                                                                                                                                                        1. 5

                                                                                                                                                                          uintptr does no such thing. You need to import the unsafe package to do anything unsafe.

                                                                                                                                                                          1. 2

                                                                                                                                                                            Most modern CPUs have registers that can fit a complex128, can add or subtract them in a single instruction, and multiply them in a handful (maybe 4). Division is more complicated, but then again I’ve worked with CPUs that lacked instructions for dividing integers, but I don’t think many people claimed that int8 wasn’t a native type :)

                                                                                                                                                                    1. 5

                                                                                                                                                                      The Go stdlib is extensive to the point that it’s clearly framework-adjacent. But it’s also minimal to the point that you’re almost certainly going to need dependencies to do certain things.

                                                                                                                                                                      Do you really need to write your own bespoke routing engine? No you don’t. Use a framework for that.

                                                                                                                                                                      1. 3

                                                                                                                                                                        mux and chi are both very capable routers, they’re not really frameworks. I prefer to use the approach of just using a simple router and the standard net/http handler interface over having a framework that tries to figure out every possible problem.

                                                                                                                                                                        1. 3

                                                                                                                                                                          I may be showing my inexperience, but i haven’t yet built a project of the scale where I needed more sophisticated routing than the STL router

                                                                                                                                                                          1. 2

                                                                                                                                                                            You don’t need to use another router, but it’s a pain to have to manually do things like reject POST requests to GET endpoints and whatnot. Plus you need to special case / to be both the homepage and the 404 page. Nothing insurmountable, but you can also just write your own 200 line library and not have to deal with it anymore.