Threads for danielrheath

  1. 21

    If I had to give two real high-dollar items for making git branching less painful:

    • Rebase, not merge, your feature branch. Do not squash.
    • Rebase your feature branch against master/main/whatever at least every day .

    I’d also suggest knowing when to cut losses–if you have a zombie branch a few months old, take the parts that are super neat and throw away the rest.

    1. 7

      This is pretty much it. GitHub exacerbates this problem because its pull request workflow based on branches is broken. What you really want is a pull request on a cherry picked range of commits onto another branch. That way you can have commits from your branch flowing into main while you continue to develop along your branch.

      1.  

        Some time ago I setup an alias for git cherry-pull <mainline>, which (rebase style) lets you assign each commit to a new branch, pushes them, then opens the ‘new pull request’ page for each branch.

        I should dust off the code and publish it.

        [edit] A colleague pointed out that a script needs to be ~perfect because it obscures the details of the git operations, while doing it longhand keeps them front of mind. Might explain why I rarely use it anymore.

        1.  

          Sounds nifty! Is the interface like rebase interactive? And I’d recommend a new name, because google autocorrupts it to cherry-pick.

          1.  

            I’ve written similar scripts. The two things that I kept hitting are:

            1. Getting this to play nicely with rebase -i and merging/splitting commits is…not trivial.
            2. Automation in PRs is often triggered by the main/master branch, so all but your bottom PR doesn’t get checked.
          2.  

            Indeed, any of these advices would have solved the problem. Instead, I ended up spending almost a month just trying to solve the mess.

            1.  

              My condolences, friend. Happens to all of us eventually.

          3.  

            It seems to be fairly unmaintained, but I really like git-imerge for long-lived branches. It does pairwise merges of each of your commits against each of the upstream ones giving you an NxM matrix of all possible merges. It builds this as a frontier from the top-left (shared parent) branch to the bottom-right (final merge). You get to resolve conflicts exactly on the pair of your commit vs theirs that introduced it. You then have the full history for bisecting if the end result doesn’t work. You can then choose one of three ways for it to clean up the resulting history:

            • The equivalent of a git merge.
            • The equivalent of a git rebase.
            • A rebase-with-history, where it gives you a rebase but also sets the parent of each of your commits such that downstream users can still merge from your branch.
            1.  

              I’d recommend squashing before the rebase simply so there’s only one commit you have to resolve conflicts on.

              But yes, rebase often. This is the way.

            1. 1

              The problem with is it’s such a compelling idea at first, but there’s a lot of things people like their UIs to do that is very difficult to express this way, and shoe-horning those things into this currently-popular paradigm becomes real ugly real quick. You can see it breaking down in React wherever you encounter Context and portals, for example.

              Clojure or similar is probably going to be less painful for this than most JS implementations though, because of better support for metaprogramming in ways that would (in JS) require inscrutable magic.

              1. 3

                What’s an example of something difficult to express? I’m not familiar with React; I have used Elm and written a few games in FRP style.

                1. 1

                  React offers very little in the way of state management for anything complex, because it’s more of a library than a framework & state management is ‘out of scope’.

                  Anything involving complex (deeply nested) state being updated.

              1. 22

                For the uninitiated: Style insensitivity is a unique feature of the Nim programming language that allows a code base to follow a consistent naming style, even if its dependencies use a different style. It works by comparing identifiers in a case-insensitive way, except for the first character, and ignoring underscores.

                Another advantage of style insensitivity is that identifiers such as itemId, itemID or item_ID can never refer to different things, which prevents certain kinds of bad code. An exception is made for the first letter to allow the common convention of having a value foo of type Foo.

                There’s a common misconception that this feature causes Nim programmers to mix different styles in a single codebase (which, as mentioned, is precisely the opposite of what it does), and it gets brought up every time Nim is mentioned on Lobsters/HackerNews/etc, diverting the discussion from more valuable topics.

                1. 3

                  There’s a common misconception that this feature causes Nim programmers to mix different styles in a single codebase (which, as mentioned, is precisely the opposite of what it does)

                  But… isn’t it exactly what the feature does? If my coding habits would make me write itemId and a coworker’s code habits would make them write item_id, style insensitivity makes it likely that I would accidentally use a different style than my coworker for the same variable in the same codebase, right? While most languages would make this impossible by making item_id be a different name than itemId, right?

                  How is this a misconception?

                  To be clear, I’m not saying it’s a huge deal or that it warrants all the attention it’s getting (that’s a different discussion), but since you brought it up…

                  1. 3

                    Thanks for providing some context. Is this a thing that gets applied by default any time you use any library, or a feature you can specifically invoke at the point during which the library is imported?

                    The former seems … real bad. The latter seems … kinda neat? but a bit silly.

                    1. 6

                      Currently it’s always on, and there’s an opt-in compile flag --styleCheck:error that makes it impossible to use an identifier inconsistently within the same file. The linked issue discusses if and how this behavior should be changed in Nim 2.

                      Personally, I wouldn’t mind if it was removed, as long as:

                      • --styleCheck:error was on by default
                      • there was a mechanism to restyle identifiers when importing a library.
                      1. 2

                        I agree. People outside the Nim community can add real value to this discussion, since it is just speculation what they really think based on a few loud complainers.

                        1. 4

                          I’m someone who looked at Nim, really liked it, then saw the “style insensitivity” and thought “this isn’t for me”. (Not co-incidentally, I’ve been involved in a major, CEOs-gettting-involved, fiasco that was ultimately due to SQL case-insensitivity.)

                          Nim occupies a nice space - compiled but relatively “high level” - with only really Go as a competitor (zig/rust/c++ all seem a little too low level.) I personally recoil at the idea of “style insensitivity”, but hopefully in a friendly, lobste.rs manner.

                          1. 4

                            I’ve been involved in a major, CEOs-gettting-involved, fiasco that was ultimately due to SQL case-insensitivity.

                            You can’t just say this and leave us hanging 😆 tell us the story! How did that cause a fiasco?

                            1. 4

                              Our software wouldn’t start for one customer (a large bank). The problem was unreproducible and had been going on for weeks. The customer was understandably very unhappy.

                              The ultimate cause was a “does the database version match the code” check. The database had a typical version table that looked like:

                              CREATE TABLE DB_STATE (VERSION INT, ...);
                              

                              Which was checked at startup using something like select version from db_state. This was failing for the customer because in Turkish, the upper case of “version” is “VERSİON” (look closely). Case-insensitivity is language-specific and the customer had installed the Turkish version of SQL Server.

                              Some java to demonstrate:

                              public class Turkish {
                                public static void main(String[] args) {
                                  System.out.println("version".toUpperCase(java.util.Locale.forLanguageTag("tr")));
                                }
                              }
                              

                              If you look at the java documentation for toUpper, they specifically mention Turkish - others have been bit by this same issue, I’m sure.

                              Which makes me wonder - how does Nim behave if compiled on a machine in Turkey, or Germany.

                              1. 5

                                This is making me wonder if anyone has ever used this as a stack-smashing attack. Find some C code that uppercases the input in place and send a bunch of “ß”s. Did the programmer ensure the buffer is big enough?

                                1. 3

                                  I’m pretty sure Nim’s style insensitivity is not locale-specific. That would be very dumb.

                              2. 2

                                Seems plenty friendly to me. Programmers can get awfully passionate about style guides/identifier conventions.

                                I think it tracks individual, personal history a lot - what confusions someone had, what editor/tool support they had for what sort of “what meta-kind of token is this?” questions and so on. In extreme cases it can lead to, e.g. Hungarian notation like moves. It can even be influenced by font choices.

                                Vaguely related to case insensitivity, early on, Nim only used '\l' to denote a newline character..Not sure why it was not '\n' from the start, but because lower case “l” (elle) and the numeral “1” often look so similar, '\L' was the dominant suggestion and all special character literals were case insensitive. (Well, one could argue it was just tracking general insensitivity that made them insensitive…).

                                1. 2

                                  Personally I’d say this compares unfavorably to go, where style arguments are solved by the language shipping a single blessed formatting style.

                                  Confusions/disagreements over formatting style are - imo - a waste of the teams engineering time, so I see the go approach as inherently better.

                                  1. 2

                                    Go doesn’t enforce a style for identifiers. Try it online!

                                    1. 2

                                      Thanks, I hate it.

                                      Fair point to nim though!

                                2. 2

                                  There’s also crystal, but ii is failing to reach critical mass in my opinion.

                                  I think crystal did a great job providing things people usually want upfront. I want a quick and direct way to make an HTTP request. I want to extract na value from a JSON string with no fuss. I want to expose functionality via CLI or a web interface with minimal effort. Crystal got these right.

                                  I agree that above-mentioned languages are too low level.

                                  1. 1

                                    Not sure about the others, but I think exposing functionality via CLI is pretty easy in Nim. cligen is not in the Nim stdlib, though.

                                    1. 1

                                      I was not comparing to Nim directly. Just giving examples of the kind of thing I believe are the strongest drives to success of a language.

                                      But for an example of one thing that I found lacking in Nim was concurrency primitives. Crystal makes it relatively simple and direct with fairly simple and familiar fibre API.

                                      A quick way to spin up an HTTP service was another one. It even had support for websockets.

                            2. 4

                              It is always on - even for keywords like f_Or in a loop. I was trying to perhaps help guide the group towards a usage like you articulate.

                              EDIT: The main use case cited is always “use a library with an alien convention according to your own convention”. So, being more precise and explicit about this as an import-time construct would seem to be less feather ruffling (IMO).

                            3. 3

                              Just for the record - the Z shell (Zsh) had style insensitivity for its setopt builtin waaay back in the very early 90s. They did not make the first letter sensitive, though. :-)

                              As this seems to be a very divisive issue and part of what is divisive is knowing how those outside the community (who do not love/have not made peace with the feature) feel, it might be helpful if Lobster people could weigh in.

                              1. 2

                                As this seems to be a very divisive issue and part of what is divisive is knowing how those outside the community (who do not love/have not made peace with the feature) feel, it might be helpful if Lobster people could weigh in.

                                I looked into Nim and was at least partially dissuaded by style insensitivity. I don’t think it’s fatal persay, but it did hit me very early in my evaluation. I would liken it to the dot calls in Elixir: Something that feels wrong and makes you question other decisions in the language. That said, Elixir is a fabulous language and I powered through. I imagine others feel similarly.

                                1. 2

                                  What specifically do you not like about style insensitivity?

                                  1. 1

                                    Here’s the thing: I haven’t used style insensitivity so I can’t really say I dislike it. However, it struck me as unnecessarily inconsistent. I don’t care about snake case or camel case. I just want code to be consistent. Of course, code I write can be consistent with style insensitivity, but code I read probably won’t be.

                                    Additionally, I imagined that working in a team could have issues: repos use the original author’s preferred styling. Of course, having a clear style guide helps, but in small teams sometimes people are intractable and resistant to change. In a way, it triggers a feeling of exasperation: a memory of all the stupid little arguments you have with other developers.

                                    So here I am kicking the tires on a new exciting language and I am already thinking about arguing with people. Kind of takes the wind out of your sails. It may be a great feature, but I imagine it’s a barrier to adoption for some neurotic types like myself. (Maybe that’s a blessing?)

                                    1. 1

                                      You have it the other way around. With style insensitivity, code is much more likely to follow a consistent style — because it can’t be forced into inconsistency by using libraries from different authors.

                                      1. 1

                                        I can see how code I write is consistent, but code I read is going to be more inconsistent. If it wasn’t then why would we need style insensitivity in the first place?

                                        1. 1

                                          I can see how code I write is consistent, but code I read is going to be more inconsistent.

                                          Can you show me a serious Nim project that uses an inconsistent style?

                                          If it wasn’t then why would we need style insensitivity in the first place?

                                          Because libraries you’re using may be written in different styles.

                                          1. 1

                                            I’m saying it’s inconsistent across projects. Not within projects. Sometimes you have to read other people’s code. Style insensitivity allows/encourages people to pick the nondefault style.

                                            Ultimately, I’m not in the nim ecosystem. I posted my comment about why style insensitivity made me less interested in nim. I can tell you that this is the exact sort of argument I was looking to avoid so you have proven my initial concerns correct.

                                            1. 1

                                              I don’t see what the problem is with reading code written in a different style, as long as it’s consistent. And in practice, most Nim projects follow NEP1.

                              2. 2

                                Doesn’t JRuby have something similar around Java native methods?

                                1. 2

                                  I think it’s an interesting comparison, but it’s important to keep in mind that a language based around message passing is fundamentally different from what’s going on here where the compiler itself is collapsing a bunch of different identifiers during compile-time. When you call a method in Ruby, you’re not really supposed to care how it’s resolved, but when you make a call in a language like Nim, you expect it to be resolved at compile-time.

                                  1. 3

                                    I’d disagree there. The mechanism in JRuby is that the method is made available under multiple names to the application after it’s loaded. That’s not extremely different from what Nim does, except if we go down to the level to say we can’t compare languages with different runtime and module loading models.

                                    https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby

                                    1. 2

                                      I guess what I meant was that even if the implementation works the same way, Rubyists fundamentally have different expectations around what happens when you call foo.bar(); they’ve already given up on greppability for other reasons.

                              1. 5

                                That’s nice and all, but ultimately gives me an even bigger impression that if I want to stay away from a service playing Man-In-The-Middle (cloudflare), I’m more or less a roadkill for those guys.

                                1. 18

                                  Honestly, that’s how it’s always been. You have bigger pipes than the DDOSer or you pound sand and fall over. There’s no good way around it.

                                  Welcome to the modern internet, hoping you won’t get DDOSed is not a scalable strategy to prevent DDOS attacks. I personally only really use cloudflare defensively, because my site had been knocked over entirely with DDOS attacks and I don’t want to deal with that headache again.

                                  1. 4

                                    hoping you won’t get DDOSed is not a scalable strategy

                                    It worked so far, mostly, at least for years ;) But I also didn’t launch anything public really, and I’m at the point of changing that, which gives me nightmares. (And I really, really dread having one service taking the (TLS) keys to my kingdom..)

                                    P.S. Yes, you’re right..

                                    1. 2

                                      I personally only really use cloudflare defensively

                                      Could you elaborate on how you use them?

                                      We looked into them at my company, and I even had a call with their sales guys, but it was impossible to get useful information out of them. They basically wanted 6k / mo, or else just use the free tier…. and everything was business jargon.

                                      1. 9

                                        Sure. I am a person that likes to write about tech on their blog. I am also not a white man that is attracted to women, which unfortunately makes me a target for harassment, hate and apparently (as in this is something I have directly observed through my personal experience in this hellplane) getting biblical amounts of traffic sent at me with little warning. I use Cloudflare defensively because they are not likely going to take Cloudflare down with the amount of traffic that the kids that apparently decide that me being honest about observable facts about how I experience reality means that my site turns into a competition of how much traffic can booters and DDoS for hire services can throw at it.

                                        By using Cloudflare, which sits between the public internet and my blog server, the attackers will target cloudflare, not my blog server. This makes their attempted attacks do nothing. Combined with the ridiculous levels of engineering I have done to make my blog as fast as possible, I am fairly confident that my site can weather most DDoS attacks that will get thrown my way. The other part of this puzzle is to avoid writing things that are too inflammatory so that I am not an enticing target, but that is different and is more of a deterrence strategy than an outright technical thing.

                                        Cloudflare is part of my strategy to protect my website against random DDoS attacks. I really wish I didn’t have to use them, but overall I think that the net good outweighs the complications that I take doing this kind of stuff. Definitely worth the $20 a month I pay for the service, if only for the peace of mind.

                                        1. 1

                                          Thanks for the reply. That is a shitty situation. If I want to setup similar protection, are there specific technical options you use? Addons? Configuration? Etc…

                                          Or does just the standard service automatically give you the DDoS protection?

                                          1. 3

                                            I can check, but other than telling it “holy crap cache everything as much as you can” I’m pretty sure it’s fairly vanilla.

                                    2. 5

                                      Keep in mind that cloudflare is not the only game in town. Sure, it’s all effectively MitM, but there are other valid options from not-as-evil companies. Or as reezer mentioned, you can rely on your provider to some extent.

                                      1. 6

                                        Do you have any good sources talking about Cloudflare’s evilness? The amount of power they have is obviously absurd but I haven’t found much info about them actually abusing it.

                                        1. 7

                                          IIRC the loudest voices RE cloudflare object to their free speech absolutism & handling of abuse complaints - e.g. when they received complaints about far-right sites selling pro-insurrection merchandise, nazi memorabilia, etc they A) kept serving them at a profit, and B) took personal details including address from the complainant and passed it on to the site owners.

                                          While free speech absolutism has those for and against it, I’m sure you can imagine why someone might object to having their home address passed to a white nationalist group as “an activist against white nationalism with an asian name lives at this address”.

                                          1. 3

                                            For me this is where they reached the comic book villain level of evil https://mobile.twitter.com/stealthygeek/status/1485731083534667779 Since then I’m actively encouraging people to read it and use some other service instead.

                                        2. 3

                                          A lot can already be done with a haproxy<=>varnish sandwich¹ on a €30 dedicated machine.² But this not cool anymore, the new coolness is man-in-the-middle with vendor-lock-in-freemium and unreliability.

                                          What can I say, I’m an old man, now… :)

                                          ¹. https://www.haproxy.com/blog/haproxy-varnish-and-the-single-hostname-website/
                                          ². I dont want to advertise for a German provider which starts by “Hetz” and finishes by “ner” or a the semi-cheap branch of a french provider which name asks “so, you start?” There are many others, like one formerly known as “dedibox”, etc…

                                          1. 12

                                            You seem to dismiss the new MitM vendors, but anything you deploy to your dedicated machine has two basic issues:

                                            1. You can get DoS-ed by anyone with a similar pipe to yours. It makes no difference what you deploy on your machine - if your network interface is flooded with empty packets, that’s all you’ll see. So anyone with a €30 dedicated machine can kill your service.

                                            2. (mentioned in the post) - If you’re a popular DoS target, your service provider may not like to be constantly flooded by your traffic and will drop you. This has happened to many people already and there’s nothing you can do about it, unless you explicitly pay them for being your DoS shield.

                                            1. 4

                                              You’re right. At the end if they want to DDoS, they will succeed unless you use these special companies (~= Cloudflare, Akamai, Fastly, …)

                                              But in the case of the author, network was not the limiting factor, he got properly DoSed (not DDoS) because his web app had slow calls (= high CPU usage), and didn’t limit incoming connections. HAProxy (= limiting connection) and Varnish (= caching page) will go a long way before the network becomes a limit. And when the network starts becoming a limit these €30 dedicated machine providers (at least Hetzner, OVH/SoYouStart, Scaleway, …) have DDoS protections.

                                              In the case of the author, HAProxy and Varnish would have done a lot already.

                                          2. 1

                                            Most bigger providers, be it Hetzner, OVH or others give you quite good DDOS protection for free.

                                            Also with the numbers shown in the article one really shouldn’t underestimate what resources are available for relatively cheap these days.

                                            And using Cloudflare can also mean that these “How X nearly caused the internet to go down” and similar turning downtime into marketing articles on the Cloudflare blog probably affect you, whereas you are fine otherwise. Don’t get me wrong, they are sometimes pretty informative, yet it’s something that one should consider.

                                            So it’s all a bit context dependent. Depending on what service you are hosting attacks might also look differently and individual solutions might or might not work. DOS can often be achieved in more effective ways than just hitting the landing page, that usually is quite static in first place many times. And if you have something that rapidly fills up databases or causes compute resources to be used recovering might be a lot harder. Of course dumb attack are the most frequent ones, but usually also the ones having the smallest effect.

                                            In short what I wanna say is that if you blindly use cloudflare (or any others) that form or that websocket thingy might still knock your service out, with a lot less resources on the attackers side.

                                            1. 4

                                              Hetzner’s DDoS protection is not very effective. Sure, it’s best than other providers such as Contabo (another German provider) where their “DDoS protection” is a free nullroute, but nothing’s compared to OVH’s protection. And then, they (at least happened before, not sure nowadays) didn’t protect any traffic coming from inside their network - so have fun dealing with OVH boxes DDoSing other OVH boxes.

                                              1. 1

                                                I’d argue that dropping traffic early from your provider is a lot easier to deal than traffic from random places on the internet. Don’t they even have a firewall thingy, so you could block that even before touching any local packet filter.

                                              2. 3

                                                They don’t give you DDOS protection, they just don’t boot you for having higher traffic (as they did ~10 years ago, trust me). And they are so friendly to nullroute that traffic. It does not help with the load on your side.

                                                1. 1

                                                  Again, depending on the kind of attack and the service the same is true for CloudFlare, etc. Sure, if your problem is someone GETing / then pretty much using a CDN will fix your problem. I just don’t think the sentiment that it’s CloudFlare or not is the right one. It’s not a 0 and 1 thing. Especially not for the particular case discussed here.

                                            1. 3

                                              Great post, very cool project.

                                              It’s crazy how ideas are just floating around.

                                              For the past few months I’ve been thinking about what I call “singe-server web apps” and “single-binary web apps”.

                                              What i’m interested in is simplifying the deployment of web apps on services like Linode or Digital Ocean by just uploading and running a single binary that contains everything needed including the DB and scheduled tasks. I was thinking about using Go with embedded HTML, CSS and images and SQLite as the DB. One could also use something like Litestream to make sure the DB is safe in the event of a major server failure, but that would require a “second server/binary”.

                                              I don’t really know what this is but the concept feels very appealing to me. Kinda reminds me of the PHP days where you just upload a script and just opened the browser. I know PHP still exists but it requires a web server and configuration to run. The idea of a single binary feels even more portable than PHP.

                                              Also https://redbean.dev/ is a very inspiring and interesting project.

                                              1. 2

                                                These exist. They are called unikernels and lots of people are using them.

                                                1. 1

                                                  What is the advantage over CGI?

                                                  1. 2

                                                    CGI would assume that you are in a multi-process environment. Most unikernels are single-process (many are multi-threaded though). CGI would also assume all the usual unix trappings such as users, interpreters, shells, etc.

                                                    The most obvious benefit is ease of use. There are no shells or interactivity with unikernels so when you deploy it - it’s either running or it’s not. While you can configure the server there isn’t ssh running where you pop in and do extra configure post-deploy.

                                                    Then there is security. CGI quite literally is the canonical “shelling out” mechanism. CGI and the languages that heavily used it in the 90s and mid aughts were fraught with numerous security issues because of this practice. You have to deal with all the input/output sanitization and lots of edge cases.

                                                    Then there is performance. CGI is woefully under performant since you have to spawn a new process for it and under more modern systems that use “big data” dealing with heaps in tens of gigabytes that becomes ridiculously bad.

                                                    Anyways, very few people actually use ‘cgi’ as it were today. For languages that need to rely on a front-end proxy like nginx (because they are single process, single thread - like ruby, python, node, etc.) they siphon incoming requests off the front-end (nginx) and push it to your app back-end (your actual application).

                                                    Unikernels work really well for languages that deal with threads like Go, Rust, Java, etc. They work well for scripting languages too but what I just described above the back-end becomes individual vms instead of worker processes. They basically force the end-user to fit their workloads to the appropriate instance type.

                                                    1. 1

                                                      The most obvious benefit is ease of use. There are no shells or interactivity with unikernels so when you deploy it - it’s either running or it’s not. While you can configure the server there isn’t ssh running where you pop in and do extra configure post-deploy.

                                                      Isn’t that anti ease-of-use? I like to be able to go in and dig around when something goes wrong.

                                                      1. 2

                                                        IMO this makes debugging significantly easier than deploying to a linux system. If I throw on my devops hat and start thinking about all the times pagerduty woke me up at 2am in the morning half the time is spent figuring what process is causing an issue. Something is opening up too many sockets too fast? Open up lsof to figure what process it is. I can’t ssh in because logfiles are overflowing the disk? Now I have to hunt down the cronjob that I didn’t know existed that didn’t have proper log rotation on. In unikernel land there really is only one process so you know which program is causing the issue. Instrument it, ship your logs out and you are going to solve the vast majority of issues quickly.

                                                        Also there are other cases where debugging is significantly easier. Since it’s a single process system you can literally clone the vm in production (say a live database), download the image and attach gdb to it and now you not only are going to find the root of the problem but you are going to do so in a way that is non-destructive and doesn’t touch prod.

                                                        As an aside the ease-of-use I was referring too was not pertaining to debugging (although that is insanely easy) but to deployment/administration as compared to the dumpster fire of k8s/“cloud native”. Unikernels shift all the administration responsibilities to the cloud of choice. So while you can configure networking/storage to your hearts content you don’t have to actually manage it. Most people don’t understand this point about unikernels - they think a k8s like tool is necessary to use them which is totally not true - this won’t make sense to most people until they actually go deploy them for the first time and then this clicks.

                                                        1. 1

                                                          I’d argue that’s a combination of A) familiarity, and B) linux OS having built out robust introspective/investigative tooling over decades.

                                                          A unikernel has the advantage that many of those investigative tools are for problems that no longer exist, and the disadvantage that it no longer has those tools baked-in for the problems that it does still have.

                                                          EG you don’t have du, but you also don’t have a local filesystem that can bring down the server when you accidentally fill it with logs/tempfiles.

                                                          1. 2

                                                            Most unikernels actually do work with filesystems as most applications that do anything want to talk to one. Databases, webservers, etc. Logging is dealt with mostly 2 ways: 1) You either don’t care and you just rely on what goes out the serial - which is stupid slow so not really a prod method or 2) You do care and you ship it out via syslog to something like elastic, papertrail, splunk, etc.

                                                            1. 1

                                                              EG you don’t have du, but you also don’t have a local filesystem that can bring down the server when you accidentally fill it with logs/tempfiles.

                                                              So how do you find out that your app e.g. crashes because some database key was NULL?

                                                              1. 2

                                                                You have logging and/or crash reporting and you do something useful with them. It’s your problem to do though, but that’s not really any different than deploying to a traditional stack.

                                                                1. 1

                                                                  OK, but where do the logs go? If they go to another server, which then stores them on a filesystem you’ve just kicked the can elsewhere.

                                                                  1. 1

                                                                    Last I checked kicking the can down the road is most of IT :)

                                                                    1. 1

                                                                      Sure, but you can’t argue that e.g. you don’t have a filesystem to manage.

                                                    2. 2

                                                      If you wanted to use rust (or see about statically linking in a sqlite VFS via cgo) you could see about using https://GitHub.com/backtrace-labs/verneuil for sqlite replication. Completely in-process and exposes both a rust and C interface. It works quite well for all my home use cases, like for example replicating my blogs sqlite db to a s3 blob store for easier rollbacks.

                                                    1. 7

                                                      Then theoretical limit a server can support on a single port is 2⁴⁸ which is about 1 quadrillion because:

                                                      Over IPv4. This goes to 2¹⁴⁴ over IPv6, which is exceeding by far the estimated 2⁸⁰ atoms in the entire observable universe.

                                                      1. 10

                                                        According to https://educationblog.oup.com/secondary/maths/numbers-of-atoms-in-the-universe, it’s not 2^80 but on the order of 10^80, which (log2(2.4 * 10 ^ 78), to be more exact, as taken from the article) works out to approx. 2^260, so IPv6 is still not ready to cover it all. But I agree with the general idea IPv6 address space should be sufficient for humankind in the observable future.

                                                        1. 4

                                                          I hope we get there one day. For now I’m stuck unsupported: https://test-ipv6.com/ 0/10 :(

                                                          1. 5

                                                            Surprised to see I’m 0/10, too. As far as I know this has never impacted me. Given that the IPv4 scarcity worries turned out like the Peak Oil scare did, can someone remind me why I should still care about IPv6? (I’m only half joking)

                                                            1. 8

                                                              IPv4 scarcity is not the only reason to care about v6 (having millions of IPs per server can be very useful, for just one example) but it’s also not a fake problem. v4 scarcity is getting worse all the time. T-Mobile LTE users don’t even get a NAT’d v4 anymore, just a sort of edge translation to be able to mostly reach v4 only hosts (this breaks a lot of WebRTC stacks if the server is v4 only for example).

                                                              1. 2

                                                                T-Mobile LTE users don’t even get a NAT’d v4 anymore

                                                                Forgive me for being ignorant here, but I thought NAT was pretty much the bandaid for mitigating the symptoms of IPv4 address exhaustion (at least on the client side). Is there some fundamental limit to how many users can be behind a NAT, and is T-Mobile doing a type of translation different from standard NAT in order to get around it?

                                                                1. 5

                                                                  Yes, T-Mobile isn’t using a standard NAT or CGNAT at all. They use 464XLAT if you want to look up the tech.

                                                                  1. 1

                                                                    There are limits to NAT but it’s mostly either port exhaustion or too much translation happening on a single router. Layered NAT can solve that but that degrades performance. There are probably limits at which point IPv6 would be cheaper to run than layers and layers of NAT, but I don’t know if that time is coming any time soon.

                                                                    1. 0

                                                                      CGnat means you share an ipv4 address; makes hole punching even worse, but most things can be made to work.

                                                                2. 3

                                                                  10/10 here

                                                                  1. 1

                                                                    Thanks for the link — that’s new to me. I get 10/10 at home; I’m not fond of Comcast/Xfinity the company but I’m happy to see they’re giving me up-to-date service.

                                                                    So does this mean that I could run a publicly-accessible server from home without NAT shenanigans and with a stable IPv6 address?

                                                                    1. 2

                                                                      Yeah. Once enabled, your router (depending on the router) will usually delegate addresses in the assigned /64 to devices on your network. You can live a NAT-free life! Just be careful to firewall.

                                                                1. 9

                                                                  It might look like prolonged human misery throughout the world.

                                                                  https://ourworldindata.org/uploads/2019/11/Extreme-Poverty-projection-by-the-World-Bank-to-2030-786x550.png

                                                                  Bluntly: capitalism, growth, wealth, technology - these are the drivers of human progress and flourishing.

                                                                  1. 1

                                                                    I agree except that the poverty reduction shown in East Asia is from socialist China.

                                                                    1. 6

                                                                      China’s “socialism” revolves around state-owned enterprises in a market economy. They’re pretty capitalist, even Chinese schools teach the Chinese system of government as a Hegelian derivation of socialism and capitalism.

                                                                      1. 3

                                                                        What distinguishes capitalism as a system is that profit is the decisive and ultimate factor around which economic activity is organized. China’s system makes use of markets and private enterprise, but it is ultimately planned and organized around social ends (see: the aforementioned poverty alleviation).

                                                                        In China they describe their current system as the lower stage of socialism, but yes they’ve developed it in part based on insights into the contradictions of earlier socialist projects.

                                                                        1. 2

                                                                          Another, less charitable, way of looking at it: the Chinese Government is unwilling to relinquish power, but discovered through the starvation and murder of 45 million of their own people that mixed economies are less bad than planned economies.

                                                                          1. 2

                                                                            Yeah, I used to believe all that too. But eventually I got curious about what people on the other side of the argument could possibly have to say, and much to my surprise I found they had stronger arguments and a more serious commitment to truth. Then I realized that the people pushing those lines I believed were aligned with the people pushing all sorts of anti-human ideologies like degrowth.

                                                                            1. 2

                                                                              “Government willing to relinquish power” is a sufficiently low-half-life, unstable-state-of-being that the average number in existence at any given time is zero. What information does referencing it add?

                                                                              1. 1

                                                                                I disagree. Any government participating in open, free, elections is clearly willing to relinquish power.

                                                                                1. 1

                                                                                  In Australia, 78 senate seats and 151 house seats change occupants at an election; the remaining 140,000 government employees largely remain the same.

                                                                                  Is replacing 0.1% of the people really ‘replacing the government’?

                                                                                  1. 1

                                                                                    Ah, fair - I was referring to the politicians (theoretically) in charge of the civil service. I’m intrigued by where you’re going with this, though … are you concerned about the efficacy of changing the 0.1% even in the case of democratically elected Governments?

                                                                                    1. 1

                                                                                      To my mind, long-term stability is the key practical advantage of constitutional democracies as a form of government.

                                                                                      Dictatorships change less frequently, and churn far more of the government when they do. Single-party rule is subject to sudden, massive policy reversals.

                                                                                      Stability (knowing how the rules can change over time, and how they can’t) is what makes them desirable places for the wealthy to live and invest, which makes larger capital works possible.

                                                                                      1. 1

                                                                                        Right so to paraphrase - you don’t see the replacement of politicians by democratic means as likely to effect significant change, but also, you see that as a feature not a bug?

                                                                                        1. 1

                                                                                          Essentially, yes. Significant changes would imply that the voters have drastically changed their minds in a short time, which essentially never happens. The set of changes is also restricted (eg no retrospective crimes, restrictions on asset seizure).

                                                                      2. 1

                                                                        Some starting criticism: https://issforum.org/essays/PDF/CR1.pdf

                                                                        Encourage taking “our world in data” charts with a grain of salt when considering fossil fuel dependence (and our future), planetary boundaries framework losses (notably biodiversity), etc.

                                                                        1. 4

                                                                          Hunter-gatherer societies also ran up against the limitations of their mode of relating to the environment. A paradigm shift in this relationship opened up new horizons for growth and development.

                                                                          If we’ve reached similar environmental limits then the solution is a similar advancement to a higher mode, not “degrowth” (an ideology whose most severe ramifications will inevitably fall upon the people who are struggling the most already).

                                                                          1. 1

                                                                            This is a book review. What does it do to suggest the data that the number of people in extreme poverty is decreasing are false?

                                                                            1. 1

                                                                              Okay, go back to the linked chart, which references Poverty and Shared Prosperity, (World Bank, 2018) - here’s some reflection around the metrics - 12 Things We Can Agree On about Global Poverty (Hickel & Kenny, 2018) - notably the words of caution about such data:

                                                                              “10. Income and consumption does not tell us the whole story about poverty. Poverty is multi-dimensional, and some aspects of human well-being can be obscured by consumption figures.”

                                                                              “11. The present rate of poverty reduction is too slow for us to end $1.90/day poverty by 2030, or $7.40/day poverty in our lifetimes. To achieve this goal, we would need to change economic policy to make it fairer for the world’s majority. We will also need to respond to the growing crisis of climate change and ecological breakdown, which threatens the gains we have made.”

                                                                              “12. Ultimately, the more morally relevant metric is not proportions or absolute numbers, but rather the extent of poverty vis-a-vis our capacity to end it. By this metric, the world has much to do—perhaps more than ever before.”

                                                                        1. 2

                                                                          I did this at my last big company job.

                                                                          I did it for scalability reasons.

                                                                          1. 2

                                                                            Yep - if you are sharding anyways, it really makes sense.

                                                                          1. 3

                                                                            I frequently see “newtypes” (in Haskell-speak) and sometimes phantom type parameters for IDs, but it’s really not clear to me how much benefit this approach produces over a type alias. That is, for the classes of bugs that type ID string catches, but type ID = string would not, how often does those actually occur? My experience is: Not often.

                                                                            1. 1

                                                                              A type alias of type ID = string would make all different types of identifiers equivalent from the type checker’s perspective. Since identifiers are so pervasive in backend development this was the main class of bugs we wanted to prevent, as it’s quite easy to call a function with the wrong type of identifier (especially after refactoring). But YMMV of course.

                                                                              1. 3

                                                                                My experience is that this class of bugs is relatively uncommon and easy to catch/fix.

                                                                                Moreover, names seem to provide better bang-for-buck in both solving this problem and other readability improvements. In go, this means using structs instead of positional arguments.

                                                                                For example, instead of:

                                                                                func AttachFile(db DB, emailID string, fileID string) (attachmentID string, err error) {
                                                                                  // ...
                                                                                }
                                                                                

                                                                                Do:

                                                                                type AttachFile struct {
                                                                                  EmailID string
                                                                                  FileID string
                                                                                }
                                                                                
                                                                                func (args AttachFile) Do(db DB) (attachmentID string, err error) {
                                                                                  // ...
                                                                                }
                                                                                

                                                                                Now it’s extremely unlikely you’ll accidentally swap the IDs because the call site will be much clearer. As a bonus, this makes it easier to address a laundry list of other concerns, such as logging, authorization, validation, etc.

                                                                                1. 3

                                                                                  The fun thing is that if you squint, types are names that are checked by the computer. Granted, there are always trade offs involved, but for me, it makes it that little bit easier to make the integration reflect the problem I’m solving. And the error proofing is a bonus, too.

                                                                                  1. 2

                                                                                    Fun fact; Go actually calls “type Foo string” a NamedType in the spe

                                                                                2. 2

                                                                                  I avoid this in my codebase by making all the sequences (in test mode) increment by 200 per ID, and starting them at different offsets for each table (fewer than 200 tables). This ensures that no identifier can match a row in another table.

                                                                              1. 25

                                                                                I mean, don’t program like this in any language:

                                                                                cp newfil newfile2  # Deliberate typo  
                                                                                echo "Success"
                                                                                

                                                                                cp has a return value. Check it.

                                                                                1. 10

                                                                                  I believe that’s partly the point in the post. Using set -e effectively forces return code handling, at the least explicitly swallowing a bad return code with something like || true.

                                                                                  As an aside, this is why I’m not a fan of Go’s error handling. It’s optional because the “err := func()” can always be written as “func()” (afaik and can tell, anyway – happy to know if this can be forced.).

                                                                                  1. 3

                                                                                    IIRC go vet will fail that particular idiom (failure to assign / check an error return).

                                                                                    1. 4

                                                                                      So no better than shell scripts then, you need a separate tool to yell at your mistakes.

                                                                                      1. 2

                                                                                        It’s good to have a linter like go vet, but I agree that compiler that defaults to throwing errors (or at least warnings) on clear anti-patterns is better. Go has an idiomatic escape already, too, in “_ := func()” to throw away the returned error, so I’m curious why go’s compiler allows any returned value to be implicitly and silently ignored.

                                                                                1. 31

                                                                                  Serve static html from the backend, and forego dynamic behavior on the front end. You’ll spend a lot less time doing things unrelated to your goal.

                                                                                  1. 11

                                                                                    This is the answer. Don’t mess around with SPAs, they will make your life much harder. Just write a traditional web app. Use express.js if you know JS, or sinatra if you know ruby, etc. These are tools you can actually start using in an hour or less, that can serve routes in a few lines of code, and whose features you can learn incrementally as needed. If you want to add a little slickness to your UI (transitions, fetches without page reloads, etc), while staying in the classic html/css paradigm you already know, have a look at https://htmx.org/.

                                                                                    1. 2

                                                                                      Use express.js if you know JS, or sinatra if you know ruby, etc

                                                                                      It’s C++. There’s a lot of it already; the UI is just a layer on top. As I said I used a couple of libraries to give me a rudimentary routing system (based on path regexes) and Jinja-like templates.

                                                                                      1. 2

                                                                                        I have a lot of webdev experience with various stacks, but not C++. From my (limited) general experience with C++, I would imagine it would be a cumbersome web development experience, but if it’s working for you, go for it. I had assumed you were asking for something else. Either way, I think my original advice remains the same. Backend language you are familiar with, minimalist framework you can learn very quickly (or none at all, eg, in golang the std lib is enough), and htmx for UI effects/fanciness if needed.

                                                                                        EDIT:

                                                                                        From your other reply:

                                                                                        And I wouldn’t be considering HTML for the UI at all if it couldn’t do dynamic behavior; that’s table stakes. It’s not 1995 anymore and my goal isn’t to rebuild Geocities :)

                                                                                        It really depends how complex the dynamic parts need to be. At some point, if the frontend logic gets out of control, something like React may be warranted. But ime most sites that use React don’t need it. For a “social-networking”-esque site, I could see this going either way. But my instinct is still to start with a traditional architecture augmented by htmx until you find yourself needing more.

                                                                                    2. 7

                                                                                      The HTML has to be dynamically generated based on the (C++) model layer. This isn’t a static website. But I’m fairly satisfied with the C++ template engine I’m using.

                                                                                      And I wouldn’t be considering HTML for the UI at all if it couldn’t do dynamic behavior; that’s table stakes. It’s not 1995 anymore and my goal isn’t to rebuild Geocities :)

                                                                                      1. 6

                                                                                        I have written… a significant amount of javascript in the past ~15 years.

                                                                                        I would recommend you start by thinking carefully about where you want the state to live. Having some state in the javascript, some in the URL, some in HTTP cookies and some in the server (‘stateful connections’) is a recipe for trouble. IME, storing auth state in cookies and everything else in the URL has consistently been the most compatible with how browsers want pages to behave, at the cost of restricting how much state you can store (to a few kb).

                                                                                        For most content, it’s easier to get a better result if you use <a href links rather than javascript (generating different HTML in the server process based on the URL).

                                                                                        For parts which constantly receive new input from the server (eg a chat window), you can render an iframe to a URL which holds the connection open (using chunked encoding) and sends new content as it arrives. This requires very little code, is fast, and retains state correctly across page refreshes with no action on your part.

                                                                                        Beyond that, a very small amount of javascript to toggle classes is typically enough.

                                                                                        1. 1

                                                                                          Thanks. Fortunately there is pretty much no UI-specific state I need to keep. It’s all running on a client device so there’s by definition only a single user.

                                                                                        2. 5

                                                                                          Here’s a few fairly powerful vanilla techniques:

                                                                                          • Replacement for onclick: document.querySelectorAll(...).addEventListener('click', function(event) { const element = this; ... }
                                                                                          • Dynamically fetch HTML rendered by the server: fetch("/url...", { headers: { 'Content-Type': 'text/html' }, ... }).then(resp => resp.text()).then(htmlText => { element.innerHTML = htmlText; })
                                                                                      1. 3

                                                                                        That is a surprise. I’ve only used base64 as the final step in encoding data for transport over protocols or formats that don’t support binary data. And there are a lot of them… XML being fairly notable for not being enable to encode NUL.

                                                                                        1. 1

                                                                                          XML can encode NUL, different protocols may do it differently though. There is no one “XML encoding”.

                                                                                          1. 2

                                                                                            XML can encode NUL, different protocols may do it differently though. There is no one “XML encoding”.

                                                                                            I can encode NUL as base64-text-rasterized-in-a-png, too.

                                                                                            There’s a difference between “you can build an encoding scheme in this language which can represent NUL” and “the language has explicit support for this feature, and it works well”.

                                                                                            1. 1

                                                                                              Does XML accept a numeric character reference for NUL, like this: &#0; ?

                                                                                              https://en.m.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references

                                                                                          1. 4

                                                                                            I feel like pretty much every “design pattern” is an example of an “emergent language feature”, as the author named them. Which is what I dislike about Java-style OOP.

                                                                                            1. 8

                                                                                              Design patterns are descriptive, not prescriptive. Whenever objects are composed in a certain way, including composition of functions, then the corresponding design pattern describes the behavior of the composition. They don’t just emerge from languages you don’t like, but from any Turing-complete language.

                                                                                              1. 4

                                                                                                Whenever there is a pattern in your code, you should abstract it away. Some languages will allow you to do that, some won’t.

                                                                                                1. 8

                                                                                                  Expressive languages still have patterns, people just refuse to call them patterns because they think expressive languages don’t have patterns.

                                                                                                  1. 2

                                                                                                    Can you give an example?

                                                                                                    1. 3

                                                                                                      If nothing else, Nim’s metaprogramming tends to have certain patterns, like dispatching on the kind of an AST node.

                                                                                                      Also, XiDoc uses when isMainModule and not defined(js):, a very common pattern in Nim programs that want to both expose a library and an executable from the same file. Just because the pattern isn’t obnoxious to deal with doesn’t mean it isn’t a pattern, a thing repeated where needed. Janet solves that particular conundrum differently, and Nim’s is a riff on a similar pattern in Python.

                                                                                                      It is also worth calling out that many patterns are as much about the the way data is arranged as they are are about code being arranged.

                                                                                                      And one could argue that convention-based programming is all about fitting into a prescribed pattern.

                                                                                                      That being said, making patterns in code less obnoxious to deal with is nearly always pleasant, IMO.

                                                                                                      1. 1

                                                                                                        I’ll see if I can come up with one, though it might be tricky because I don’t think we have any languages in common

                                                                                                        1. 2

                                                                                                          Just use pseudocode.

                                                                                                          1. 1

                                                                                                            I don’t see how I could. Patterns are found by examining how people use languages in the wild, and there’s no pseudocode in the wild.

                                                                                                        2. 1

                                                                                                          Ruby is an ultra-expressive language and very strong on using patterns like attr_accessor and similar to manage that complexity. Most of those patterns end up as libraries, but their use is as schematic as using patterns in other languages.

                                                                                                          1. 2

                                                                                                            I wouldn’t call attr_accessor a pattern. It’s just a method. That’s like calling print a method.

                                                                                                            1. 1

                                                                                                              It’s the implementation of the “Accessor Pattern” in a method to encourage its use. Ruby also uses iteration as a general pattern over loops, and the method is called “each”. It uses conversion over casts, implemented through “to_” methods. Ultimately, all pattern use boils down to some form of using language features, and methods are just the most common construct in Ruby.

                                                                                                              Ruby is very brief in it’s pattern use, but there’s a ton of them to know to program it competently.

                                                                                                              1. 2

                                                                                                                Well, that’s exactly my point. The pattern is abstracted away into a method, so there’s no repetitive code.

                                                                                                                1. 1

                                                                                                                  Patterns are not about repetitive code. That may be related, but many patterns are around common structure and names.

                                                                                                                  Related discussion: attr_accessor :foo, :bar, :batz or three lines of attr_accessor :foo...? If DRY is your only principle, the first, but there’s a strong school that says the second is preferable.(*)

                                                                                                                  Java Code is repetitive, but strongly pattern-based.

                                                                                                                  (*) which is why i prefer Single Source of Truth over DRY. https://en.wikipedia.org/wiki/Single_source_of_truth

                                                                                                                  1. 3

                                                                                                                    In my opinion, what distinguishes a pattern from normal code is that you have to recognize it as a pattern instead of taking the code at face value. For example, if you see the following Java code:

                                                                                                                    public class Vector2 {
                                                                                                                        private double x;
                                                                                                                        public double getX() {
                                                                                                                            return x;
                                                                                                                        }
                                                                                                                        public void setX(double newX) {
                                                                                                                            x = newX;
                                                                                                                        }
                                                                                                                        private double y;
                                                                                                                        public double getY() {
                                                                                                                            return y;
                                                                                                                        }
                                                                                                                        public void setY(double newY) {
                                                                                                                            y = newY;
                                                                                                                        }
                                                                                                                    }
                                                                                                                    

                                                                                                                    If you just read the code without recognizing that it’s “just” two properties with getters and setters, you’ll have to think about what it does in the larger picture. In contrast, the Ruby version

                                                                                                                    class Vector2
                                                                                                                      attr_accessor :x, :y
                                                                                                                    end
                                                                                                                    

                                                                                                                    makes the intention clear.

                                                                                                                2. 1

                                                                                                                  IMHO, to_xxx is an anti-pattern. Making one type out of another should be a constructor on the target type. to_xxx in Java is an artefact of Java types being inextensible.

                                                                                                                  1. 1

                                                                                                                    How far would you take that? “Each class which wants to support serialization to string should add a constructor to the string class” seems a little extreme to me.

                                                                                                            2. 1

                                                                                                              Clojure (with-open), Common Lisp (with-open-file, with-open-stream) and Ruby (File.open have the with-foo pattern for scoped resource usage.

                                                                                                          2. 4

                                                                                                            One of the frustrating things about design patterns in software is that so much of the original intent and thought behind “patterns” was lost in the telephone game of people talking about software engineering over the years. Christopher Alexander and the Gang of Four would both tell you that if you can abstract it away, it’s—by definition—not a pattern.

                                                                                                            The key thing that separates patterns from data structures and algorithms is that patterns are slightly different every time they are manifested. A pattern is a guideline for how one could structure a solution to a problem, but not a solution itself. Taking a pattern and applying it still requires human judgement and understanding of the specific context in which it’s applied to know what to implement.

                                                                                                            1. 2

                                                                                                              Abstraction is not factorization. Yes, whenever there is a repetition in code, we should factor it out.

                                                                                                              1. 1

                                                                                                                Nah. That repetition is very likely to be incidental, and factoring it out has the effect of reifying an abstraction that is unlikely to stand the test of time.

                                                                                                              2. 1

                                                                                                                This sentence implies definitions of “pattern” and “abstraction” that aren’t familiar to me. Can you say more?

                                                                                                                1. 2

                                                                                                                  A pattern is something that is repetitive, either directly or on a more abstract level. If you have a lot of the same code, it violates the DRY principle and you should extract it into a procedure/function/method. However, this won’t always be possible when the repetition is more nuanced. In this case, languages like Java will simply say “fuck you” and leave you to either write a lot of repetitive code, or even use a code generator to write it automatically, which produces heaps of code that is hard to navigate through and find the true substance. Meanwhile, a more powerful language will offer features like templates or macros that can extract the repetition in the same way that procedures can extract simple repetition.

                                                                                                                  1. 1

                                                                                                                    Thanks for the response. I think you’re using a pretty esoteric definition of “pattern”. Also, DRY isn’t really about literal repetition of code, it’s about sources of truth in the information sense. It’s often far better to leave repetition alone than to try and abstract it away!

                                                                                                              3. 2

                                                                                                                Huh! I’ve never heard this perspective before. I’ve always understood design patterns as explicitly proscriptive: they originate from repetition in practice, yes, true — but they exist as well-defined things, serving as a kind of shared domain language for practitioners. I’ve always liked the notion that design patterns are “cages for complexity” — things to actively apply to problems to keep them tractable.

                                                                                                            1. 10

                                                                                                              So one answer to the question as initially posed is that no, WebAssembly is not the next Kubernetes; that next thing is waiting to be built, though I know of a few organizations that have started already.

                                                                                                              I agree there is something of an “inner platform effect” going on here…

                                                                                                              https://en.wikipedia.org/wiki/Inner-platform_effect

                                                                                                              That is, WebAssembly is useful, but we don’t need it to encompass all of server side computing … That’s just rebuilding an operating system on top of an operating system, which basically doubles the number of problems your system has.

                                                                                                              I imagine it’s going to be a similarly useful technology as the JVM … but the JVM is by and large “just another Unix process” in a typical server workload. It didn’t end up being as general or universal as was once thought.

                                                                                                              1. 2

                                                                                                                I haven’t started using webassembly in practice yet, but isn’t one benefit of WASI et al that the enable more advanced capabilities systems than (most) traditional server operating systems? That could be a practical benefit, especially for multi-tenant services i think.

                                                                                                                1. 7

                                                                                                                  Having default-deny of a wasm sandbox vs. default-allow of Unix is definitely better in principle. However it does make it harder to port existing software, which was one benefit of WASM.

                                                                                                                  I think what @eyberg listed is basically what I’m getting at. WASM is a small part of a server side platform; WASI adds more, but you will end up rebuilding most of an OS. That is exactly what the JVM tried to do.

                                                                                                                  And you will have downsides like lack of heap protection, since WASM is a flat address space:

                                                                                                                  https://lobste.rs/s/pzr5ip/everything_old_is_new_again_binary

                                                                                                                  And performance issues like lack of SIMD. I think they are working on adding SIMD, but again it’s another layer / point of indirection, i.e. an “inner platform”. An ISA is already an abstraction layer over physical hardware :) This may be a cost you want to pay in some circumstances, but not all.

                                                                                                                  Here I question if WebAssembly is really “polyglot”: https://news.ycombinator.com/item?id=28581634

                                                                                                                  i.e. programmers underestimate the degree to which languages and VMs are coupled. Any VM design decision creates some “losers”, and the losers are the languages that will experience a 2x-10x slowdown over their native environment.

                                                                                                                  1. 1

                                                                                                                    Having default-deny of a wasm sandbox vs. default-allow of Unix is definitely better in principle.

                                                                                                                    Snap’s --classic flag comes to mind here.

                                                                                                                    1. 1

                                                                                                                      And you will have downsides like lack of heap protection, since WASM is a flat address space

                                                                                                                      There is https://github.com/WebAssembly/multi-memory, which is basically memory segmentation for WebAssembly.

                                                                                                                    2. 1

                                                                                                                      The capability system is incredible, almost comparable to that of lua - with the advantage that nearly all WASM implementations are coded defensively and expect hostile bytecode.

                                                                                                                  1. 5

                                                                                                                    My issue is that I believe a software engineer should be able to apply known, repeatable, principles and practices to a software endeavor in order to produce a predictable outcome within determined constraints.

                                                                                                                    Where does that exist in our industry, other than in non-complex systems?

                                                                                                                    1. 10

                                                                                                                      IME, “non-complex systems” are largely the ones built by people who treat it like engineering.

                                                                                                                      99% of the time, complex systems come about when you let someone fuck around with new tools instead of solving a problem.

                                                                                                                      Known, repeatable methods exist for virtually every aspect of programming, at virtually every layer.

                                                                                                                      1. 4

                                                                                                                        99% of the time, complex systems come about when you let someone fuck around with new tools instead of solving a problem.

                                                                                                                        Indeed! Needlessly complex systems come about when you allow that to happen in pretty much any industry. The complexity of a problem tends to translate into complexity of the software that solves it, much like it tends to translate into complexity of the machinery that solves it. E.g. tax software is very complex because tax legislation is very complex, even though it’s “just” arithmetic, much like photolithography equipment is very complex because the sequence of chemical and physical processes it steers is very complex.

                                                                                                                        Granted, not all problems being solved stem straight from the “real-world” application of a program. Things like allowing only people with the right clearance to view some documents (“security”) are also legitimate problems that a system may need to solve. The bloat line isn’t always easy to draw.

                                                                                                                        But complexity additional to that of the legitimate problems being solved is entirely self-inflicted, and often arises because nobody in charge or anything has any understanding of what’s important and what isn’t, so they let everyone – or, worse, they insist that everyone – fuck around with new tools.

                                                                                                                      2. 2

                                                                                                                        There’s a glimpse of this in the industry already. It’s a niche but it’s there. Formal methods.

                                                                                                                        For example, there are relatively big systems (tens of KLOC) being built using Dafny or Spark.

                                                                                                                        They use techniques that are repeatable, simple and pretty well understood (imperative languages + contracts).

                                                                                                                        Once there’s an incentive to use them more, I guess bigger systems will be built by composing simpler verified parts. The biggest problem is cost. It’s 3-6x more costly to build software like this, and it’s much slower.

                                                                                                                        1. 2

                                                                                                                          One open problem is that most proofs don’t compose, as I understand it, so you can’t just use small verified parts and compose them into a larger verified whole, you have to re-verify the whole as an entire system, at least for some classes of formal methods. @hwayne I think has more details there.

                                                                                                                          1. 1

                                                                                                                            Absolutely. Dafny for example only carries postconditions forward to keep tractability while composing things, but that looses some information so it’s a compromise. In practice, I think it works quite well.

                                                                                                                          2. 1

                                                                                                                            I think that is an interesting point, but is that glimpse on the fringes? A much more pressing need is surely to find a predictable way to model a complex domain problem in code? When I started programming about 40 years ago the question of the day was how to represent business logic and constraints outside of a data model. Stored procedures, or… what? In some ways nothing has really changed, albeit instead of stored procedures the engineering of the day is transactional scripts organized using functional decomposition which rapidly approach a big ball of mud as complexity increases. Hmm, sounds just like 30 years ago, but without the “agile” and “services” terminology that provide a diversion today.

                                                                                                                            Formal methods are I think answering a question of how, where the problem is more one of “what”?

                                                                                                                            “The hardest single part of building a software system is deciding precisely what to build.”, Frederick Brooks – “No Silver Bullet”

                                                                                                                          3. 2

                                                                                                                            I’m going to make a leap of faith and assume you’re saying that because you feel that other “engineering” fields have those properties…they really don’t, in my experience working closely alongside mechanical, electrical, and chemical engineers.

                                                                                                                            1. 1

                                                                                                                              No I made no statement about other engineering disciplines.

                                                                                                                            2. 1

                                                                                                                              Release Engineering?

                                                                                                                            1. 4

                                                                                                                              Really great approach! The whole post showcases quite pragmatic approach to the problem they had and how they optimized it for. My favorite sentence is at the end:

                                                                                                                              The library works for our target platforms, and we don’t wish to take on extra complexity that is of no benefit to us.

                                                                                                                              Truly pragmatic approach: it works for us, if you want, fork and modify to oblivion, we give you a starting point. Wish more software is handled like this and doesn’t include all but kitchen sink.

                                                                                                                              1. 0

                                                                                                                                More and more people are fortunately adopting the suckless philosophy.

                                                                                                                                1. 15

                                                                                                                                  Unfortunately, the suckless philosophy leads to software that doesn’t do what software is meant to do - alleviate human work by making the machine do it instead. The suckless philosophy of “simplicity” translates to “simplistic software that doesn’t do what you would need it to do, so either you waste time re-implementing features that other people have already written (or would have written), or you do the task by hand instead”.

                                                                                                                                  If, when required to choose exactly one of “change the software to reduce user effort” and “make the code prettier”, you consistently choose the latter, you’re probably not a software engineer - you’re an artist, making beautiful code art, for viewing purposes only. You definitely aren’t writing programs for other people to use, whether you think you are or not.

                                                                                                                                  This philosophy (and the results) are why I switched away from dmenu to rofi - because rofi provided effort-saving features that were valuable to me out-of-the-box, while dmenu did not. (I used dmenu for probably a year - but it only took me a few minutes with rofi to realize its value and switch) rofi is more valuable as a tool, as a effort-saving device, than dmenu is, or ever will be.

                                                                                                                                  In other words - the suckless philosophy, when followed, actively makes computers less useful as tools (because, among other things, computers are communication and collaboration devices, and the suckless philosophy excludes large collaborative projects that meet the needs of many users). This is fine if your purpose is to make art, or to only fulfill your own needs - just make sure that you clearly state to other potential users that your software is not meant for them to make use of.

                                                                                                                                  Also note that the most-used (and useful) tools follow exactly the opposite of the suckless philosophy - Firefox, Chromium, Windows, Libreoffice, Emacs, VSCode, Syncthing, qmk, fish, gcc, llvm, rustc/cargo, Blender, Krita, GIMP, Audacity, OBS, VLC, KiCad, JetBrains stuff, and more - not just the ones that are easy to use, but also ones that are hard to use (Emacs, VSCode, Audacity, Blender, JetBrains) but meet everyone’s needs, and are extensible by themselves (as opposed to requiring integration with other simple CLI programs).

                                                                                                                                  There’s a reason for this - these programs are more useful to more people than anything suckless-like (or built using the Unix philosophy, which shares many of the same weaknesses). So, if you’re writing software exclusively for yourself, suckless is great - but if you’re writing software for other people (either as an open-source project, or as a commercial tool), it sucks.

                                                                                                                                  To top it off, people writing open-source software using the suckless philosophy aren’t contributing to non-suckless projects that are useful to other people - so the rest of the open-source community loses out, too.

                                                                                                                                  1. 2

                                                                                                                                    It’s fine to disagree with “the suckless philosophy”, but do please try to be nice to people gifting their work as FLOSS.

                                                                                                                                    1. 11

                                                                                                                                      The tone is not dissimilar from the language on the page it is replying to: https://suckless.org/philosophy/

                                                                                                                                      Many (open source) hackers are proud if they achieve large amounts of code, because they believe the more lines of code they’ve written, the more progress they have made. The more progress they have made, the more skilled they are. This is simply a delusion.

                                                                                                                                      Most hackers actually don’t care much about code quality. Thus, if they get something working which seems to solve a problem, they stick with it. If this kind of software development is applied to the same source code throughout its entire life-cycle, we’re left with large amounts of code, a totally screwed code structure, and a flawed system design. This is because of a lack of conceptual clarity and integrity in the development process.

                                                                                                                                      1. 1

                                                                                                                                        I wasn’t actually trying to copy the style of that page, but I guess that I kind of did anyway.

                                                                                                                                        @JoachimSchipper (does this work on Lobsters?) My reply wasn’t meant to be unkind to the developer. I’m frustrated, in the same sense that you might be frustrated with a fellow computer scientist who thought that requiring all functions to have a number of lines of code that was divisible by three would improve performance, an idea which is both obviously wrong, and very harmful if spread.

                                                                                                                                        …but I wasn’t trying to impart any ill will, malice, or personal attack toward FRIGN, just give my arguments for why the suckless philosophy is counter-productive.

                                                                                                                                    2. 1

                                                                                                                                      Some people insist on understanding how their tool works.

                                                                                                                                      I have a few friends like that - they are profoundly bothered by functionality they don’t understand and go to lengths to avoid using anything they deem too complex to learn.

                                                                                                                                      The rest of open source isn’t ‘losing out’ when they work elsewhere - they weren’t going to contribute to a ‘complex’ project anyways, because that’s not what they enjoy doing.

                                                                                                                                      1. -4

                                                                                                                                        Nice rant

                                                                                                                                        1. 5

                                                                                                                                          You throw advertising for suckless in the room as the true way, link to your website with the tone described here and then complain about responses ? That doesn’t reflect well on the project.

                                                                                                                                          1. 0

                                                                                                                                            What are you talking about? There is no one single true way, as it heavily depends on what your goals are (as always). If your goals align with the suckless philosophy, it is useful to apply it, however, if your goals differ, feel free to do whatever you want.

                                                                                                                                            I don’t feel like replying exhaustively to posts that are ad hominem, which is why I only (justifiably) marked it as a rant. We can discuss suckless.org’s projects in another context, but here it’s only about the suckless philosophy of simplicity and minimalism. I am actually surprised that people even argue for more software complexity, and SLOC as a measure of achievement is problematic. In no way does the suckless philosophy exclude you from submitting to other projects, and it has nothing to do with pretty code. You can do pretty complex things with well-structured and readable code.

                                                                                                                                            1. 4

                                                                                                                                              While you may find it insulting, I don’t think the comment is ad hominem at all. It’s not saying that the suckless philosophy is defective because of who created/adopts/argues for it. That would be an attack ad hominem. The comment is saying the suckless philosophy is defective because software that adheres to it is less useful than other software, some of which was then listed in the comment.

                                                                                                                                              While it’s (obviously) perfectly fine to feel insulted by a comment that says your philosophy produces less-than-useful software, that does not make the comment either a rant or an ad hominem attack.

                                                                                                                                              It’s a valid criticism to say that over-simplifying software creates more human work, and a valid observation that software which creates more human work doesn’t do what software is meant to do. And you dismissed that valid criticism with “Nice rant.” If you don’t feel like responding exhaustively, no one can blame you. But I view “nice rant” as a less-than-constructive contribution to the conversation, and it appears that other participants do as well.

                                                                                                                                              1. 2

                                                                                                                                                My post was neither a rant, nor ad-hominem. You should be a bit more thoughtful before applying those labels to posts.

                                                                                                                                                It’s clearly not an ad-hominem because nowhere in my post did I attack your character or background, or use personal insults. My post exclusively addressed issues with the suckless philosophy, which is not a person, and is definitely not you.

                                                                                                                                                It’s also (more controversially) probably not a rant, because it relies on some actual empirical evidence (the list of extremely popular programs that do the opposite of the suckless philosophy, and the lack of popularity among programs that adhere to it), is well-structured, is broken up into several points that you can refute or accept, had parts of it re-written several times to be more logical and avoid the appearance of attacks on your person, and takes care to define terminology and context and not just say things like “suckless is bad” - for instance, the sentence “So, if you’re writing software exclusively for yourself, suckless is great - but if you’re writing software for other people (either as an open-source project, or as a commercial tool), it sucks” specifically describes the purpose for which the philosophy is suboptimal.

                                                                                                                                                It also had at least three orders of magnitude more effort put into it than your two-word dismissal.

                                                                                                                                            2. 4

                                                                                                                                              Rather than labeling it a rant, wouldn’t it be more persuasive to address some of the points raised? Can you offer a counterpoint to the points raised in the first or last paragraphs?

                                                                                                                                              1. 2

                                                                                                                                                It is definitely a rant, as the points adressed are usually based on the question which norms you apply. Is your goal to serve as many people as possible, or is your goal to provide tools that are easy to combine for those willing to learn how to?

                                                                                                                                                In an ideal world computer users would, when we consider the time they spend with them, strive to understand the computer as a tool to be learnt. However, it becomes more and more prevalent that people don’t want to and expect to be supported along the way for everything non-trivial. We all know many cases where OSS developers have quit over this, because the time-demand of responding to half-assed PRs and feature-requests is too high.

                                                                                                                                                @fouric’s post went a bit ad-hominem regarding “software engineers” vs. “artists”, but I smiled about it as my post probably hit a nerve somewhere. I would never call myself a “software engineer”.

                                                                                                                                                Hundreds of thousands of people are using suckless software, knowingly or unknowingly. Calling us “artists” makes it sound like we were an esolang-community. We aren’t. We are hackers striving for simplicity.

                                                                                                                                                I could also go into the security tangent, but that should already be obvious.

                                                                                                                                                1. 1

                                                                                                                                                  It is definitely a rant, as the points adressed are usually based on the question which norms you apply.

                                                                                                                                                  …norms which I addressed - I was very clear to describe what purposes the suckless philosophy is bad at fulfilling. That is - my comment explicitly describes the “norms” it is concerned with, so by your own logic, it is not a rant - and certainly contains more discussion than any of your further replies, who do nothing to refute any of its points.

                                                                                                                                                  @fouric’s post went a bit ad-hominem regarding “software engineers” vs. “artists”

                                                                                                                                                  Nor is there any ad-hominem contained in the comment, and certainly nothing around my differentiation between “software engineers” and “artists” - nowhere did I make any personal attack on your “character or motivations”, or “appeal to the emotions rather than to logic or reason”, as a quick online search reveals for the phrase “ad-hominem”.

                                                                                                                                                  I smiled about it as my post probably hit a nerve somewhere.

                                                                                                                                                  If you want to refute any of the points I made, you’re welcome to do it. However, if you just want to try to arouse anger and smile when you do so, I’ll ask you to stop responding to my posts, especially with a two-word dismissal that doesn’t address any of my arguments.

                                                                                                                                                  I would never call myself a “software engineer”

                                                                                                                                                  …then it should be even more clear that my post was not a personal attack or ad-hominem against you. “You keep using that word…”

                                                                                                                                          2. 4

                                                                                                                                            How does the suckless philosophy interact with feature flags?

                                                                                                                                            1. 2

                                                                                                                                              Suckless would say you should only have features you use, and instead of feature flags you have optionally-applied patches

                                                                                                                                        1. 1

                                                                                                                                          Got a new air fryer, I’ve got a whole line up of recipes to try this weekend. So far Buffalo Cauliflower “wings” are a far and away winner.

                                                                                                                                          Programming wise, I might find a Makie.jl ticket to pickup, wanting to get more into Julia open source.

                                                                                                                                          1. 1

                                                                                                                                            Buffalo Cauliflower is great. My favourite air fryer recipe so far is fried olives. You need three bowls, the first full of plain flour with whatever spices you feel like (some ginger and paprika is nice), one with egg, and one with breadcrumbs. Roll a pimento-stuffed olive in each bowl in turn until it’s completely coated. Pop them in the air fryer for about 5 minutes and they come out warm and crunchy. Totally addictive. Fortunately, they’re just enough effort that I am too lazy to stuff my face with them all the time.

                                                                                                                                            1. 1

                                                                                                                                              This sounds amazing! Thanks for the tip, my partner and I love olives so we’ll definitely have to try this out.

                                                                                                                                            2. 1

                                                                                                                                              Can somebody explain to me the difference between an air fryer and a convection oven?

                                                                                                                                              1. 4

                                                                                                                                                Marketing

                                                                                                                                                1. 1

                                                                                                                                                  That’s a very lazy claim and makes as much sense as saying the only difference between a toaster and a microwave is marketing - after all, they both use EM radiation directed at the surface of the food to heat and so must be basically equivalent. The fact that it’s a different part of the spectrum is just a detail.

                                                                                                                                                  The outcome of heating food depends on quite a lot of factors. There’s a big difference between convection and radiation in heating. Radiation (in the form of grills, toasters, and so on) provides a lot of heat towards the food and so produces a very high temperature gradient. The outside gets oxidised quickly, the inside may remain cold. In a microwave, the heat comes from interaction between the water molecules and the microwave and so the hotest point is just below the surface. This typically isn’t exposed to air and so you don’t cause any of the chemical reactions that lead to crisping on the outside. A convection oven heats the air and cooks the food by the air conducting heat to the food. The air cools as a result of transferring the heat to the food. An old-style convection oven typically would heat very unevenly and so newer (last 50 years?) ones have a fan that moves the air around. This means that moisture from the surface is slowly removed, which can dry out the surface of the food.

                                                                                                                                                  An air fryer has a much more aggressive fan. This means that the temperature of the air touching the food is generally higher, it also means that the drying effect is much greater. As a result, things get crisp much faster in an air fryer and, because the edges get hotter faster, the middle is cooked faster.

                                                                                                                                                  This means that, if you have a small amount of oil on the surface of food, the result is closer to deep frying than to roasting.

                                                                                                                                                2. 1

                                                                                                                                                  Size and air speed (typically substantially faster in an air fryer - which is good for e.g. pork crackling where rapid surface heating is key).

                                                                                                                                                  1. 1

                                                                                                                                                    An air fryer moves the air a lot faster than a fan-assisted oven. This means that it dries the surface of the food a lot more quickly and transfers heat to the surface faster.

                                                                                                                                                    1. 1

                                                                                                                                                      Size

                                                                                                                                                      1. 1

                                                                                                                                                        Tyvm

                                                                                                                                                  1. 9

                                                                                                                                                    Interesting comment from Peter Norvig there: http://www.loper-os.org/?p=69#comment-17594

                                                                                                                                                    There are other languages which allow developers to be very productive, and all it takes is spending a bit of time learning them. Having said that, I do agree with the thesis that corporation value fungibility of developers a lot, and I find that soul crushing.

                                                                                                                                                    1. 8

                                                                                                                                                      The response to that by the website’s primary author is as classy as usual, too. With friends like these…

                                                                                                                                                      1. 6

                                                                                                                                                        I think “fungibility” is a particularly pessimistic view. The same benefits that facilitate “fungibility” in a corporate context also facilitate collaboration generally including in the open source, research, and just-for-fun worlds.

                                                                                                                                                        1. 4

                                                                                                                                                          Counterpoint: If you work on something truly valuable to society, it’s irresponsible to make it depend on you alone. We humans are fragile creature, after all.

                                                                                                                                                          1. 3

                                                                                                                                                            Agree, although this is an extreme example. There aren’t that many things that are truly valuable to society. Most of the time, it’s valuable only for your corporate overlord as a mean to extract money, and if that goes up in flame, I won’t feel bad at all.

                                                                                                                                                        1. 5

                                                                                                                                                          This is good, but it, IMO, should be SHA256 or Blake2 instead, which are considered cryptographically strong unlike MD5.

                                                                                                                                                          1. 2

                                                                                                                                                            Since this is just a validation script you could theoretically make it generic enough to process a handful of different hash types so that it’s more compatible.

                                                                                                                                                            1. 2

                                                                                                                                                              I was just thinking about this, and had two thoughts:

                                                                                                                                                              • Generalize it by adding a CLI flag to indicate which hashing function is being used. (Something like, -n md5, -n sha256, etc)
                                                                                                                                                              • And/or also supporting the Multihash format
                                                                                                                                                              1. 2

                                                                                                                                                                Thought about adding other formats, but considering I was nerd-sniped, I had other things I intended to do today 😅

                                                                                                                                                                Definitely gonna read up on Multihash, as this is the first time I’ve heard of it.

                                                                                                                                                              2. 1

                                                                                                                                                                Feature creep 😁

                                                                                                                                                                But adding that into the script wouldn’t be too much of an excercise.

                                                                                                                                                              3. 1

                                                                                                                                                                You’re absolutely right, but most sites that I’ve come across that use the pattern only provide MD5.

                                                                                                                                                                I thought about adding a flag to specify the type of sum, but feature creep 😁

                                                                                                                                                                1. 1

                                                                                                                                                                  Yeah, but how would that help you run a script where the MD5 was provided :)

                                                                                                                                                                1. 5

                                                                                                                                                                  What’s wrong with base32 < /dev/urandom | head -c 32 | tr '[:upper:]' '[:lower:]' ?

                                                                                                                                                                  160 bits of entropy (5 per char) while being easy to type (no special chars etc - though most sites will make you add one).

                                                                                                                                                                  1. 2
                                                                                                                                                                    $ base32 < /dev/urandom | head -c 32 | tr A-M a-m | sed 's/..../&-/g;s/-$//'; echo 
                                                                                                                                                                     QWP5-liQN-mmUX-2kX7-kYkW-WchN-SR5O-3QXY
                                                                                                                                                                    
                                                                                                                                                                    1. 3

                                                                                                                                                                      dd if=/dev/random|tr -cd '\x21-\x7e'|dd bs=1 count=16 status=none;echo

                                                                                                                                                                      I have noticed that for some things it lets too much through, but in those cases the filter can always be modified.