1. 4

    I have a 13” M1 and it’s the best laptop I’ve owned in a long time, possibly ever. Fantastic battery life and thermals. One cable connects to my external monitor/USB hub so I get all my peripherals and charging in one fell swoop. The lack of ports has never been a problem, but I’m a minimalist.

    The only time I heard the fan spin up is when I accidentally had a tight infinite loop in some code I was working on. I’ve never gotten the battery below 30% and I use it on the go all the time.

    I’ve heard the 14” M1Pro is even nicer.

    1. 2

      I’ve heard the 14” M1Pro is even nicer.

      It’s complicated… I had the 13” M1 Air and now the Pro 14” (M1 Pro 10 core, not the base model). My findings:

      • The M1 Air being passively cooled is really a nice feature. The fan on the Pro 14” rarely turns on. But when it turns on, you hear it. It is not ‘MacBook Pro Intel’-loud or ‘Lenovo Thinkpad’-loud. But it still feels like a downgrade.
      • Even though the weight difference of the Air and the Pro is not large on paper, it is quite a big difference in practice. Even though I have had my Pro for a month now, I still think ‘it’s heavy’ every time I pick it up.
      • I love the return of MagSafe, but in practice it does not make that much of a difference. I am using it at a desk 95% of the time, and USB-C is even better in that case (fewer cables to plug). Though I’ll probably love it when travel is back to normal.
      • The 120Hz display is beautiful and sure, you can see the difference as notifications come in. But I mostly plug it in to an external screen that is 60Hz, so :shrug:. Also, it is a visible difference, but not something that wows me, like moving to a retina screen did (which basically can’t be unseen).
      • The M1 in the Air is nothing to sneeze at. It is largely equivalent to a Ryzen 3700X performance-wise, but passively cooled and uses very little energy.
      • That said, if you do a lot of builds (e.g. I am doing a lot of Rust stuff), the 8 performance cores of the M1 Pro/Max are really nice. Also, the M1 Pro/Max have two Firestorm AMX (matrix multiplication) units, compared to one in the M1. Since my work is primarily related to machine learning, I benefit from that as well.
      • The SD card reader is nice for importing photos or putting maps on my GPS (which has a slow USB connection).
      • The notch is great. It is additional screen estate, and there is nothing in the middle of the menu bar anyway (outside Xcode).

      For most people, the M1 Air is the best Mac, it provides the best price-features balance, plus being light and passively cooled is great. Get a Pro if you need > 16GB RAM, need to connect more than one external display, or if your workflow benefits a lot from the additional performance cores.

      1. 1

        If only they would provide a setting to never turn the fans on and therefore never work hard enough to need to. I’d take less performance over fan noise. I can’t see Apple ever making this option and if anyone else does, it’ll be an unreliable hack.

        So I’m sticking with the Air, and - apart from the lack of multiple external monitor support (which I will likely work around) it’s pretty much the perfect personal computer for me.

      2. 1

        Honestly, the only thing I’d want on the Air from the Pro is MagSafe. Hopefully the next revision of the Air incorporates that.

        1. 3

          And the headphone jack/amplifier that is compatible with high impedance studio headphones. Then the MacBook Air becomes the ultimate portable audio machine.

          1. 1

            Wow, first I heard of this. Looks like it’d be fine to use something like the HD600’s with.

            1. 2

              Technical details can be found here: https://support.apple.com/en-us/HT212856

          2. 3

            Eh, I like the idea of USB-C everything, but dongles and adapters are hit and miss, and more miss than hit to be honest. I have an external monitor running through Apple’s USB-C adapter and it works on my wife’s 2020 13” MacBook Pro but not my 2020 16” MacBook Pro (or rather, she got an image in shades of pink while I got “no signal” at all). I’ve used other adapters as well, and some of those would fry an egg if you used them to power your MacBook. Similarly, I’ve had a lot of problems with various dongles for SD cards that require some ceremonious combination of disconnecting and reconnecting the disk from the dongle and the dongle from the computer). I also bought an “Amazon Basics” ethernet->USB-C adapter which straight up didn’t work. Until all of that fuckery is ironed out, I’ll content myself with physical ports.

            Beyond my problems, there’s a whole bunch of lay people who understandably believe that they should be able to power their USB-C devices with a USB-C charger, because after all, what kind of numpty would design a connector that would allow someone to underpower their device? But instead, you have to read the fine print on every device and power supply you use to make sure the power supply is adequate (and even then you might have issues if the power supply is average quality).

            1. 2

              I have an external monitor running through Apple’s USB-C adapter and it works on my wife’s 2020 13” MacBook Pro but not my 2020 16” MacBook Pro (or rather, she got an image in shades of pink while I got “no signal” at all).

              What I have learned over the years: the only thing that is really reliable is DisplayPort. So, I use a USB-C Alt mode <-> DisplayPort cable. Has always done the job wonderfully.

              I’ve used other adapters as well, and some of those would fry an egg if you used them to power your MacBook.

              Oh yeah. And even worse, lot’s of them cause interference, dropping Bluetooth connections and Wifi. I had an Anker USB-C dock that reliably dropped Bluetooth and Wifi when it was plugged in. Same experience with some other docks.

              to power their USB-C devices with a USB-C charger,

              I have a very expensive Lenovo USB-C dock. And it decides not to charge the laptop 70% of the time and you have to replug it several times to get it charging. Even more funny: I had a Lenovo laptop for a bit over half a year. When the battery was drained, the Lenovo dock (or Lenovo charger that was provided with the laptop) couldn’t bring the laptop back to life. Though connecting it 10 minutes to an Apple USB-C charger revived it wonderfully. Something seems to go awfully wrong with negotiating power delivery with some Lenovo docks/adapters.

              1. 1

                I have a very expensive Lenovo USB-C dock. And it decides not to charge the laptop 70% of the time and you have to replug it several times to get it charging.

                I had the TB3 (or 2?) dock for a X1 Carbon 5th generation and only had problems with it. Displays were often not detected no matter which DP port they were connected to. Using the wired ethernet port caused random system freezes under Linux and the list goes on. It is not as bad as the USB-3 dock from Lenovo which is just garbage. Anyways, never had a problem connecting external displays using USB-C. You only have to make sure to use a proper cable, which is not that easy, but if you got one together with your monitor then just use that.

          3. 1

            I have a very similar setup and no matter what I do with my 13” Mac Pro M1 the fan never spins up. It’s my first MacBook and I have to admit that even macOS is not perfect, sometimes USB devices connected to my docking station/monitor are not picked up after suspend (hello Linux!) and I also had to force reboot the machine once. Battery life and performance are fantastic and Rosetta2 is like magic, it does not seem to matter if an app is emulated or not, performance is always fine. If I could only use Gnome3 as a desktop environment on this machine…

          1. 7

            I’m really mad about this. I’ve been a linux shill for a long time, and continue to be one, but if someone wanted me to recommend a laptop, at this point, the only thing I can say (unless you want to play games) is an m1 macbook. I’d go for the pro rather than the air, but it’s all the same. It does everything I need it to, and it doesn’t do all that much I don’t want it to. There is no other alternative that has the same build quality, usefulness, and battery life out there.

            1. 3

              Agreed. I really want to use Linux, and I don’t mind grinding through all of the little bugs and quirks to get it to behave properly with whatever hardware I happen to have; however, there’s just no way to get anywhere close to Mac quality trackpad support or at least I haven’t found it in the last ~15 years. Certainly I can’t recommend it to anyone less technical.

              It’s really a marvel that Microsoft doesn’t work with hardware vendors to get close to parity. Is trackpad software/hardware really that difficult that it’s a veritable mote for Apple laptops?

              1.  

                Agreed. I really want to use Linux, and I don’t mind grinding through all of the little bugs and quirks to get it to behave properly with whatever hardware I happen to have; however, there’s just no way to get anywhere close to Mac quality trackpad support or at least I haven’t found it in the last ~15 years. Certainly I can’t recommend it to anyone less technical.

                I recently switched back to a Macbook, my first in 10 years or so. I’ve been using Linux/*BSD for 15 or so years, including many as a primary machine. I try to think of MacOS like a wierd Linux distro that limits what I can do and run, yet runs photoshop/lightroom reliably which is a must for me. Oh it runs Emacs as well!

                I haven’t pushed the hardware much yet, but it’s snappy and all that. My previous laptop had 4 GB of RAM so even 8 GB is such an improvement in itself. I typically use it for PS/LR, ssh:ing, writing Ansible and scripting. It’s not as amazing as I thought, but it never gets in the way or start swapping like my old machine :-)

              2.  

                Completely agree. I switched to an Air a few months after rocking the ThinkPad/Linux combo for many years. Im sad to say, the Macbook just is a better all round package.

              1. 7

                As usual, the touchpad (which Apple calls “trackpad”) is great, much better than any touchpad I have ever used on a PC laptop

                Here we go again…

                There is nothing special about the hardware (well, Apple is an early adopter of force-sensitive pads, but current Synaptics devices are force-sensitive too). Nothing magic about macOS either. It’s just usually compared against bad software. Windows 10 with any HID-multitouch touchpad feels pretty much the same as macOS. On the unix side, other than ensuring you’re not using anything legacy stuff (xf86-input-synaptics lol), you might need this patch to make scrolling look totally smooth in GTK apps (“might” because it already looks fine if the touchpad’s event rate is high enough, e.g. I never noticed any jitter with a 125Hz touchpad + 60Hz display).

                1. 29

                  Honestly, I think you’re wrong. There’s nothing magical, but macOS is just so much more reliable than any trackpad I’ve used, and I’ve used trackpads across a relatively wide range of high-end non-Mac laptops. The mac is, for example, the only laptop line I’ve used which always, with 100% accuracy, detects a two finger click as a right click, regardless of how sloppy I am. All other laptops will sometimes just emit a left click rather than a right click if, say, my fingers aren’t horizontal enough or are too close. Also, Wayland currently has a horrible bug where touchpad scrolling is 1.5x faster than it should’ve been (https://gitlab.gnome.org/GNOME/mutter/-/issues/1731). Scrolling in Linux is also universally much more jittery than in macOS (yes, even with libinput drivers), where the screen will jump around a bit when I hold my fingers still. Macs are also the only systems I’ve used where a one-finger tap is registered instantly; there’s always at least what feels like a few hundred milliseconds of delay in Linux with libinput.

                  There’s a lot to like about non-Mac hardware. But I still haven’t found any non-Mac laptops with a decent touch pad, even in the Mac’s price range. I don’t know if it’s a hardware thing or a software thing; I’m guessing it’s a combination.

                  And maybe my experience isn’t representative. Maybe every non-Mac laptop I have ever laid my hands on in my life have just been especially bad. I don’t think so though.

                  1. 9

                    a few hundred milliseconds

                    Simply no way. I’ve used Linux on the most random laptops since 2013 and have never noticed input latency this high and I used to play rhythm games with Synaptics touchpads.

                    1. 5

                      I might be exaggerating, I don’t know. All I know is that it doesn’t feel instant, and the number I hear people throw around as the delay that’s required for something to feel “instant” is 100ms, which puts my best guess somewhere above 100ms. Though you do adjust to it, and I didn’t really understand that there’s a delay before I used a Mac trackpad again and it felt unnaturally fast.

                      Do note that I’m talking about tapping, not clicking. Clicking is always fast in my experience. And again, maybe there are differences in hardware here. But this one really feels like a software thing, and everyone’s using libinput these days.

                      1. 3

                        The latency is there, you just got used to it. Linux is pretty bad, unless you’re using the PREEMPT_RT patches.

                        You can easily measure how bad it is by running cyclictest from rt-test, with SMP enabled and SCHED_FIFO policy. It will set alarms and then measure the difference between the requested time and the time it runs at.

                        Minimum is irrelevant, average has some limited value, max is the column you want to look at. Unit is µs.

                        With mainline kernel, you’ll see max cross into ms range in a matter of minutes, if not seconds. Leaving it running (its cpu usage is low) for a day or two, you’ll see max get into tens of milliseconds.

                        linux-rt patchset does help, but only for scheduler latency. The userspace Linux input stack is another layer of bad.

                        Latency is something that needs to be a core design target. Like security, it cannot be tacked in.

                        To put things in perspective, AmigaOS (1985) input.device task ran with priority 20, making it the highest priority task in the system, which is realtime with hard priorities; if a higher priority task becomes runnable, it will run immediately.

                    2. 2

                      (“might” because it already looks fine if the touchpad’s event rate is high enough, e.g. I never noticed any jitter with a 125Hz touchpad + 60Hz display)

                      So it sounds like there ARE hardware differences? I don’t know whether it’s hardware or software, but every time I use a Windows machine (and I’m talking about higher end Dell XPS laptops, mostly) I end up frustrated with the janky touchpad behavior. For example, the scrolling speed is always wonky and the device doesn’t pick up my two-finger scroll gesture until I’ve moved my fingers almost a centimeter.

                      1. 3

                        Agreed. I’ve used a lot of PCs with both Windows and Linux, and I’ve tried everything I could find to get the touchpads calibrated optimally and they never came close to a Mac, much to my frustration. That said, even Linux running on a Mac doesn’t have good trackpad options, so I don’t doubt that much of the problem is in software–but that’s not much of a consolation so long as “the right software” doesn’t exist for Linux.

                        1. 1

                          Funnily enough the author of the gtk patch was using an external Apple Magic Trackpad 2 which is 90Hz. Basically no one has noticed any jitter in gtk’s naive processing with internal trackpads :)

                          doesn’t pick up my two-finger scroll gesture

                          Windows probably has the highest thresholds for scroll recognition, though they shouldn’t be that big. Also, what applications are you testing with? I’ve heard that Windows does some weird delay with legacy apps that only support basic mouse scrolling. Something like modern browsers, which do use touchpad native panning APIs, shouldn’t be affected by that.

                          1. 2

                            When I find myself on a Windows device, I’m almost always using Chrome. Now that I’m thinking about it, though, I wonder if part of my frustration with trackpads on Windows is the (lack of) inertial scrolling. I’m accustomed to being able to kind of “flick” the trackpad lightly to scroll down a bit while I’m reading something, etc. Windows seems to stubbornly assume that I’m using a wheel mouse.

                            1. 2

                              Even with drivers and software that attempt to make scrolling ‘smooth’, it’s never anything like on MacOS, where it’s not that it’s just ‘smooth’, it’s that you scroll to where you expected. It’s almost like it’s been tuned to perfectly match expectations - and scroll there smoothly and so fast it never feels like it’s lagging behind. Connected to your fingers.

                              I’d liken it to riding a lightweight road bike with higher end components. You move your body and the bike moves with you. You don’t feel like you’re dragging the bike along.

                              1. 1

                                Chrome was developing the proper support for all this like 4 years ago so it’s definitely in the production release by now. Are you actually testing “precision touchpad” (HID-multitouch) devices?

                                1. 2

                                  I have no idea what the hardware is, like I said, the machines I’ve used are new and new-ish Dell XPS laptops. My point isn’t that you can’t get a good experience on Windows, it’s that I haven’t gotten a good experience on Windows, even with $2500 laptops (equivalent in price to a Mac).

                          2. 1

                            There is nothing special about . . .

                            I’ve always likened Mac vs. non-Mac trackpads to driving an e.g. BMW 335i vs. a Chevrolet truck. It’s just a more precise and overall nicer user experience.

                            1. 1

                              It could also be familiarity. Different vendors and OSs have different acceleration mappings. People who are used to macs use a not Mac and it feels wrong, and they tell everyone it’s bad. People who are used to windows or linear have the same experience. It’s like how my grandma’s cookies are just better than yours’s. I can’t explain it, and I don’t need to, it’s just true, and my whole family thinks so too. If you disagree you must be confused or misguided.

                              Also, are the pads literally force sensitive? I’ve found putting my palm on it registers as more “force” than pushing hard on it, but my laptop is 7 years old and not apple.

                              1. 1

                                putting my palm on it registers as more “force” than pushing hard on it

                                That means it’s not force sensitive, which makes sense for a 7-year-old not-Apple. On the non-Apple side, as I said, only the very latest Synaptics generation is force sensitive.

                                1. 1

                                  Ok that makes sense, cause the one I have was billed as I think “pressure sensitive” or something weaseley like that. I’m not exactly a close follower of new laptop tech, historically I’ve only gotten new ones when the current one breaks. TBF I’m pretty impressed with how long this one has lasted.

                            1. 18

                              Having been in and since “passed out” of the PHP ecosystem (and admittedly, the last version I used was now 7.2), I found that my biggest productivity and quality of life issues with PHP lie in an area which is difficult to reform - its standard library.

                              PHP has a very nice documentation of it’s standard library - and that’s great, because you need to consult it frequently. There’s so much power there, but a lot of it is hard to wield.

                              • Everything exists in the ‘prelude’. There’s no real organisation or filtering of the functions the runtime provides except for extensions, which are at least compartmentalised in the documentation, but still exist in one flat namespace. PHP does have namespaces, but they are really provided for the sake of user defined code and the runtime makes little (no?) use of them.

                              • There’s a real usability issue which has arisen from the through-line of the original PHP language, which represented almost a shell script over C libraries, to the modern language, which means that the built-in functions tend to very closely resemble C counterparts in a way that often doesn’t make much sense or feels unwieldy, which has a few knock-on effects:

                                • PHP has a system for “reference variables” which basically makes them permanently pass-by-reference when passed to functions; this is an inherent property of the binding and (as of 7.2 at least) you can never remove this property from a binding, and you can never tell if a variable is a reference or not. It seems this was largely implemented to mimic how C achieves mutating and returning non-trivial values, but it’s not always clear that careful thought went into whether other mechanisms in PHP are more suited.

                                • Finding or remembering functions you want for common operations can be difficult because they use the difficult to interrogate names of their C peers (particularly for strings), and not just ones like strftime which at least will be familiar from a few other languages - strtr, strstr, strpbrk, ftell, may be unfamiliar and unintuitive even if you are a trained programmer coming from another language.

                                • The requirements of binding native functions mean that pre-7.0, these functions were the only place where typing enforcement would pop up, which is part of the reason that so many sites with poor configuration would spew massive amounts of PHP warnings.

                              • The additions that PHP has made in these areas over the years have many consistency issues in the design and conventions of the functions (inconsistent ordering of items and collections in the arguments to collection operations, inconsistent use of _ to break up function names, mixing ‘2’ and ‘to’, having a separate camelCase naming convention for object methods)

                              1. 5

                                It’s been more than a decade since I last dabbled with PHP and your criticisms match my memory. I wonder why they don’t add proper modules/namespaces to the standard library while leaving the old APIs in place for compatibility reasons. Push the new APIs as the way forward via culture and linters (using old APIs is a lint error and maybe eventually a glaring deprecation warning in the runtime).

                                1. 3

                                  It’s going to happen for 8.1, albeit slowly.

                              1. 3

                                This is super cool! I spent a few months building something similar (in Go, using Starlark). I would get hung up on bootstrapping various low-level dependencies and eventually gave up. I’m excited to check this out and maybe contribute. :)

                                1. 3

                                  No way! Yeah, navigating bootstrapping dependencies was (and continues to be) very tough. I would stop working on the project at times solely because of how intimidated I was about getting some random build working. Imagine it will get easier, but I feel you. And yes please check it out and contribute :)

                                1. 1

                                  This is exciting! The biggest thing that has put me off Go so far has been the lack of generics. (I remember the days before generics made it into Java and I’m not too eager to re-live that experience)

                                  I understand the rationale for not including generics from the start, but as far as I can tell it leads to a lot of boilerplate and unsafe code. Especially in a language with good support for first-class functions, not having generics always felt like a missed opportunity.

                                  1. 6

                                    I’ve been writing Go professionally for a few years now, and lack of generics doesn’t result in “unsafe” code, at least not in the Go sense of memory-unsafe. It can result in runtime type assertion failures if interface{} types are used and converted at runtime. It can also result in boilerplate, with repeated (type safe) functions like ContainsInt and ContainsString instead of Contains[T] for slices. However, that happens less often than you’d think, as (unlike early Java), the built-in slice and map types are “generic” already (parameterized by type) … you just can’t add user-defined generic types or functions. This gets most people surprisingly far.

                                    That said, I’m cautiously optimistic about generics. They seem to be taking a typically Go-like caution with the features, not overhauling the language or stdlib with the introduction of generics. Still, I suspect there will be a raft of new “functional programming” libraries and other such things at first which won’t really fit in the Go spirit. Then hopefully it’ll settle down.

                                    1. 3

                                      I hope they don’t take too long with introducing the genetics to the standard lib. They risk a number of third party solutions filling the void. Best case, it will be like Apache commons. Worst case, like perl OOP. (I guess rust async frameworks are somewhere in between)

                                      1. 2

                                        it’s not entirely clear where you want generics to go in the standard library. the only real place i can think of is the sort library, and last thing i knew that was already being worked on. the go standard library isn’t filled with collections types or whatever like rust or c++. there really are only one or two files in the entire standard library where generics even could be added, much less would be useful. there’s a reason they hadn’t been added yet, and it’s because you don’t need them 99.9% of the time if you’re programming in go idiomatically, which the standard library generally does.

                                        my biggest fear with the introduction of generics is what is articulated in the parent of your comment, which is that everyone starts burying all of their code in a thousand layers of generic gibberish. the last thing anyone should want is for go to turn into c++. the fact of the matter is that at the moment if you find yourself “needing” generics in your go project, you’re probably doing something wrong, and you’ll either need to restructure your project in a better way, or, in the very few cases when you can’t do that (because you actually do need generics) you may have to hack around it. when the introduction of generics goes mainstream, you won’t ever have to hack around their absence when you really need them, but that doesn’t mean you shouldn’t refactor around their unnecessary inclusion. more often than not, reflexive use of generics is a matter of premature optimization, which your code (particularly in go) will be far better off without.

                                        i think a lot of people have this mistaken impression that all the philosophical “a bit of copying is better than a bit of dependency” etc etc stuff in the go community arose as some sort of coping mechanism for the lack of several important features. the opposite is true in reality: these “missing features” were deliberately left out for the purpose of incentivizing what the language’s developers believed to be a better style of programming. whether the costs incurred are worth the benefits is up for debate. at the very least it appears to be widely understood that some annoyances arise from that, particularly boilerplate, and that’s where generics and the various error handling proposals that aren’t set in stone yet have come from.

                                        here’s what that doesn’t mean:

                                        • best practices have meaningfully changed
                                        • every function needs type parameters
                                        • every file needs type parameters
                                        • every project needs type parameters

                                        if go as an experiment has taught us anything at all it’s that in the vast majority of cases you absolutely can go without all of these things we’ve convinced ourselves we need. if you find yourself thinking you need to use generics for a particular problem, the fact that you now can should not make you any less apt to pause and consider whether there really isn’t any other way to model the solution to your problem.

                                    2. 1

                                      I will say that Java’s solution to everything was inheritance + downcasting in the days before generics, and I think people mistakenly put all of the inheritance unpleasantness of inheritance into generics when thinking of the bad old days of Java. Go locks generics and that’s not great, but it still feels a whole lot better than Java 1.0. Notable Go also has type inference, first class functions, and structural subtyping which contribute a lot to the overall experience relative to Java 1.0.

                                      1. 1

                                        I’m mostly leery of generics, because I worry that it will lead to code which is hard to follow and reason about.

                                      1. 8

                                        I’m not exactly sure what the special sauce is here but vanilla .NET supports creating single static binaries just like Go does.

                                        Here is an example in a project of mine though of the fsproj settings and the actual command invoked to get a static binary:

                                        https://github.com/eatonphil/dbcore/blob/master/dbcore.fsproj

                                        https://github.com/eatonphil/dbcore/blob/master/Makefile#L10

                                        I assume it’s a static binary because I could copy the binary alone to a VM without .NET on it and still run the binary.

                                        1. 4

                                          Even without the native compilation, I’m quite enjoying targeting the .net frameworks included in windows by default. If your users are on win10 and update at least once a year, you can publish your winforms app for .net framework 4.6 and it will “just run”. Ilmerge can get rid of extra DLLs too. Simple, single file GUI apps start <100KB.

                                          1. 2

                                            The problem is the frameworks, while conceptually simple deployment wise, are effectively EoL due to .NET Core/Standard. (The terminology was never clear; the incoherent story is why is the biggest reason I lost interest in .NET. I’d likely stick with Framework, because it’s basically not going to go full CADT like the rest of the ecosystem has.)

                                            1. 6

                                              The problem is the frameworks, while conceptually simple deployment wise, are effectively EoL due to .NET Core/Standard. (The terminology was never clear; the incoherent story is why is the biggest reason I lost interest in .NET

                                              The literal names are absolutely abysmal, granted, but their meanings have always been consistent:

                                              • .NET Standard is a standard set of APIs. It’s not an implementation. Mono, .NET Core, .NET Framework, UWP, and (I think, for the last couple of years or so) Unity are all implementations of .NET Standard.
                                              • .NET Framework is the version of .NET that ships as part of Windows. It is basically running in the old COM/ActiveX style, where all the .NET objects and runtime ship as part of the OS proper.
                                              • .NET Core is new implementation of .NET, separate from .NET Framework, that focuses on shipping static binaries and running on multiple platforms. It also aims to be a viable alternative for .NET Framework even when running on Windows, though the support cycle of .NET Framework means it’s not going anywhere soon.
                                              1. 2

                                                CADT?

                                                1. 5

                                                  Had to look it up, but it’s Cascade of Attention-Deficit Teenagers.

                                                  1. 3

                                                    are effectively EoL due to .NET Core/Standard.

                                                    That’s not true. .NET Framework is a Windows component and thus is supported as long as the OS is.

                                                    https://dotnet.microsoft.com/platform/support/policy/dotnet-framework

                                                  2. 1

                                                    Unless I’m mis-understanding something here, this says you mightn’t be right about this :)

                                              1. 26

                                                The article treats Go and Rust as on equal footing when it comes to safety. This is quite wrong, unless “safety” refers only to memory safety: Rust is far safer than Go in general, for a number of reasons: algebraic data types with exhaustive pattern matching, the borrow checker for statically preventing data races, the ability to use RAII-like patterns to free resources automatically when they go out of scope, better type safety due to generics, etc.

                                                Of course, both languages are safer than using a dynamically typed language. So from the perspective of a Python programmer, it makes sense to think of Go as a safer alternative.

                                                There may be certain dimensions along which it makes sense to prefer Go over Rust, such as the learning curve, the convenience of a garbage collector, etc. But it’s important to be honest about each language’s strengths and weaknesses.

                                                1. 22

                                                  On the other hand, if you do think about memory safety, it’s not quite so clear cut. In Go, I can create a cyclic data structure without using the Unsafe package and the GC will correctly collect it for me. In Rust, I have to write custom unsafe code to both create it and clean it up. In Go I can create a DAG and the GC will correctly clean it up. In Rust, I must use unsafe (or a standard-library crate such as RC that uses unsafe internally) to create it, and clean it up.

                                                  However, in Go I can create an object with a slice field and share it between two goroutines and then have one write update it in a loop with a small slice and a large slice and the other goroutine read until it sees the base of the small slice and the length of the large slice. I now have a slice whose bounds are larger than the underlying object and I can violate all of the memory-safety invariants without writing a single line of code using the Unsafe package. In Rust, I could not do this without incorrectly implementing the Sync trait, and you cannot implement the Sync trait without unsafe code.

                                                  Go loses its memory safety guarantees if you write concurrent software. Rust loses its memory safety guarantees if you use non-trivial data structures. C++ loses its memory safety guarantees if you use pointers (or references).

                                                  1. 12

                                                    Go loses its memory safety guarantees if you write concurrent software. Rust loses its memory safety guarantees if you use non-trivial data structures. C++ loses its memory safety guarantees if you use pointers (or references).

                                                    This is fantastically succinct. Thanks, I might use this myself ;)

                                                    1. 6

                                                      In Rust, I have to write custom unsafe code to both create it and clean it up

                                                      No, you really don’t.

                                                      You can create it with no unsafe code (outside of the standard library) and no extra tracking by using Box::leak, it will just never be cleaned up.

                                                      You can create it with no unsafe code (outside of the standard library) and reference counted pointers by using Rc::new for forward pointers and Rc::downgrade for back pointers, and it will be automatically cleaned up (at the expense of adding reference counting).

                                                      You can make use of various GC and GC like schemes with no unsafe code (outside of well known libraries), the most famous of which is probably crossbeam::epoch.

                                                      You can make use of various arena datastructures to do so with no unsafe code (outside of well known libraries), provided that that form of “GC all at once at the end” fits your use case, e.g. typed arena.

                                                      1. 3

                                                        You can create it with no unsafe code (outside of the standard library)

                                                        The parenthetical here is the key part. The standard library implementations for all of the things that you describe all use unsafe.

                                                        1. 6

                                                          No, it isn’t. That’s how the entire language works, encapsulate and abstract unsafe things until they are safe. To argue otherwise is to argue that every allocation is bad, because implementing an allocator requires unsafe (and the standard library uses unsafe to do so)…

                                                          Unsafe code is not viral.

                                                          1. 1

                                                            Note also that the Rust Standard library has special dispensation for unsafe and unstable features – it can assume a particular compiler version, it can use unsafe code that would be unsound without special knowledge of the compiler, and it can compel the compiler to change in order to support what the stdlib wants to do.

                                                      2. 13

                                                        Of course, both languages are safer than using a dynamically typed language.

                                                        I wish people would stop saying that. Especially with “of course”. We can believe all we want, but there is no data supporting the idea that dynamically typed languages are inherently less safe. Again, I don’t care why you think it should be the case. First show me that it actually is, then try to hypothesize as to why.

                                                        1. 21

                                                          I often find production bugs in dynamically typed systems I work on which are due to issues that would be caught be a type checker for a modern type system (e.g., null reference errors, not handling a case of an algebraic data type when a new one is added, not handling new types of errors as the failure modes evolve over time, etc.). That’s an existence proof that having a type checker would have helped with safety. And this is in a codebase with hundreds of thousands of tests and a strict code review policy with code coverage requirements, so it wouldn’t be reasonable to attribute this to an insufficient test suite.

                                                          Very large companies are migrating their JavaScript codebases to TypeScript precisely because they want the safety of static types. Having been privy to some of those discussions, I can assure you there were made with a lot of consideration due to the enormous cost of doing so.

                                                          Going down the academic route, dependent types let you prove things that tests cannot guarantee, such as the fact that list concatenation is associative for all inputs. I personally have used Coq to prove the absence of bugs in various algorithms. As Dijkstra said, “program testing can be used to show the presence of bugs, but never to show their absence”. Types, on the other hand, actually can show the absence of bugs if you go deep enough down the rabbit hole (and know how to formally express your correctness criteria).

                                                          You don’t have to believe me, and perhaps you shouldn’t since I haven’t given you any specific numbers. There are plenty of studies, if you care to look (for example, “A Large Scale Study of Programming Languages and Code Quality in Github; Ray, B; Posnett, D; Filkov, V; Devanbu, P”). But at the same time, there are studies that claim the opposite, so for this topic I trust my personal experience more than the kind of data you’re looking for.

                                                          1. 2

                                                            Yet Go lacks many of those features, such as algebraic data types, exhaustive switches, and has both nil and default values.

                                                            1. 3

                                                              Yes, hence my original claim that Rust is far safer than Go. But Go still does have a rudimentary type system, which at least enforces a basic sense of well-formedness on programs (function arguments being the right type, references to variables/functions/fields are not typos, etc.) that might otherwise go undetected without static type checking. Since these particular types of bugs are also fairly easy to catch with tests, and since Go programs often rely on unsafe dynamic type casting (e.g., due to lack of generics), Go is not much safer than a dynamically typed language—in stark contrast to Rust. I think one could reasonably argue that Go’s type system provides negligible benefit over dynamic typing (though I might not go quite that far), but I do not consider it reasonable to claim that static types in general are not capable of adding value, based on my experience with dependent types and more sophisticated type systems in general.

                                                              1. 2

                                                                Since these particular types of bugs are also fairly easy to catch with tests, and since Go programs often rely on unsafe dynamic type casting (e.g., due to lack of generics), Go is not much safer than a dynamically typed language—in stark contrast to Rust.

                                                                But only <1% of Go code is dynamically typed, so why would you argue that it’s not much safer than a language in which 100% of code is dynamically typed? Would you equally argue that because some small amount of Rust code uses unsafe that Rust is no safer than C? These seem like pretty silly arguments to make.

                                                                In my experience writing Go and Rust (and a whole lot of Python and other languages), Go hits a sweet spot–you have significant type safety beyond which returns diminish quickly (with respect to safety, anyway). I like Rust, but I think your claims are wildly overstated.

                                                            2. 2

                                                              so for this topic I trust my personal experience more than the kind of data you’re looking for.

                                                              I wonder how much of this is us as individual programmers falling into Simpson’s Paradox. My intuition says that for large, complex systems that change infrequently, static typing is a huge boon. But that’s only some portion of the total programs being written. Scientific programmers write code that’s more about transmitting mathematical/scientific knowledge and easily changeable for experimentation. Game scripters are looking for simple on-ramps for them to change game logic. I suspect the “intuitive answer” here highly depends on the class of applications that a programmer finds themselves working on. I do think there’s an aspect of personality here, where some folks who enjoy abstraction-heavy thinking will gravitate more toward static typing and folks who enjoy more “nuts-and-bolts” thinking may gravitate toward dynamic typing. Though newer languages like Nim and Julia are really blurring the line between dynamic and static.

                                                              1. 2

                                                                Have you done Coq to prove the correctness of anything that wasn’t easy by inspection? I’ve looked at it and I’m definitely interested in the ideas (I’m working through a textbook in my spare time), but I’ve never used it to prove anything more complicated than, say, linked list concatenation or reversing.

                                                                And how do you generate the program from your code? Do you use the built-in extraction, or something else?

                                                                1. 2

                                                                  I often find production bugs in dynamically typed systems I work on that are due to things that would be caught be a type checker

                                                                  I can offer an equally useless anecdotal evidence of my own practice where bugs that would be caught by a type checked happen at a rate of about 1/50 to those caused by mis-shapen data, misunderstanding of domain complexity and plain poor testing, and when they do, they’re usually trivial to detect and fix. The only thing that tells me is that software development is complex and we are far from making sweeping statements that start from “of course”.

                                                                  Very large companies are migrating their JavaScript code bases to TypeScript for exactly for that reason.

                                                                  Sorry, the “thousand lemmings” defense won’t work here. Out whole industry has been investing countless engineer-years in OO abstractions, but then people started doing things without it and it turned out OO wasn’t the requirement for building working systems. Software development is prone to fads and over-estimations.

                                                                  Types, on the other hand, actually can show the absence of bugs

                                                                  That’s just plain wrong. Unless you mean some very specific field of software where you can write a formal specification for a program, but to this day it’s just not practical for anything that’s useful.

                                                                  1. 5

                                                                    It’s clear that many people find value in static types even if you don’t. Maybe you make fewer mistakes than the rest of us, or maybe you’re working in a domain where types don’t add as much value compared to others. But you shouldn’t try to invalidate other people’s experiences of benefitting from static types.

                                                                    they’re usually trivial to detect and fix

                                                                    I prefer to eliminate entire categories of errors without having to detect and fix them down the line when they’ve already impacted a user.

                                                                    That’s just plain wrong.

                                                                    Maybe you haven’t used formal verification before, but that doesn’t mean it isn’t used in the real world. There’s a great book series on this topic if you are interested in having a more open mind. I’ve used these kind of techniques to implement parts of a compiler that are guaranteed correct. Amazon also uses deductive techniques in multiple AWS teams (example), and there’s a decent chance you have indirectly benefitted from some of those efforts. So, my claim is not “just plain wrong”. As you alluded to, it usually doesn’t make sense to invest that much in those kinds of formal guarantees, but it’s nice that types can do that for you when you need them to.

                                                                    At this point, it seems like you aren’t interested in having a good faith discussion, with your abrasive comments like “I don’t care why you think it should be the case”, “equally useless anecdotal evidence”, and dismissing a demonstrable claim as “just plain wrong”. I think you have some good points (e.g., I completely agree about your position on OO) and could be more effective at delivering them if you didn’t seem so invested in discounting other people’s experiences.

                                                                    I respect your opinion that I should not have stated that Rust and Go are “of course” safer than dynamically typed languages. In particular, Go’s type system is so underpowered that I can see a reasonable argument that the ceremony of appeasing it without reaping the guarantees that a better type system would give makes it more difficult to build robust software than not having types at all. I certainly wouldn’t say the same for Rust, though. Rust often forces me to handle error cases that I didn’t even know were possible and would never think to test.

                                                                    1. 1

                                                                      But you shouldn’t try to invalidate other people’s experiences of benefitting from static types.

                                                                      Go’s type system is so underpowered that I can see a reasonable argument that the ceremony of appeasing it without reaping the guarantees that a better type system would give makes it more difficult to build robust software than not having types at all.

                                                                      Do you not think this is invalidating the experience of Go users who benefit from usage of the language?

                                                                      1. 1

                                                                        I said I could see it as a reasonable argument, not that I personally agree with it. I’m trying to give some validity to what isagalaev is saying and potentially meet them in the middle by acknowledging that not all type systems provide a clear benefit over dynamic typing. But I already stated my stance in my original top-level comment: that Go’s type system is still better than no type system when it comes to safety (not memory safety, but a more broad notion of safety).

                                                                        It is true, though, that Go’s type system is quite weak compared to other type systems. That’s not the same as saying that people don’t benefit from it. On the contrary, I’ve claimed the opposite—which is what started this whole discussion in the first place.

                                                                      2. 1

                                                                        abrasive comments

                                                                        Apologies on that, fwiw.

                                                                      3. 2

                                                                        […] caused by mis-shapen data, […]

                                                                        Statements like these always make me suspect the author doesn’t appreciate just how much can in fact be captured by even a relatively simple type system. “Make illegal states unrepresentable” has become something of a mantra in the Elm community in particular, and I can’t remember the last time I saw a bug in a typed FP language that was due to “mis-shappen data” get past the type checker.

                                                                        I think there’s a tendency to try to compare languages by lifting code wholesale from one language into the other, assuming it would be written more or less the same way, which is often not the case. So, if you see a something that throws TypeError, of course you assume that would get caught by a static type system. Folks who have only worked with type systems like those in Java/Go/C generally look at null/nil bugs and assume that those wouldn’t get caught, even though they’re impossible in other systems. It’s easy to point out “null isn’t a thing in this language,” but what’s a bit harder to capture is that a lot of things that aren’t obviously type errors that crop up at runtime in a dynamically typed language would likely be captured by types in a program writing with the benefit of a modern type system. Obviously it won’t if you just write a stringly-typed program, but… don’t do that, use your tools.

                                                                        1. 1

                                                                          “Make illegal states unrepresentable” has become something of a mantra in the Elm community in particular, and I can’t remember the last time I saw a bug in a typed FP language that was due to “mis-shappen data” get past the type checker.

                                                                          It’s not about illegal states. I mean code expecting a response from an HTTP call in a particular schema and getting a different one. I don’t see how this problem can be prevented at compile time. Or more subtly, getting data in a correct shape (say, an ISO-formatted time string), successfully parsing it (into an internal datetime type), but then producing the result that the user doesn’t expect because it assumes the time to be in a different time zone.

                                                                          (Also, I don’t see how making illegal states unrepresentable is in any way endemic to type-checked languages. It’s just a good architectural pattern valid everywhere.)

                                                                          1. 1

                                                                            I mean code expecting a response from an HTTP call in a particular schema and getting a different one.

                                                                            Ah, you are talking about something somewhat different then. Yes, obviously types can’t statically prove that inputs that come in at runtime will be well-formed. However, they can force you to deal with the case of a parse failure – which many languages make it really easy to forget. “Forgetting a case” is another one of those things that I think people often incorrectly assume aren’t (or can’t easily be made) type errors. It’s hard to say what you should do in that case without more context, but it makes it hard to introduce a bug by omission.

                                                                            If the bug is just that the programmer was mistaken about what the endpoint’s schema was (or the server operator changed it inappropriately), I’ll agree that just having static types in your client program does not really help that much, though it might be a bit easier to track down since the error will occur right at the point of parsing, rather than some time later when somebody tries to use the value.

                                                                            That said, I’ll point to stuff like protobuf, capnproto, and even swagger as things that are trying to bridge this gap to some degree – there is still an opportunity to just assign the entirely wrong schema to an endpoint, but they narrow the space over which that can happen substantially; once you’ve got the right schema rigged up the programmer is unlikely to get the shape of the data wrong, as that’s just defined in the schema.

                                                                            Or more subtly, getting data in a correct shape (say, an ISO-formatted time string), successfully parsing it (into an internal datetime type), but then producing the result that the user doesn’t expect because it assumes the time to be in a different time zone.

                                                                            Dealing with fiddly distinctions like this is something types are really great at. I have some good points of comparison with date/time stuff, as I’ve worked on projects where this stuff is core to the business logic in both Python and Haskell. Having a type system for it in Haskell has been a godsend, and I wish I’d had one available when doing the prior project.

                                                                            Somewhat simplified for presentation (but with the essentials in-tact), the Haskell codebase has some types:

                                                                            • A date & time with an attached (possibly arbitrary) time zone, “ZonedDateTime”
                                                                            • A date & time in “local time,” where the timezone is implied by context somehow. “LocalDateTime”

                                                                            As an example of where this is useful: the code that renders the user’s feed of events in order expects a list of LocalDateTime values, so if you try to pass it the datetime with some arbitrary timezone, you’ll get a type error. Instead, there’s a function timeInZone which takes a ZonedDateTime and a TimeZone, and translates it to a LocalDateTime with the provided timezone implied. So in order to get an event into a users feed, you need to run it through this conversion function, or it won’t type check.

                                                                            (Also, I don’t see how making illegal states unrepresentable is in any way endemic to type-checked languages. It’s just a good architectural pattern valid everywhere.)

                                                                            It’s a lot easier to do it when you can actually dictate what the possible values of something are; if in the event of a bug a variable could have any arbitrary value, then your options for enforcing invariants on the data are much more limited. You can put asserts everywhere, but having static types is much much nicer.

                                                                    2. 6

                                                                      Also, people talk about “dynamic languages” like they’re all the same, while they are often as different as C and Rust, if not more.

                                                                      Writing safe Javascript is an impossible nightmare..

                                                                      Writing safe Python is easy and fun. I do think it would be safer with a good type-system, but at the same time, a shorter and more idiomatic code (where you don’t have to fight with the compiler) brings its own sort of safety and comfort.

                                                                      1. 4

                                                                        Writing safe Python is easy and fun.

                                                                        Python has its own share of footguns, such as passing strings somewhere where bytes are expected, or new, unhandled exceptions being added to libraries you’re calling.

                                                                        Mypy doesn’t completely protect you. IME, many errors occur at the seams of typed/untyped contexts. Which is not surprising, but it is a downside of an after-the-fact, optional type checker.

                                                                        1. 1

                                                                          Yeah, and mypy has far less coverage for third-party packages than TypeScript. IME when I use TS I’m surprised if I don’t find a type package, whereas with mypy I’m surprised if I do.

                                                                          1. 1

                                                                            About one in twenty times I do see a types package in DefinitelyTyped which is very incorrect. Almost always only with libraries with small user bases.

                                                                            1. 1

                                                                              Incorrect as in “this parameter is a number but is typed as a string”, or too loose/too restrictive?

                                                                              1. 1

                                                                                Varies. I’ve seen symbols typed as strings, core functionality missing, functions that couldn’t be called without “as any”.

                                                                          2. 1

                                                                            Python isn’t perfect, but unhandled exceptions can happen in C++ too..

                                                                            It doesn’t have to be after the fact. You can check types at run-time, and there are libraries that will help you with that. It comes at a slight performance cost, of course (but if that matters, why are you using Python?), but then you gain the ability to implement much more sophisticated checks, like contracts, or dependent types.

                                                                            Anyway, at least personally, type errors are rarely the real challenge when writing software.

                                                                        2. 3

                                                                          there is no data supporting the idea that dynamically typed languages are inherently less safe

                                                                          If we use the Gary’s Types document for the definition of a dynamically typed language, I am able to find some research:

                                                                          I do agree that this amount of research is far away from us being able to say “of course”.

                                                                          1. 3

                                                                            Not gonna take a position here on the actual static vs dynamic debate, but the second paper you linked is deeply flawed. I wrote a bit about the paper, and the drama around it, here: https://www.hillelwayne.com/post/this-is-how-science-happens/

                                                                            1. 1

                                                                              Awesome! Thank you for sharing.

                                                                          2. 2

                                                                            I think it stands to reason that statically typed languages are safer than dynamically typed languages. I’m vaguely aware of some studies from <2005 that compared C++ to Python or some such and found no significant difference in bugs, but I can’t imagine those findings would hold for modern mainstream statically typed languages (perhaps not even C++>=11). Personally I have extensive experience with a wide array of languages and my experience suggests that static typing is unambiguously better than dynamic typing; I hear the same thing from so many other people and indeed even the Python maintainers–including GVR himself–are compelled. Experience aside, it also stands to reason that languages in which entire classes of errors are impossible would have fewer errors in total.

                                                                            So while perhaps there isn’t conclusive data one way or the other, experience and reason seem to suggest that one is better than the other.

                                                                            1. 1

                                                                              Experience aside, it also stands to reason that languages in which entire classes of errors are impossible would have fewer errors in total.

                                                                              What this (very common) argument is missing is that a) those errors are not as frequent as the words “entire classes of errors” may lead to believe, that b) testing covers many of those errors better (by testing for correct values you’re getting correct types for free), and that c) instrumenting your code with types isn’t free, you get bloated and more rigid code that may lead to more serious errors in modeling your problem domain.

                                                                              1. 4

                                                                                I’ve personally found that relying on a decent type system makes my code more flexible, as in easier to refactor, because I can rely on the type system to enforce that all changes are valid.

                                                                                1. 1

                                                                                  I’ve developed and operated Python services in production for about a decade. Type errors were the most common kind of errors we would encounter by a wide margin. We were very diligent about writing tests, but inevitably we would miss cases. Some of these were “this function is literally just an entry point that unmarshals JSON and passes it into a library function… I don’t need a test” but they would forget to await the library function.

                                                                                  Moreover, how do you reconcile “annotating your code takes too much time and makes your code too inflexible, but writing tests is good value for money”? Am I misunderstanding your argument? Note also that tests are useful for lots of other things, like documentation, optimizations, refactoring, IDE autocomplete, etc.

                                                                                  1. 1

                                                                                    Moreover, how do you reconcile “annotating your code takes too much time and makes your code too inflexible, but writing tests is good value for money”?

                                                                                    Types are not a replacement for tests, you have to write tests anyway. And they are good value for money, which is one of the few things we actually know about software development. So the proposition I’m making is that if you write good tests they should cover everything a type checker would. Because, essentially, if you check all your values are correct then it necessarily implies that types of those values are correct too (or at least, they work in the same way).

                                                                                    Now, to your point about “but inevitably we would miss cases” — I’m very much aware of this problem. I blame the fact that people write tests in horribly complicated ways, get burnt out, never achieve full test coverage and then turn to type checking to have at least some basic guarantees for the code that’s not covered. I’m not happy with this, I wish people would write better tests.

                                                                                    You example with a test for a trivial end point is very telling in this regard. If it’s trivial, then writing a test for it should also be trivial too, so why not?

                                                                                    1. 1

                                                                                      I disagree. In my extensive experience with Python and Go (15 and 10 years, respectively), Go’s type system grants me a lot more confidence even with a fraction of the tests of a Python code base. In other words, a type system absolutely is a replacement for a whole lot of tests.

                                                                                      I specifically disagree that checking for a value guarantees that the logic is correct (type systems aren’t about making sure the type of the value is correct, but that the logic for getting the value is sound).

                                                                                      While 100% test coverage would make me pretty confident in a code base, why burn out your engineers in pursuit of it when a test system would reduce the testing load significantly?

                                                                                      With respect to “trivial code thus trivial tests”, I think this is untrue. Writing “await foo(bar, baz)” is trivial. Figuring out how to test that is still cognitively burdensome, and cognition aside it’s many times the boilerplate.

                                                                                      Lastly, people rarely discuss how static type systems make it harder to write certain kinds of bad code than dynamic type systems. For example, a function whose return type varies depending on the value of some parameter. The typical response from dynamic typing enthusiasts is that this is just bad code and bad Go code exists too, which is true but these kinds of bad code basically can’t exist in idiomatic Go code and they are absolutely pedestrian in Python and JavaScript.

                                                                                      At a certain point, you just have to get a lot of experience working with both systems in order to realize that the difference is really quite stark (even just the amount of documentation you get out of the box from type annotations, and the assurance that that documentation is correct and up to date).

                                                                                      1. 1

                                                                                        I specifically disagree that checking for a value guarantees that the logic is correct

                                                                                        I didn’t say anything about the whole logic. I said if your values are correct then it necessarily implies your types are correct. Specifically, if you have a test that does:

                                                                                        config = parse_config(filename)
                                                                                        assert config['key'] == 'value'
                                                                                        

                                                                                        Then it means that parse_config got a correct value in filename that it could use to open and parse the config file. In which case it also means filename was of correct type: a string, or a Path or whatever the language’s stdlib could use in open(). That’s it, nothing philosophical here.

                                                                                        While 100% test coverage would make me pretty confident in a code base, why burn out your engineers in pursuit of it

                                                                                        Let me reiterate: if achieving 100% test coverage feels like a burn-out, you’re doing it wrong. It’s actually not even hard, especially in a dynamic language where you don’t have to dependency-inject everything. I’m not just fantasizing here, that’s what I did in my last three or four code bases whenever I was able to sell people on the idea. There’s this whole ethos of it being somehow impossibly hard which in many applications just doesn’t hold up.

                                                                                        1. 1

                                                                                          Some more :-)

                                                                                          Writing “await foo(bar, baz)” is trivial. Figuring out how to test that is still cognitively burdensome, and cognition aside it’s many times the boilerplate.

                                                                                          Huh? The tooling is out there, you don’t have to invent anything: https://pypi.org/project/pytest-asyncio/

                                                                                          @pytest.mark.asyncio
                                                                                          async def test_some_asyncio_code():
                                                                                              res = await library.do_something()
                                                                                              assert b'expected result' == res
                                                                                          

                                                                                          At a certain point, you just have to get a lot of experience working with both systems in order to realize that the difference is really quite stark

                                                                                          Just to clarify here, I mostly work in Python, but I also work extensively in JavaScript, TypeScript, Kotlin and Rust (much less in the latter than I would like). And my experience tells me that types is not the most significant feature that makes a language safe (for whatever value of “safe”). It is also subjective. I do absolutely trust you that you find working in Go more comfortable, but it’s important to understand that the feeling doesn’t have to be universal. I would hate to have to program in Go, even though it’s a simple language.

                                                                                2. 1

                                                                                  Genuine question: how could it be shown? You would need at least two projects of similar scope, in similar areas, written by programmers of similar skill (which is hard to evaluate on its own) and similar level of understanding of the problem area (which means that rewrites of the same code base can’t count), differing only in their choice of static/dynamic typing. How could such a research be possible?

                                                                                  More generally: is there any solid research about which languages are better? Is there any data that programs written is the assembly language are more or less error-prone than those written in Python? This should be intuitively obvious, but is there data? I tried to find anything at all, but only discovered half-baked “studies” that don’t control for either the programmer experience or the complexity of the problem area.

                                                                                  My point is, how can we do better than a bunch of anecdotes here?

                                                                                  1. 3

                                                                                    Right, I think one can admit that, as a field, we’re not in amazing shape epistemologically, but we are still left having to actually make decisions in our day to day, so not having opinions isn’t really an option – we’re stuck going on experience and anecdote, but that’s not quite the same as having no information. It’d be nice to have conclusive studies. Unfortunately, all I’ve got is a career’s worth of anecdata.

                                                                                    I have no idea how to study this kind of thing.

                                                                                    1. 3

                                                                                      Yep, this was exactly my point: when someone asks for studies that conclusively show that X is better than Y in this context, I think that they are asking for too much and people are justified in saying “of course” even in the abscence of rock-solid evidence.

                                                                                    2. 2

                                                                                      I would go so far as to argue that, often, when people insist on data for something like this, they are actually being disingenuous. If you insist on (quantitative) data when you know that none exist or are likely to exist in the future, then you are actually just saying that you want to unquestioningly maintain the status quo.

                                                                                      1. 2

                                                                                        I would go so far as to argue that, often, when people insist on data for something like this, they are actually being disingenuous.

                                                                                        … Why would it be disingenuous to ask for data? This just sounds absurd. Moreover there really isn’t consensus around this topic. Take a look at Static v. dynamic languages literature review, this has been an ongoing topic of discussion and there still isn’t a conclusion either way. Regardless this perspective frightens me. It sounds a lot like “I have an opinion and data is hard so I’m going to call you disingenuous for disagreeing with me.” This isn’t the way to make good decisions or to tolerate nuanced opinions.

                                                                                        “The problem with any ideology is it gives the answer before you look at the the evidence. So you have to mold the evidence to get the answer you’ve already decided you’ve got to have.” – Bill Clinton

                                                                                        1. 2

                                                                                          Why would it be disingenuous to ask for data?

                                                                                          It isn’t, and I didn’t say that it was.

                                                                                          I said it was potentially disingenuous to insist on (quantitative) data as a prerequisite for having a discussion. If good data don’t exist, then refusing to talk about something until good data do exist is just another way of defending whatever the status quo is. What it basically says is that regardless of how we made the current decision (presumably without data, since data don’t exist), the decision cannot be changed without data.

                                                                                          I’m honestly not sure how you came up with that interpretation based on what I wrote. I didn’t even say which side of the issue I was on.

                                                                                          Edit: you can also substitute “inconclusive data” for “no data”.

                                                                                          1. 2

                                                                                            I’m honestly not sure how you came up with that interpretation based on what I wrote. I didn’t even say which side of the issue I was on.

                                                                                            I think this is a difference between our interpretations on “insist”. I tend to read “insist” as an earnest suggestion, not a hard prerequisite, so that’s where my my disagreement came from. I didn’t mean to imply anything about which side you were on since that’s immaterial to my point really. I agree that categorically refusing to discuss without sufficient data is a bit irresponsible since in real life humans are often forced to make decisions without appropriate evidence.

                                                                                            If good data don’t exist, then refusing to talk about something until good data do exist is just another way of defending whatever the status quo is.

                                                                                            My thinking here is, at what point does this become a useless thought exercise? Static typing isn’t new and is gaining ground in several languages. There’s already a “programmer personality” identity based around static typing and “healthy” Twitter communities of folks who bemoan static or dynamic languages. At some point, the programming community at large gains nothing by having more talking heads philosophizing about where and why they see bugs. You can take a cursory search on the internet and see folks advocating for pretty much any point on the spectrum of this debate. To me this discussion (not this Lobsters thread, but the greater discussion as a whole) seems to have reached the point where it’s useless to proceed without data because there’s no consensus around which point on the spectrum of static/dynamic does actually lead to fewer (if any point does at all) bugs. And if more philosophizing doesn’t help us arrive at a conclusion, it really boils down to the same thing: your personal feelings and experiences, in which case the discussion is more of a form of socializing than a form of actual discussion. In other words, without data, this discussion trends more toward bikeshedding than actually answering the question under discussion.

                                                                                            1. 2

                                                                                              In other words, without data, this discussion trends more toward bikeshedding than actually answering the question under discussion.

                                                                                              That’s fair. I agree that this particular topic has been pretty well discussed to death.

                                                                                              1. 1

                                                                                                there’s no consensus around which point on the spectrum of static/dynamic does actually lead to fewer (if any point does at all) bugs

                                                                                                I think consensus is emerging slowly—static languages seem to have grown more popular in the last decade to the extent that many JavaScript developers are converting to TypeScript, Python developers are embracing Mypy, most (all?) of the most popular new languages of the last 10-15 years have been statically typed (the Go community in particular seems to consist of a lot of former Python and Ruby devs), etc. On the other hand, I scarcely if ever hear about people switching to dynamically typed languages (once upon a time this was common, when the popular static offerings were C, C++, and Java). It’s possible that this emerging consensus is just a fad, but things do seem to be converging.

                                                                                            2. 1

                                                                                              I suspect the problem is that this question is enormously multivariate (skill of developers, development methodology, testing effort to find bugs, different language features, readability of the language, etc).

                                                                                              It’s entirely likely that we have been studying this for a long time and yet the variable space is so large that we’ve hardly scratched it at all. And then some people come along and interpret this lack of conclusive data as “well, static and dynamic must be roughly equal” which seems strictly more périlleuse than formulating one’s own opinion based on extensive experience with both type systems.

                                                                                              I don’t think your Clinton quote applies because we’re talking about forming an opinion based on “a career’s worth of anecdata”, not letting an ideology influence one’s opinion. Everyone admits that anecdata is not as nice as conclusive empirical data, but we don’t have any of the latter and we have lots of the former and it seems to point in a single direction. In this case the ideological take would be someone who forms an opinion based on lack of evidence and lack of subjective experience with both systems.

                                                                                          2. 1

                                                                                            Genuine question: how could it be shown? You would need at least two projects of similar scope, in similar areas, written by programmers of similar skill (which is hard to evaluate on its own) and similar level of understanding of the problem area (which means that rewrites of the same code base can’t count), differing only in their choice of static/dynamic typing. How could such a research be possible?

                                                                                            Remember that “project scope”, “project area” (systems, web, database, etc), “license status” (GPLv3, proprietary, etc) are all dimensions for a project that can be recorded and analyzed. There is a rich literature of statistical methods to compensate for certain dimensions being over or underrepresented, and for compensating for incomplete data. If we can come up with a metric for being error-prone (which is difficult, so perhaps we need multiple metrics (NB: Code complexity metrics are a good look here to look at the challenges)), and we can faithfully record other dimensions of projects, we can try to rigorously answer this question. The big barriers here usually involve data siloing (proprietary projects rarely share relevant data about their projects) and just manpower (how many developers, especially of open source projects, really have the time to also gather stats about their contributors and their bugs when they can barely hold together the project itself in their generous free time, or can get approval in a proprietary project).

                                                                                            That said there’s this stubborn “philosopher-programmer” culture in programming circles that doesn’t seem particularly interested in epistemological work which also often muddles the conversation, especially if the topic under discussion has a lot of strong opinions and zealotry involved.

                                                                                            1. 1

                                                                                              The short answer is, I don’t know. I had some ideas though. Like an experiment where you solicit a public participation from a bunch of people to write from scratch something not complicated, and yet not trivial. Like, I don’t know, a simple working chat client for an existing reference server implementation. You don’t impose any restriction: people could work in any language, use libraries, etc. Time capped by, say, a couple of weeks. And then you independently verify the results and determine defects of any sort. And then you look at correlations: does number of defects correlate with dynamic/static nature? Programmer’s experience? Programmer’s experience with a language? Amount of active working hours? Something else?

                                                                                              My hypothesis is that we can’t actually evaluate a language in a vacuum. Instead a language+programmer is a actually an atomic unit of evaluation. Like in auto racing you can’t say which driver is the best (although it’s people’s favorite pastime), you can only talk about a driver in a particular car driving on particular tracks.

                                                                                              1. 2

                                                                                                There is a 1994 paper called “Haskell vs. Ada vs. C++ an Experiment in Software Prototyping Productivity” which doesn’t touch on static vs dynamic typing, but, I think, follows about the same format as what you’re proposing, right? That paper is widely disliked due to its methodological problems. An example of its discussion: https://news.ycombinator.com/item?id=14267882

                                                                                            2. 1

                                                                                              We can believe all we want, but there is no data supporting the idea that dynamically typed languages are inherently less safe

                                                                                              I think that some people tend to use the term “safe” to mean both “memory-safe” and “bug-resistant”, whereas others would use the term “safe” to refer to “memory-safe” only.

                                                                                              I can quite believe that applications written in dynamically-typed languages might be vulnerable to a whole class of bugs that aren’t present in their statically-typed equivalents because, unless you’re very careful, type coercion can silently get you in ways you don’t expect. You could write an entire book on the many mysterious ways of the JavaScript type system, for example.

                                                                                              That said, these aren’t really bugs that make the program unsafe if you’re talking about memory safety. It’s not terribly likely that these sorts of bugs are going to allow unsafe memory accesses or cause buffer overflows or anything of the sort.

                                                                                              1. 2

                                                                                                applications written in dynamically-typed languages might be vulnerable to a whole class of bugs [ … ] , type coercion can silently get you in ways you don’t expect.

                                                                                                Dynamic languages is not just JavaScript. For example Python and Clojure don’t do type coercion, nor do they silently swallow access to non-existing names and attributes.

                                                                                            3. 4

                                                                                              Of course, both languages are safer than using a dynamically typed language. So from the perspective of a Python programmer, it makes sense to think of Go as a safer alternative.

                                                                                              Returns also diminish. Using Go rather than Python will probably reduce type errors by 95% while Rust would reduce them by 99%. And that additional 4% of type errors may not be worth the hit to productivity (yes, I assert that Go is quite a lot more productive than Rust for most applications, even though I am a fan of both languages). Note also that these are just type errors; there are lots of errors which neither Rust nor Go can protect against.

                                                                                              1. 5

                                                                                                there are lots of errors which neither Rust nor Go can protect against.

                                                                                                “How does your language handle null references?”

                                                                                                Prohibited by the type system at compile time.

                                                                                                “Nice, nice. What about out-of-bounds array accesses?”

                                                                                                Sometimes detectable even at compile time and at any rate detected and safely handled at runtime.

                                                                                                “Wonderful. So obviously then if your allocator reports that you’ve run out of memory…”

                                                                                                Instant, unrecoverable crash, yes.

                                                                                                1. 2

                                                                                                  I’m not sure how that relates to my “there are lots of errors which neither Rust nor Go can protect against.” statement that you’re quoting. Yes, those are categories of errors that Rust protects against and Go does not, but there are still lots of other errors that neither language protect against.

                                                                                                  1. 1

                                                                                                    My point is that one of the errors that neither protect you against is out-of-memory errors, which has always baffled me. Rust doesn’t even panic (which could be recovered), but aborts.

                                                                                                    OOM is much more often treated as a situation where it’s seemingly okay to absolutely crash compared to other resource-exhaustion situations (nobody would be like “oh the disk is full, let’s just crash and not even attempt to let the programmer deal with it”).

                                                                                                    1. 2

                                                                                                      I don’t know the rationale for this in Rust, but I’m aware that there’s been some discussion of this in the C++ standards committee. Gracefully handling out-of-memory conditions sounds really useful, but there are two problems:

                                                                                                      • In several decades of the C++ specification defining exception behaviour for operator new exhausting memory and longer for C defining malloc as returning NULL when allocation fails, there are no examples of large-scale systems outside of the embedded / kernel space that gracefully handle memory exhaustion in all places where it can occur. Kernels generally don’t use the standard may-fail APIs and instead use two kinds of allocations, those that may block and those that may fail, with the vast majority of uses being the ones that can block.
                                                                                                      • Most *NIX systems deterministically report errors if you exhaust your address space (which is not easy on a 64-bit system) but don’t fail on out-of-memory conditions at the allocation point. They will happily report that they’ve allocated memory but then fault when you try to write to it.

                                                                                                      If you do get an out-of-memory condition, what do you do? If you’re disciplined and writing a very low-level system, then you do all of your allocation up-front and report failure before you’ve tried any processing. For anything in userspace, you typically need to do a load of cleanup, which may itself trigger allocation.

                                                                                                      In general, the set of things for which it is possible to gracefully handle allocation failure are so distinct from everyday programming that it’s difficult to provide a generic mechanism that works for both. This is what malloc(3) and malloc(9) are such different APIs.

                                                                                                      1. 2

                                                                                                        Part of the trouble is that in most languages, it’s really hard to actually do much of anything without further allocation. Especially in languages where allocation can happen implicitly, this really does seem like an “above the program’s pay grade” kind of thing.

                                                                                                        That said, Rust is decidedly not one of those languages; this is an API design choice, and it has indeed often felt like an odd one to me.

                                                                                              1. 6

                                                                                                I wish this included some explanation of why these are useful or explanations of why they are. Like, why use zerolog over logrus/zap/whatever? Why use gorilla/mux over gin or go-chi or the standard library? Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                                1. 4

                                                                                                  I’m not the author of the post, but I can try to answer some questions:

                                                                                                  Like, why use zerolog over logrus/zap/whatever?

                                                                                                  zerolog and zap is what the author of logrus admit he would write if he wrote logrus/v2. zerolog claims to be a “better” version of zap (there are claims of performance improvement on other people’s computers)

                                                                                                  Why use gorilla/mux over gin or go-chi or the standard library?

                                                                                                  gorilla/mux is much lightweight as opposed to gin which has renderers, etc… Also, there are claims of very high performance on other people’s computers. With gorlla/mux you can plug your own json de-/serialization library which is faster than gin’s.

                                                                                                  Why have that overly-complex unique code thing to determine where a logged error is thrown instead of making sure your errors have stack traces?

                                                                                                  ¯\(ツ)/¯ No idea… The unique code approach feels very hacky and brittle to me.

                                                                                                  1. 3

                                                                                                    I would even suggest “httprouter” as a more lightweight alternative to gorilla/mux.

                                                                                                    1. 2

                                                                                                      Most “higher level” Go routers are probably based on it anyways.

                                                                                                    2. 1

                                                                                                      We use unique logging codes for our logs, and it makes it easier to locate a particular statement in either the logs, or the source code. Now, we generate the unique code by hand, but it’s not a horrendous issue for us (we have a separate document that records each logging statement).

                                                                                                    3. 1

                                                                                                      I’d be curious to know the best practices for annotating errors with stack traces. Any good library suggestions?

                                                                                                      1. 3

                                                                                                        github.com/pkg/errors has some nice helpers, as described in its documentation. The issue is that it requires changing your code to using errors.Errorf() instead of fmt.Errorf().

                                                                                                        Go2 will do it differently, but natively

                                                                                                        1. 3

                                                                                                          Also, errors.Wrapf is very useful when handling errors from packages which don’t use errors.

                                                                                                          1. 2

                                                                                                            You can wrap errors using fmt.Errorf() and the %w verb, and then later deal with them using errors.Is() or errors.As() and friends.

                                                                                                            1. 1

                                                                                                              That doesn’t give you stack traces though, correct?

                                                                                                          2. 2

                                                                                                            YES. This is probably my biggest issue with supporting production Go code. Errors are still too hard to locate.

                                                                                                            1. 1

                                                                                                              I personally use this to manage all that. If you use the errors.Wrap() function to wrap errors, it’ll add stack traces. And if you want to make a new error, the errors.New() function will also add a stack track where it was called. Then when you’re logging the error make sure it’s being logged in a way that will not just print the message. Most loggers should have a way to do that (I know zerolog and logrus do).

                                                                                                              1. 1

                                                                                                                Shameless plug for my errors library: https://pkg.go.dev/github.com/zeebo/errs/v2

                                                                                                                • captures stack traces, but only once even if wrapped multiple times
                                                                                                                • plays nicely with standard library errors package with errors.Is and errors.As
                                                                                                                • has a “tag” feature to let you associate and query tags with errors
                                                                                                                • helper to keep track of groups of errors
                                                                                                            1. 15

                                                                                                              I think the key insight here is that container images (the article confuses images and containers, a common mistake that pedants like me will rush to point out) are very similar to statically linked binaries. So why Docker/container images and why not ELF or other statically linked formats?

                                                                                                              I think the main answer is that container images have a native notion of a filesystem, so it’s “trivial” (relatively speaking) to put the whole user space into a single image, which means that we can package virtually the entire universe of Linux user space software with a single static format whereas that is much harder (impossible?) with ELF.

                                                                                                              1. 4

                                                                                                                And we were able to do that with virtualization for at least 5 - 10 years prior Docker. Or you think that packaging also the kernel is too much?

                                                                                                                Anyways, I do not think that a container having the notion of a filesystem is the killer feature of Docker. I think that moving the deployment code (installing a library for example) close to compilation of the code helped many people and organizations who did not have the right tooling prior that. For larger companies who had systems engineers cgroups gave the security part mostly because packaging was solved decades prior to Docker.

                                                                                                                1. 1

                                                                                                                  IMO it’s not the kernel but all of the supporting software that needs to be configured for VMs but which comes for ~free with container orchestration (process management, log exfiltration, monitoring, sshd, infrastructure-as-code, etc).

                                                                                                                  Anyways, I do not think that a container having the notion of a filesystem is the killer feature of Docker. I think that moving the deployment code (installing a library for example) close to compilation of the code helped many people and organizations who did not have the right tooling prior that.

                                                                                                                  How do you get that property without filesystem semantics? You can do that with toolchains that produce statically linked binaries, but many toolchains don’t support that and of those that do, many important projects don’t take advantage.

                                                                                                                  Filesystem semantics enable almost any application to be packaged relatively easily in the same format which means orchestration tools like Kubernetes become more tenable for one’s entire stack.

                                                                                                                2. 4

                                                                                                                  I can fit a jvm in a container! And then not worry about installing the right jvm in prod.

                                                                                                                  I used to be a skeptic. I’ve been sold.

                                                                                                                  1. 2

                                                                                                                    Slightly off topic - but JVM inside a container becomes really interesting with resource limits. Who should be in charge of limits, JVM runtime or container runtime?

                                                                                                                    1. 7

                                                                                                                      Gotta be the container runtime (or the kernel or hypervisor above it) because the JVM heap size limit is best-effort. Bugs in memory accounting could cause the process to use memory beyond the heap limit. Absent that, native APIs (JNI) can directly call malloc and allocate off-heap.

                                                                                                                      Would still make sense for the container runtime to tell the JVM & application what the limits on it currently are so it can tailor its own behaviour to try to fit inside them.

                                                                                                                      1. 4

                                                                                                                        It’s easy: the enclosing layer gets the limits. Who should set the resource limits? ext4 or the iron platter it’s on?

                                                                                                                        1. 2

                                                                                                                          What’s the enclosing layer? What happens when you have heterogenous infrastructure? Legacy applications moving to cloud? Maybe in theory it’s easy, but in practice much tougher.

                                                                                                                        2. 2

                                                                                                                          Increasingly the JVM is setting its own constraints to match the operating environment when “inside a container”.

                                                                                                                      2. 4

                                                                                                                        Yes, layers as filesystem snapshots enable a more expressive packaging solution than statically linked alternatives. But its not just filesystems, but also runtime configuration (variables through ENV, invocation through CMD) that makes the format even more expressive.

                                                                                                                        p.s. I have also updated the post to say “container images”

                                                                                                                        1. 3

                                                                                                                          I think the abstraction on images is a bit leaky. With docker you’re basically forced to give it a name into a system registry, so that you can then run the image as a container.

                                                                                                                          I would love to be able to say like… “build this image as this file, then spin up a container using this image” without the intermediate steps of tagging (why? because it allows for building workflows that don’t care about your current Docker state). I know you can just kinda namespace stuff but it really bugs me!

                                                                                                                          1. 3

                                                                                                                            Good practice is addressing images by their digest instead of a tag using the @ syntax. But I agree - registry has always been a weird part of the workflow.

                                                                                                                            1. 1

                                                                                                                              addressing images by their digest instead of a tag using the @ syntax.

                                                                                                                              Be careful about that. The digest of images can change as you push/pull them between different registries. The problem may have settled out, but we were bitten by changes across different releases of software in Docker’s registry image and across the Docker registry and Artifactory’s.

                                                                                                                              I’m not sure if there’s a formal standard for how that digest is calculated, but certainly used to be (~2 years back) be very unreliable.

                                                                                                                              1. 1

                                                                                                                                Oh I wasn’t aware of that! That could let me at least get most of the way to what I want to do, thanks for the pointer!

                                                                                                                            2. 3

                                                                                                                              I noticed Go now has support for, in its essentially static binary, including a virtual filesystem instantiated from a filesystem tree specified during compilation. In that scenario, it further occurs to me that containerization isn’t perhaps necessary, thereby exposing read only shared memory pages to the OS across multiple processes running the same binary.

                                                                                                                              I don’t know in the containerization model if the underlying/orchestrating OS can identify identical read only memory pages and exploit sharing.

                                                                                                                              1. 2

                                                                                                                                I think in the long term containers won’t be necessary, but today there’s a whole lot of software and language ecosystems that don’t support static binaries (and especially not virtual filesystems) at all and there’s a lot of value in having a common package type that all kinds of tooling can work with.

                                                                                                                                1. 2

                                                                                                                                  As a packaging mechanism, in theory embedded files in Go works ok (follows single process pattern). In practice, most Go binary container images are empty (FROM scratch + certs) anyways. Lots of files that are environment dependent that you would want at runtime (secrets, environment variables, networking) that are much easier to declaratively add to a container image vs. recompile.

                                                                                                                                2. 2

                                                                                                                                  So why Docker/container images and why not ELF or other statically linked formats?

                                                                                                                                  There are things like gVisor and binctr that work this way, as do somethings like Emscripten (for JS/WASM)

                                                                                                                                  1. 2

                                                                                                                                    I really hope for WASI to pick up here. I used to be a big fan of CloudABI, which now links to WASI.

                                                                                                                                    It would be nice if we could get rid of all the container (well actually mostly Docker) cruft.

                                                                                                                                1. 26

                                                                                                                                  These are all valid criticisms of certain patterns in software engineering, but I wouldn’t really say they’re about OOP.

                                                                                                                                  This paper goes into some of the distinctions of OOP and ADTs, but the summary is basically this:

                                                                                                                                  • ADTs allow complex functions that operate on many data abstractions – so the Player.hits(Monster) example might be rewritten in ADT-style as hit(Player, Monster[, Weapon]).
                                                                                                                                  • Objects, on the other hand, allow interface-based polymorphism – so you might have some kind of interface Character { position: Coordinates, hp: int, name: String }, which Player and Monster both implement.

                                                                                                                                  Now, interface-based polymorphism is an interesting thing to think about and criticise in its own right. It requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries. But the critique of OOP presented in the OP is nothing to do with interfaces or polymorphism.

                                                                                                                                  The author just dislikes using classes to hold data, but a class that doesn’t implement an interface is basically the same as an ADT. And yet one of the first recommendations in the article is to design your data structures well up-front!

                                                                                                                                  1. 15

                                                                                                                                    The main problem I have with these “X is dead” type article is they are almost always straw man arguments setup in a way to prove a point. The other issue I have is the definition or interpretation of OOP is so varied that I don’t think you can in good faith just say OOP as a whole is bad and be at all clear to the reader. As an industry I actually think we need to get past these self constructed camps of OOP vs Functional because to me they are disingenuous and the truth, as it always does, lies in the middle.

                                                                                                                                    Personally, coming mainly from a Ruby/Rails environment, use ActiveRecord/Class to almost exclusively encapsulate data and abstract the interaction with the database transformations and then move logic into a place where it really only cares about data in and data out. Is that OOP or Functional? I would argue a combination of both and I think the power lies in the middle not one versus the other as most articles stipulate. But a middle ground approach doesnt get the clicks i guess so here we are

                                                                                                                                    1. 4

                                                                                                                                      the definition or interpretation of OOP is so varied that I don’t think you can in good faith just say OOP as a whole is bad and be at all clear to the reader

                                                                                                                                      Wholly agreed.

                                                                                                                                      The main problem I have with these “X is dead” type article is they are almost always straw man arguments setup in a way to prove a point.

                                                                                                                                      For a term that evokes such strong emotions, it really is poorly defined (as you observed). Are these straw man arguments, or is the author responding to a set of pro-OOP arguments which don’t represent the pro-OOP arguments with which you’re familiar?

                                                                                                                                      Just like these criticisms of OOP feel like straw men to you, I imagine all of the “but that’s not real OOP!” responses that follow any criticism of OOP must feel a lot like disingenuous No-True-Scotsman arguments to critics of OOP.

                                                                                                                                      Personally, I’m a critic, and the only way I know how to navigate the “not true OOP” dodges is to ask what features distinguish OOP from other paradigms in the opinion of the OOP proponent and then debate whether that feature really is unique to OOP or whether it’s pervasive in other paradigms as well and once in a while a feature will actually pass through that filter such that we can debate its merits (e.g., inheritance).

                                                                                                                                      1. 4

                                                                                                                                        I imagine all of the “but that’s not real OOP!” responses that follow any criticism of OOP must feel a lot like disingenuous No-True-Scotsman arguments to critics of OOP.

                                                                                                                                        One thing I have observed about OOP is how protean it is: whenever there’s a good idea around, it absorbs it then pretend it is an inherent part of it. Then it deflects criticism by crying “strawman”, or, if we point out the shapes and animals that are taught for real in school, they’ll point out that “proper” OOP is hard, and provide little to no help in how to design an actual program.

                                                                                                                                        Here’s what I think: in its current form, OOP won’t last, same as previous form of OOP didn’t last. Just don’t be surprised if whatever follows ends up being called “OOP” as well.

                                                                                                                                    2. 8

                                                                                                                                      The model presented for monsters and players can itself be considered an OO design that misses the overarching problem in such domains. Here’s a well-reasoned, in-depth article on why it is folly. Part five has the riveting conclusion:

                                                                                                                                      Of course, your point isn’t about OOP-based RPGs, but how the article fails to critique OOP.

                                                                                                                                      After Alan Kay coined OOP, he realized, in retrospect, that the term would have been better as message-oriented programming. Too many people fixate on objects, rather than the messages passed betwixt. Recall that the inspiration for OOP was based upon how messages pass between biological cells. Put another way, when you move your finger: messages from the brain pass to the motor neurons, neurons release a chemical (a type of message), muscles receive those chemical impulses, then muscle fibers react, and so forth. At no point does any information about the brain’s state leak into other systems; your fingers know nothing about your brain, although they can pass messages back (e.g., pain signals).

                                                                                                                                      (This is the main reason why get and set accessors are often frowned upon: they break encapsulation, they break modularity, they leak data between components.)

                                                                                                                                      Many critique OOP, but few seem to study its origins and how—through nature-inspired modularity—it allowed systems to increase in complexity by an order of magnitude over its procedural programming predecessor. There are so many critiques of OOP that don’t pick apart actual message-oriented code that beats at the heart of OOP’s origins.

                                                                                                                                      1. 1

                                                                                                                                        Many critique OOP, but few seem to study its origins and how—through nature-inspired modularity—it allowed systems to increase in complexity by an order of magnitude over its procedural programming predecessor.

                                                                                                                                        Of note, modularity requires neither objects nor message passing!

                                                                                                                                        For example, the Modula programming language was procedural. Modula came out around the same time as Smalltalk, and introduced the concept of first-class modules (with the data hiding feature that Smalltalk objects had, except at the module level instead of the object level) that practically every modern programming language has adopted today - including both OO and non-OO languages.

                                                                                                                                      2. 5

                                                                                                                                        I have to say, after read the first few paragraphs, I skipped to ‘What to do Instead’. I am aware of many limitations of OOP and have no issue with the idea of learning something new so, hit me with it. Then the article is like ’hmm well datastores are nice. The end.”

                                                                                                                                        The irony is that I feel like I learned more from your comment than from the whole article so thanks for that. While reading the Player.hits(Monster) example I was hoping for the same example reformulated in a non-OOP way. No luck.

                                                                                                                                        If anyone has actual suggestions for how I could move away from OOP in a practical and achievable way within the areas of software I am active in (game prototypes, e.g. Godot or Unity, Windows desktop applications to pay the bills), I am certainly listening.

                                                                                                                                        1. 2

                                                                                                                                          If you haven’t already, I highly recommend watching Mike Acton’s 2014 talk on Data Oriented Design: https://youtu.be/rX0ItVEVjHc

                                                                                                                                          Rather than focusing on debunking OOP, it focuses on developing the ideal model for software development from first principles.

                                                                                                                                          1. 1

                                                                                                                                            Glad I was helpful! I’d really recommend reading the article I linked and summarised – it took me a few goes to get through it (and I had to skip a few sections), but it changed my thinking a lot.

                                                                                                                                          2. 3

                                                                                                                                            [interface-based polymorphism] requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries

                                                                                                                                            You needed to do dispatch anyway, though; if you wanted to treat players and monsters homogenously in some context and then discriminate, then you need to branch on the discriminant.

                                                                                                                                            Objects, on the other hand, allow interface-based polymorphism – so you might have some kind of interface […] which Player and Monster both implement

                                                                                                                                            Typeclasses are haskell’s answer to this; notably, while they do enable interface-based polymorphism, they do not natively admit inheritance or other (arguably—I will not touch these aspects of the present discussion) malaise aspects of OOP.

                                                                                                                                            1. 1

                                                                                                                                              You needed to do dispatch anyway, though; if you wanted to treat players and monsters homogenously in some context and then discriminate, then you need to branch on the discriminant.

                                                                                                                                              Yes, this is a good point. So it’s not like you’re saving any performance by doing the dispatch in ADT handling code rather than in a method polymorphism kind of way. I guess that still leaves the stylistic argument against polymorphism though.

                                                                                                                                            2. 2

                                                                                                                                              Just to emphasize your point on Cook’s paper, here is a juicy bit from the paper.

                                                                                                                                              Any time an object is passed as a value, or returned as a value, the object-oriented program is passing functions as values and returning functions as values. The fact that the functions are collected into records and called methods is irrelevant. As a result, the typical object-oriented program makes far more use of higher-order values than many functional programs.

                                                                                                                                              1. 2

                                                                                                                                                Now, interface-based polymorphism is an interesting thing to think about and criticise in its own right. It requires some kind of dynamic dispatch (or monomorphization), and hinders optimization across interface boundaries.

                                                                                                                                                After coming from java/python where essentially dynamic dispatch and methods go hand in hand I found go’s approach, which clearly differentiates between regular methods and interface methods, really opened my eyes to overuse of dynamic dispatch in designing OO apis. Extreme late binding is super cool and all… but so is static analysis and jump to definition.

                                                                                                                                              1. 14

                                                                                                                                                This is a really good writeup! Thanks @marin for taking your time to create it.

                                                                                                                                                Ada really seems to be an overlooked gem. Especially if you’re interested in Rust, you should definitely consider Ada for the same purposes (and more beyond that).

                                                                                                                                                Three very strong points are that Ada is standardized and, in my opinion, much more readable and that it has built-in concurrency. It’s much easier to do contract-based-programming and it’s overall a much more solid foundation to build you projects upon than Rust.

                                                                                                                                                Admittedly, Ada doesn’t have such a vocal “following” like Rust, but its usage alone in nuclear power plants, planes, etc. speaks volumes.

                                                                                                                                                1. 8

                                                                                                                                                  much more readable

                                                                                                                                                  That makes a lot of sense, since readability is an explicit design goal of Ada. (Ada Reference Manual, “Design Goals”) Readability is not a design goal of Rust.

                                                                                                                                                  1. 6

                                                                                                                                                    First, “much more readable” is very subjective. Second, yes, rust has more momentum outside of nuclear power plants, which means there’s a lot more crates for everyday programming (e.g. zstd bindings, an AWS client, etc.). Seems like more Ada crates are GPL (looking at “ada web server”) which also restricts the scope in which they can be used.

                                                                                                                                                    It’s fine to compare the technical merits (what’s that with the builtin concurrency btw?! Have you seen that rust’s stdlib has a bunch of things too?), but just saying that you can swap one for the other is a bit optimistic.

                                                                                                                                                    1. 4

                                                                                                                                                      First, “much more readable” is very subjective

                                                                                                                                                      Readability is very subjective. The argument (not trying to get into one) would probably be that Ada uses much less symbology (but 70+ keywords!) and also has a required principle called “linear elaboration of declarations”. This roughly means programs must be unambiguous when read from start to finish. There are mechanisms like limited with to help break circular references.

                                                                                                                                                      zstd bindings

                                                                                                                                                      True, but Alire is now at 1.0, and if it builds under GCC, GCC itself can generate Ada bindings for you.

                                                                                                                                                      It’s fine to compare the technical merits (what’s that with the builtin concurrency btw?!

                                                                                                                                                      Ada supports types with mutual exclusion (controlled types) and also one-shot and instantiable task types as part of the language itself, which support queueing (called entries, also look up rendezvous).

                                                                                                                                                      Have you seen that rust’s stdlib has a bunch of things too?

                                                                                                                                                      Rust has a very good stdlib. My point isn’t a denigration of Rust or any other language, or to be an Ada super fan, I’m going for as objective viewpoint and objective comparisons so people understand what it can do, since it doesn’t seem very well known.

                                                                                                                                                      1. 2

                                                                                                                                                        You’re not who I was replying to, but yes, these are good points. I’m also used to the linear order of declarations (as in OCaml), and it’s clear Alire is very young.

                                                                                                                                                        I’m curious to see what the future holds for Ada. There are things I find personally ugly (mostly that it’s not expression based), but hopefully it will eat some of the space C has held for a long time. I also wonder if someone could implement something like Ada’s rendez-vous in rust…

                                                                                                                                                    2. 5

                                                                                                                                                      much more solid foundation to build you projects upon than Rust

                                                                                                                                                      One of my favorite features of Rust is Cargo. I used Ada a decade ago, and I don’t recall anything similar. I certainly don’t recall such a wide universe of packages so easily accessible.

                                                                                                                                                      its usage alone in nuclear power plants, planes, etc. speaks volumes.

                                                                                                                                                      Does it? Wasn’t Ada mandated from on-high for use in these domains? How many nuclear power plants and aeroplanes were developed since Rust was conceived? Why would a language whose mainstay is mission-critical systems be appropriate for domains where iteration velocity is far more important than correctness? I’m not trying to shoot Ada down–I had a really fun time writing some microcontroller software with it, but these are the sort of baseline questions I’m interested in before seriously considering Ada for a project.

                                                                                                                                                      1. 2

                                                                                                                                                        I used Ada a decade ago, and I don’t recall anything similar.

                                                                                                                                                        There’s something called Alire which has reached 1.0 and is now available. There’s not much there, but there’s a lot of batteries included in the GNAT community install, so I haven’t needed to manually grab anything else yet.

                                                                                                                                                        Ada mandated from on-high for use in these domains

                                                                                                                                                        Ada comes from a time when defense contractors used over 100 languages and some didn’t even include basic support for basic things like “ensure the correct number of parameters are passed.” Imagine how untenable your current project would be if it included C, C++, C#, Rust, Haskell, Ocaml, Bash, Powershell, Lua, Python, Ruby, Tcl, Java, Clojure, Beanshell, Groovy, COBOL, ALGOL, etc.

                                                                                                                                                        How many nuclear power plants and aeroplanes were developed since Rust was conceived?

                                                                                                                                                        Ada offers things Rust doesn’t with regard to high-level controls and checks, like the Ravenscar profile, which makes the compiler ensure deterministic behavior of your program, which is super important to real-time systems.

                                                                                                                                                        Why would a language whose mainstay is mission-critical systems be appropriate for domains where iteration velocity is far more important than correctness?

                                                                                                                                                        Correctness works with iteration time because iterating on incorrect code is unwieldy and you end up carrying hard-to-fix bugs forward. I think you’re assuming correctness is bulky and heavyweight, which I haven’t found in Ada. In my experience, Ada iterates exceptionally well because of short compile times, better cohesion by using packages instead of types for subprogram (function/procedure) namespacing, and centralized checks which the compiler inserts via integrated design-by-contract and constraints on types. They have made it much faster to iterate on the project I’m working on, since I end up writing small cohesive modules with often automated checks in one place instead of rolling a lot of unit tests or distributing manual checks throughout my codebase which need to be modified on every major refactor.

                                                                                                                                                        1. 3

                                                                                                                                                          Ada comes from a time when defense contractors used over 100 languages and some didn’t even include basic support for basic things like “ensure the correct number of parameters are passed.” Imagine how untenable your current project would be if it included C, C++, C#, Rust, Haskell, Ocaml, Bash, Powershell, Lua, Python, Ruby, Tcl, Java, Clojure, Beanshell, Groovy, COBOL, ALGOL, etc.

                                                                                                                                                          I think this misses the point, which is that Ada didn’t out-compete other languages for these mission-critical domains; rather, it was mandated from on-high. So we can’t infer that Ada was simply a better fit. Notably, I believe once the mandate was lifted, much of the industry returned to C and C++. To be clear, I’m not advocating for C or C++ or even advocating against Ada. I just don’t buy the “Ada must be good because it’s used in domains in which its use was mandated” argument.

                                                                                                                                                          Ada offers things Rust doesn’t with regard to high-level controls and checks, like the Ravenscar profile, which makes the compiler ensure deterministic behavior of your program, which is super important to real-time systems.

                                                                                                                                                          Yeah, this seems pretty cool, absent more information.

                                                                                                                                                          Correctness works with iteration time because iterating on incorrect code is unwieldy and you end up carrying hard-to-fix bugs forward. I think you’re assuming correctness is bulky and heavyweight, which I haven’t found in Ada.

                                                                                                                                                          To be clear, I understand the “correctness and rapid iteration go hand-in-hand” theoretical argument, and it may even have been true in the days of waterfall, but I don’t think it’s true in the days of continuous deployment. Much of software development is done with languages that are nowhere near as rigorous as Rust or Ada, and if correctness were indeed so very profitable, I think we would see a lot more of these languages. It is interesting that you say that Ada is just as productive as other languages, and I’m sure one could be quite productive in Ada, but I reserve my skepticism about Ada’s application beyond mission-critical systems until I see a few well-known, successful SaaS projects in Ada.

                                                                                                                                                          To be fair, I’ve had (and to an extent, I still have) similar reservations about Rust, but while there aren’t many SaaS applications of Rust, it is featuring prominently in lots of important technology that is cloud-adjacent (SSL libraries, hypervisors, networking infrastructure, etc). Given its relative youth, that puts it on the right trajectory to become a mainstream application language in not a lot of time.

                                                                                                                                                          That said, I want to reiterate that I’m not anti-Ada; I would really like to see Ada as a mainstream language, throwing its hat in the ring with Rust and Go for high-level application development. I just can’t believe that it’s a good fit until I see some movement.

                                                                                                                                                    1. 4

                                                                                                                                                      But if we actually read what economists have to say on how hiring markets work, they do not, in general, claim that markets are perfectly efficient or that discrimination does not occur in markets that might colloquially be called highly competitive.

                                                                                                                                                      If the bar is perfection, then there is no limit to the number of “fixes” that will be proposed.

                                                                                                                                                      We can fix this, if we stop assuming the market will fix it for us.

                                                                                                                                                      By enacting more laws, or how exactly?

                                                                                                                                                      1. 7

                                                                                                                                                        If the bar is perfection, then there is no limit to the number of “fixes” that will be proposed.

                                                                                                                                                        I guess that’s true, and I guess a good thing. Or should we not always seek to improve?

                                                                                                                                                        1. 2

                                                                                                                                                          I agree with this, but I don’t think our rhetoric is sustainable. It’s far too toxic and divisive and progress demands cooperation; I think this toxicity and steamrolling to create change is creating a debt of divisiveness that will prevent us from progressing in the future. We need to figure out how to advocate for progress without being utterly hateful–people need to stop using “fighting injustice” as a cover for their personal vendettas against individuals and groups (political parties, races, genders, etc).

                                                                                                                                                          1. 4

                                                                                                                                                            We need to figure out how to advocate for progress without being utterly hateful–people need to stop using “fighting injustice” as a cover for their personal vendettas against individuals and groups (political parties, races, genders, etc).

                                                                                                                                                            Taking your comment at face value, it is a distortion of a hallucinatory magnitude to characterize socially progressive movements – which I assume you are referring to through the fog of plausible deniability – as “divisive”, “hateful”, and having a “personal vendetta” against groups defined by “race” and “gender”. Taking for example the movement for racial justice in the US, compare a near half millennium of violent racial oppression to the overwhelmingly peaceful forms of protest across the US, and ask yourself whose toxicity, divisiveness, and vendettas against groups should be considered worthy of your critique.

                                                                                                                                                            1. 3

                                                                                                                                                              I can’t disagree more strongly. The canonized authors of the movement publicly write things like “White identity is inherently racist” (note that this is a quote from DiAngelo’s best selling book) and talk about racism incurable in white people (whites are irredeemable) and kafka trap people (“white fragility”–if you denounce the term you’re only doing so because of your own white fragility, same with “internalized racism” if the objector is a minority) and otherwise go to remarkable lengths to support the primacy of race. They redefine “racism” such that white people simply participating innocuously in their own culture is inherently racist and consequently evil and not only that but colorblindness–literally the opposite of ‘racism’ as the term has historically been defined–is also racist. I don’t see how this can be anything other than hateful and divisive and racist (per the traditional definition).

                                                                                                                                                              (And for the “So what? Words change meaning” crowd, the significance is that the term isn’t the thing that carries the moral weight; it’s the meaning–as a society we agreed that racial prejudice and hate were evil–they are evil whether “racism” as a term refers to those things or their opposites. If someone inverts the meaning of the term–and I think this is a fair characterization–and then calls themselves “antiracist”, they are necessarily opposed to justice).

                                                                                                                                                              Taking for example the movement for racial justice in the US, compare a near half millennium of violent racial oppression to the overwhelmingly peaceful forms of protest across the US, and ask yourself whose toxicity, divisiveness, and vendettas against groups should be considered worthy of your critique.

                                                                                                                                                              I’m concerned about the parallels between the former and this new ideology (which condemns the very liberalism that so significantly reduced racial oppression in so short a time). Notably the primacy of race over the individual, the eagerness to regulate speech and thought, the propensity to celebrate or rationalize political violence, the promotion of segregationist policies, the newspeak rhetorical devises, and so on. Liberalism condemns the far left and the far right at once.

                                                                                                                                                              1. 2

                                                                                                                                                                The canonized authors of the movement publicly write things like “White identity is inherently racist” (note that this is a quote from DiAngelo’s best selling book) and talk about racism incurable in white people (whites are irredeemable) and kafka trap people (“white fragility”–if you denounce the term you’re only doing so because of your own white fragility, same with “internalized racism” if the objector is a minority) and otherwise go to remarkable lengths to support the primacy of race. They redefine “racism” such that white people simply participating innocuously in their own culture is inherently racist and consequently evil and not only that but colorblindness–literally the opposite of ‘racism’ as the term has historically been defined–is also racist. I don’t see how this can be anything other than hateful and divisive and racist (per the traditional definition).

                                                                                                                                                                You realize that works like these are written from a critical perspective, right? They’re intellectual and/or sociological analyses, not literal dictates.

                                                                                                                                                                1. 2

                                                                                                                                                                  They seem to be building a racial worldview that is seized upon en masse, so I take little comfort in their perspective or analytical nature.

                                                                                                                                                                2. 2

                                                                                                                                                                  If you’re interested books on racial justice, Angela Davis and Michelle Alexander are good places to start. Verso books publishes a lot of on this subject too. I think you’ll find many thinkers who are less concerned with what you may perceive as a certain moralizing political correctness, but rather more interested in understanding and dismantling systems of violent injustice. Think policing, jailing, housing, education. This is what I’ve referred to above vaguely as “the movement for racial justice”. Not to be dismissive, but books like “white fragility” are IMO more like beach reading for guilty white folks. Serves a purpose and may be a nice book, but I don’t think anyone would refer to it as “canon”.

                                                                                                                                                                  1. 2

                                                                                                                                                                    I think we’re exposed to different angles of this movement. I see a lot of people (white and black) boosting Kendi and DiAngelo and their ilk, but you’re the first who has recommended Davis or Alexander. I’ll have a look. I don’t think Kendi or DiAngelo are actually interested in “racial justice” in any meaningful way, but rather trying to advance an abstract theoretical framework (or perhaps an incoherent word salad that aspires to look like a framework) that indicts groups and individuals they don’t like irrespective of whether or not those people have anything to do with the disparate outcomes. I fully believe there are lots of genuine people involved in the movement, but the part of the movement that is being seized upon by the media and corporations seems to strictly be the critical race theory part (they recommend the same authors, use the same jargon, etc).

                                                                                                                                                                    1. 2

                                                                                                                                                                      trying to advance an abstract theoretical framework . . . that indicts groups and individuals . . . irrespective of whether or not those people have anything to do with the disparate outcomes

                                                                                                                                                                      But, like, this is entirely correct! Structural racism means people don’t have to actively do racist (little-r, micro scale) things to be part of a racist (big-r, macro scale) group.

                                                                                                                                                                      The conversation is about understanding this distinction and it’s effects so they can be corrected, to reduce suffering — not about amplifying the distinction so it can be weaponized, to increase suffering. I understand why you might think otherwise, but that conclusion requires believing the entire conversation is happening in bad faith, and there’s just no justifiable way to reach that conclusion, the evidence and Occam’s Razor don’t support it.

                                                                                                                                                                      1. 1

                                                                                                                                                                        Structural racism means people don’t have to actively do racist (little-r, micro scale) things to be part of a racist (big-r, macro scale) group.

                                                                                                                                                                        Then this definition of “racist” can’t carry any moral value, and anyone who assigns moral value to this definition is by definition a bigot and if the group in “part of a racist group” refers to a race then the person who assigns moral value to the term is precisely a racist in the original sense of the term—one who believes a person is guilty for no reason other than the color of their skin. This is hateful.

                                                                                                                                                                        1. 2

                                                                                                                                                                          I can’t help but be left with the overall impression that you’re trying to win a game of 7-dimensional chess which is suspended above our planet. I enjoyed introducing you to Davis and Alexander, and at this point I’d suggest that you pick up some of those books because there aren’t many other ways I think I can re-state the same point, one that @peterbourgon has also expressed, and which is hammered home in those works. I don’t mean to tell you what to think, but history makes the fact of systemic injustice pretty uncontroversial. It seems that rather than confront these systems, you’d prefer think of racism as a personal choice made by context-free actors. I don’t mean to shut down discussion, but I have said what I could and the information is out there for you to engage with if you choose to.

                                                                                                                                                              2. 4

                                                                                                                                                                There has been a lot of hate, frankly, disguised for decades as civil discourse and apparently ordinary polite society behaviour. While some of the apparent tone of recent movements is appreciably different, and approaches a fever pitch in cases where people are at the end of their rope due to continuing maltreatment, I think it is disingenuous to paint the pushing back as somehow more hateful than what’s being pushed back on.

                                                                                                                                                                1. 2

                                                                                                                                                                  There has been a lot of hate, frankly, disguised for decades as civil discourse and apparently ordinary polite society behaviour.

                                                                                                                                                                  There’s also a lot of people who call civil discourse ‘hate’ as a way to shut down differing points of view.

                                                                                                                                                                  While some of the apparent tone of recent movements is appreciably different, and approaches a fever pitch in cases where people are at the end of their rope due to continuing maltreatment, I think it is disingenuous to paint the pushing back as somehow more hateful than what’s being pushed back on.

                                                                                                                                                                  From my vantage point, I see a lot of people being slandered, canceled, and even assaulted for living their ordinary lives and failing to toe a particular ideological line. These aren’t hateful people and many of them are themselves minorities; if they knew what policy would fix various racial disparities, they’d support it (e.g., IIRC a majority of even Republicans support police reform–there’s clearly more good will/faith out there than we’re lead to believe). They simply don’t buy the far-left newspeak rhetoric and extreme and frankly idiotic solutions (“tear down capitalism!”, “defund police!”, etc).

                                                                                                                                                                  Further, your characterization is that the bad actors are presumably minorities at the end of their ropes, but the people I see behaving the worst in this regard are very often white and almost uniformly privileged people, often with lofty positions in media or universities. Similarly there are many well-behaved people of all races and positions. There’s not a strong racial signal as far as I can tell (although you wouldn’t know it from the mainstream media).

                                                                                                                                                                  I think you and I have different positions, and that’s fine. I’m sure mine is skewed, and I’m always trying to understand better. Hopefully in time people with views similar to yours and people with views similar to mine will come to a more mutual understanding, but of course that’s dependent on a healthy debate.

                                                                                                                                                                  1. 4

                                                                                                                                                                    There’s also a lot of people who call civil discourse ‘hate’ as a way to shut down differing points of view. From my vantage point, I see a lot of people being slandered, canceled, and even assaulted for living their ordinary lives and failing to toe a particular ideological line.

                                                                                                                                                                    Something I have noticed from a lot of conservative-leaning Americans is the tendency to latch onto the idea that someone might address their behaviour as somehow being the gravest sin, far worse than the shitty behaviour itself. Free speech doesn’t mean free from consequences!

                                                                                                                                                                    Communication is certainly a two way street, but the “differing views” stuff is frankly pretty exhausting. The paradox of tolerance is a pretty tangible phenomenon, as it turns out. If you have a pattern of poor behaviour, other people are welcome to – and should! – point it out, especially when the transgressors are powerful people. The religious right have been doing this in their own way for years, harassing advertisers and TV networks, and politicians; organising boycotts and making a racket, to shut down TV shows or laws or organisations that they believe are offensive.

                                                                                                                                                                    In another thread, you said:

                                                                                                                                                                    They redefine “racism” such that white people simply participating innocuously in their own culture is inherently racist and consequently evil

                                                                                                                                                                    I am a white person from Australia, where we have our own unfortunate, regrettable history. There are aspects of what I imagine you’re defining as “white” culture (whatever that is) that are indeed quite horrid. By “simply participating” in modern US society you (and I) are utilising a pile of wealth that was created through colonialism, and slavery, and many other deeply awful, violent, destructive aspects of our shared societal history. On top of that, many societal institutions (like the police, or the fact that wage theft is not a crime) are structurally configured to protect certain groups of people at the often violent expense of other groups.

                                                                                                                                                                    By pretending it isn’t something we all need to deal with urgently, that we have the luxury of waiting for someone to come along and debate us in a tone of which you approve, you are taking a fundamentally regressive stance. There is no move on this chess board that isn’t inherently a political decision, even though it might feel like your doing nothing and staying out of the way is somehow balanced or apolitical.

                                                                                                                                                                    a majority of even Republicans support police reform–there’s clearly more good will/faith out there than we’re lead to believe

                                                                                                                                                                    I will believe it when I see it! Republicans have periodically had concurrent control of the House and the Senate and the Executive and a lot of the courts and statehouses in this country. They have had ample opportunity to drive forward any “reform” that they felt would mean less people are oppressed, harmed, killed. It isn’t at all surprising to me that people are deeply unhappy with the status quo.

                                                                                                                                                                    1. 1

                                                                                                                                                                      Something I have noticed from a lot of conservative-leaning Americans is the tendency to latch onto the idea that someone might address their behaviour as somehow being the gravest sin, far worse than the shitty behaviour itself. Free speech doesn’t mean free from consequences!

                                                                                                                                                                      Take comfort in that I’m not a conservative, but a moderate liberal. Your observation would indeed be frustrating, but that’s not what I’m doing here. My claim is that ordinary white folks and increasingly minority folks who are just going about their business are maligned by the progressive left. We’re not talking about “shitty behavior”, we’re talking about something much closer to “having white skin”. Note that this is not worse than what many minorities endure; however, it is unjust to slander, malign, and cancel people, and further it distracts from progress with respect to improving minority outcomes. There certainly is no dichotomy in which we much choose between anti-white racism and anti-minority racism; morally you can’t be opposed to racism with race-based caveats (e.g., “except against $race”) but practically you’ll very likely create a lot more anti-minority racists by perpetrating anti-white racism.

                                                                                                                                                                      Communication is certainly a two way street, but the “differing views” stuff is frankly pretty exhausting.

                                                                                                                                                                      Agreed; it is exhausting; however, to be clear, “differing views” means we need to work to understand each other. It’s not some morally relativistic argument that you must accept my viewpoint.

                                                                                                                                                                      The paradox of tolerance is a pretty tangible phenomenon, as it turns out. If you have a pattern of poor behaviour, other people are welcome to – and should! – point it out, especially when the transgressors are powerful people.

                                                                                                                                                                      It may be a tangible phenomenon, but without a criteria for what is “tolerant” and “intolerant” the principle is easily abused to give anyone license to abuse any other party simply by defining intolerance such that they are intolerant. This is exactly what we see with many progressives (especially intellectuals) who seek to change the definition of racism because it doesn’t target the right people (white folks, including “colorblind” white folks, mostly). So we’re not talking about “transgressors” except insofar as the transgression is having the wrong skin color.

                                                                                                                                                                      The religious right have been doing this in their own way for years, harassing advertisers and TV networks, and politicians; organising boycotts and making a racket, to shut down TV shows or laws or organisations that they believe are offensive.

                                                                                                                                                                      And we eventually collectively shut them down in the name of liberalism. The religious right lost every significant fight–abortion, sex and violence on TV, gay marriage, etc (and while it did get Hobby Lobby, it’s not a significant issue and it won it because of liberalism).

                                                                                                                                                                      I am a white person from Australia, where we have our own unfortunate, regrettable history. There are aspects of what I imagine you’re defining as “white” culture (whatever that is) that are indeed quite horrid.

                                                                                                                                                                      I don’t think there are, but we should talk in concrete detail about what they might be. I think there certainly were elements of “white culture” which were horrid, but I think we largely expunged them (or to be precise, there are still individual racists, but they aren’t allowed to express their views in society).

                                                                                                                                                                      By “simply participating” in modern US society you (and I) are utilising a pile of wealth that was created through colonialism, and slavery, and many other deeply awful, violent, destructive aspects of our shared societal history.

                                                                                                                                                                      Granted, but this is true of all Americans (including minorities) to widely varying degrees. This has left white people with more money on average than black people (whites are more likely to have wealth privilege), and I’m pretty open to reparations or some other ideas for addressing this. I genuinely don’t know what the right answer is, nor do the overwhelming majority of white folks; however, I don’t think that gives progressives (or leftists or whichever term you prefer) any license to abuse them for their race.

                                                                                                                                                                      On top of that, many societal institutions (like the police, or the fact that wage theft is not a crime) are structurally configured to protect certain groups of people at the often violent expense of other groups.

                                                                                                                                                                      Yeah, this is real white privilege. We need to understand the extent to which this is a problem and understand its dynamics in order to solve it properly. We need trustworthy academic and media apparatuses (even if they are on “the right side”, Americans need to be able to trust that these institutions are asking questions on their behalf)–which means we need to reform or retire our concept of activist journalists and academics.

                                                                                                                                                                      By pretending it isn’t something we all need to deal with urgently, that we have the luxury of waiting for someone to come along and debate us in a tone of which you approve, you are taking a fundamentally regressive stance.

                                                                                                                                                                      It’s precisely because the problem is urgent that we can’t afford to use the moment as an opportunity to exercise our personal hatred toward whites or conservatives or otherwise stroke our own enlightened egos. We need to build coalitions and simply wishing that people would take our abuse and still be on our side is naive at best (the less-than-charitable view is that those who heap the abuse don’t actually want circumstances to improve; they like the moral landscape because they feel it gives them moral license to heap their abuse without actually suffering social consequences for doing so). People who sabotage this coalition building are obstacles that we can’t afford to ignore.

                                                                                                                                                                      will believe it when I see it!

                                                                                                                                                                      Behold

                                                                                                                                                                      You can debate whether it will be effective or whatever, but they have a proposal and I can’t seem to find the poll, but an overwhelming majority of Republican voters support police reform (this being the motivating factor for the proposal).

                                                                                                                                                                      Republicans have periodically had concurrent control of the House and the Senate and the Executive and a lot of the courts and statehouses in this country. They have had ample opportunity to drive forward any “reform” that they felt would mean less people are oppressed, harmed, killed. It isn’t at all surprising to me that people are deeply unhappy with the status quo.

                                                                                                                                                                      As have Democrats. Biden’s ‘94 crime bill wasn’t exactly friendly toward black Americans, nor was Hillary’s famous thinly veiled “superpredator” remark. But we can’t let partisan bickering distract us.

                                                                                                                                                                    2. 2

                                                                                                                                                                      There’s also a lot of people who call civil discourse ‘hate’ as a way to shut down differing points of view.

                                                                                                                                                                      “Different points of view” is a phrase that can be weaponized to paper over categorically different things.

                                                                                                                                                                      Whether or not the Laffer Curve is an effective means to guide tax policy are different points of view, and we can have a civil discourse on the subject.

                                                                                                                                                                      Whether or not transsexual women are mentally sick men are not merely different points of view. One position is hateful; civil discourse is impossible because that position is in its nature un-civil.

                                                                                                                                                                      Bringing it back on-topic: whether fewer women exist in programming occupations because of hiring bias, or because of some innate, gender-based distaste for science or math or whatever, is a gray area. It’s possible to have this discussion in a civil way, but it requires considerable attention to context. For example, not every forum is appropriate for the discussion. It would be inappropriate to have this kind of debate on a mailing list of a technology company, where women engineers at the company would be justifiably aggrieved by colleagues arguing for the “innate” position. Insisting on having this discussion in that context is hateful, to some degree.

                                                                                                                                                                      (n.b. the correlation of “differing points of view” that are actually hateful to a specific American political stance/party isn’t evidence of political censorship, it’s evidence of regressive and hateful politics.)

                                                                                                                                                                      1. 0

                                                                                                                                                                        I strongly disagree. For instance, it’s not a gray area at all to debate the cause for why there are fewer women in programming—this is an empirical question, and moreover only a minority of women are offended by either position (indeed there’s no reasonable cause for offense). This doesn’t fit any reasonable definition of “hate”. I’m strongly of the opinion that “hate” is the weaponized term, used by a specific group of bad faith actors to suppress reasonable debate as previously discussed. I agree that this is evidence of regressive and hateful politics, but probably not in the way you mean. Anyway, I don’t really enjoy rehashing these same largely semantic debates over and over, so I’ll leave you to the last word.

                                                                                                                                                                        1. 3

                                                                                                                                                                          there’s no reasonable cause for offense [for] women engineers [witnessing] colleagues arguing for the “innate” position [in a debate in the office on] whether fewer women exist in programming occupations because of hiring bias, or because of some innate, gender-based distaste for science or math

                                                                                                                                                                          Your claim kind of stands on its own here, I think.

                                                                                                                                                                2. 2

                                                                                                                                                                  Or should we not always seek to improve?

                                                                                                                                                                  Improving isn’t cost free. if the cost to implement a solution exceeds the fruit, it is not worth it.

                                                                                                                                                                  1. 4

                                                                                                                                                                    if the cost to implement a solution exceeds the fruit, it is not worth it

                                                                                                                                                                    Well, that’s a truism, so I’m not sure how much insight it delivers. The issue tends to be an appropriate accounting of the benefit. For example, many of the advanced safety features on cars probably seemed “not worth it” by this formula at the time of their introduction or regulatory mandate, because it’s difficult to put an accurate value on future lives saved. Similarly, many of these discrimination-reducing measures could easily be seen as “not worth it” as it’s difficult to put an accurate value on the long-term benefits of more representative and diverse organizations.

                                                                                                                                                                  2. 1

                                                                                                                                                                    then there is no limit to the number of “fixes” that will be proposed.

                                                                                                                                                                    I guess that’s true, and I guess a good thing

                                                                                                                                                                    Depends on your appetite for another can’t-win, perpetual war. We are still fighting the wars on poverty, terrorism, and drugs.

                                                                                                                                                                    I see two independent ideas in your comment:

                                                                                                                                                                    1. seeking to improve oneself
                                                                                                                                                                    2. seeking to improve others

                                                                                                                                                                    1 is virtuous IMO. 2 leads to pesky authoritarian over-corrections.

                                                                                                                                                                    1. 8

                                                                                                                                                                      As an aside, I always find it fascinating how readily tiny incremental changes that are light years short of perfection get called pesky authoritarian over-corrections.

                                                                                                                                                                      1. 0

                                                                                                                                                                        My comment was specifically about the risk of over-corrections, not tiny changes, that tends to follow from a zeal for improving other humans. Errors accumulate.

                                                                                                                                                                        1. 2

                                                                                                                                                                          Sure. When they’re errors. My point is that what you might call an over-correction someone else might call a tiny incremental change.

                                                                                                                                                                      2. 5

                                                                                                                                                                        “seeking to improve others” leads to pesky authoritarian over-corrections? Do you find this to be true when you think of anything else besides gender or racial equality?

                                                                                                                                                                        1. 1

                                                                                                                                                                          I’m guessing you expect an answer other than “yes”, or perhaps you had hoped to enlighten a lower creature.

                                                                                                                                                                          Your reply (and others in this thread) quickly turned personal. Hmm.

                                                                                                                                                                        2. 2

                                                                                                                                                                          seeking to improve others . . . leads to pesky authoritarian over-corrections

                                                                                                                                                                          Well, that’s certainly one failure mode of any kind of policy of mandate from authority, and we should be careful to guard against it, but it’s hardly inevitable. More importantly, there is an upper bound to the amount of progress that can be achieved on a large scale via individual virtue and action alone.

                                                                                                                                                                          1. 1

                                                                                                                                                                            Even for part 1 it is not clear that it is always good. Why would becoming the best programmer in the world good, when it would take so much effort and time, which can be spent on enjoying yourself, if you are already a pretty good programmer that can command a pretty good salary. Diminishing return is a thing and self-improvement is not without cost.

                                                                                                                                                                        3. 14

                                                                                                                                                                          If the bar is perfection, then there is no limit to the number of “fixes” that will be proposed.

                                                                                                                                                                          Indeed, that’s exactly what a benefactor of a broken system would say. For excluded folks, there’s no cost in trying to change the system; they aren’t benefitting from it regardless.

                                                                                                                                                                          1. 1

                                                                                                                                                                            that’s exactly what a benefactor of a broken system would say.

                                                                                                                                                                            Okay, but is he wrong?

                                                                                                                                                                            1. 4

                                                                                                                                                                              About what? This?

                                                                                                                                                                              If the bar is perfection, then there is no limit to the number of “fixes” that will be proposed.

                                                                                                                                                                              Yes? No? I’m unfamiliar with any documented result that answers this question, so I’m going to go with maybe here. This is such a nebulously defined problem that I’m not really sure one can answer it. Fixes to what? Perfection where? How much effort does perfection take?

                                                                                                                                                                              My point was simple: it doesn’t matter what you think about perfection or fixes or the lack thereof. Disenfranchised people, throughout history, have agitated for franchisement. From the Roman Empire’s discrimination of Christians to the brutality of Belgian rule on the Congo. No matter the advantages of the system, the disenfranchised have sought to topple theirs. Advance a position with known disenfranchisement at your own peril.

                                                                                                                                                                            2. 0

                                                                                                                                                                              Indeed, that’s exactly what a benefactor of a broken system would say.

                                                                                                                                                                              While this is a fun argument, it’s not an actual one. Just because a bad entity would say something, does not make whatever is being said bad.

                                                                                                                                                                              For excluded folks, there’s no cost in trying to change the system; they aren’t benefitting from it regardless.

                                                                                                                                                                              They think they are benefitting from it. But predicting the future is hard, and regrets do happen.

                                                                                                                                                                              1. -1

                                                                                                                                                                                Indeed, that’s exactly what a benefactor of a broken system would say.

                                                                                                                                                                                If you have nothing to hide then you don’t need privacy, right?

                                                                                                                                                                                This is Christianity’s “original sin” concept, a cudgel used against anyone who questions the priest class.

                                                                                                                                                                                1. 4

                                                                                                                                                                                  If you have nothing to hide then you don’t need privacy, right?

                                                                                                                                                                                  I’m unclear what that has to do with my comment.

                                                                                                                                                                                  This is Christianity’s “original sin” concept, a cudgel used against anyone who questions the priest class.

                                                                                                                                                                                  I’m not sure what you’re talking about. What cudgel is this for what or for whom? I’m just trying to tell you that if you don’t find a solution acceptable by all parties, then disenfranchised people will understandably not care about your perspectives or your ideals. Telling them to be quiet in the name of a philosophical good is sophistry at best.

                                                                                                                                                                              2. 5

                                                                                                                                                                                By enacting more laws, or how exactly?

                                                                                                                                                                                The legal industry has Diversity Lab.
                                                                                                                                                                                They conduct policy hackathons, create policies to promote diversity, and report on the results.
                                                                                                                                                                                The Mansfield Rule is an example of one of their policies.
                                                                                                                                                                                Now in its third iteration, the Mansfield Rule Certification measures whether law firms have affirmatively considered at least 30 percent women, attorneys of color, LGBTQ+ and lawyers with disabilities for leadership and governance roles, equity partner promotions, formal client pitch opportunities, and senior lateral positions.
                                                                                                                                                                                102 large law firms have agreed to this rule and their compliance is assessed by third-party audits.

                                                                                                                                                                                There’s nothing to stop the technology sector from taking similar actions.

                                                                                                                                                                                1. 1

                                                                                                                                                                                  Thanks. But those efforts are part of the free market, they aren’t state mandates. So this is an example of the market voluntarily experimenting with solutions.

                                                                                                                                                                                  1. 2

                                                                                                                                                                                    It’s a combination of voluntary actions and state mandates.
                                                                                                                                                                                    The legal industry has been working on gender equity and diversity for decades.
                                                                                                                                                                                    Law schools used affirmative action to admit gender-balanced classes in the 60 and 70s.
                                                                                                                                                                                    Class-action lawsuits in the 1970s forced law firms to change their hiring practices.
                                                                                                                                                                                    Diversity is also important to clients for legal services; Diversity Lab’s initiatives are backed by Microsoft, Starbucks, Bloomberg LP, and 3M.

                                                                                                                                                                                    Edited to add the following text.
                                                                                                                                                                                    Law firm diversity metrics are public and widely shared.
                                                                                                                                                                                    The National Law Journal’s Women in Law Scorecard, for example, was released earlier this week.

                                                                                                                                                                                2. 7

                                                                                                                                                                                  The majority of the article makes clear that perfection isn’t the bar. The point of using the word “perfectly” seems to be to address a specific disingenuous claim:

                                                                                                                                                                                  1. Markets are competitive
                                                                                                                                                                                  2. Unjustified discrimination is a competitive disadvantage
                                                                                                                                                                                  3. Market forces in a competitive market must tend toward a perfect balance that squeezes out disadvantageous behavior
                                                                                                                                                                                  4. Therefore, discrimination can’t be a significant factor in the market

                                                                                                                                                                                  I’d reckon laws aren’t likely the point. It’s already illegal (in the US at least) to discriminate on most of the bases talked about in the article; from a policy perspective, a change in enforcement might help. But most likely, the change is going to have to be a cultural one. The sort of thing where enough people talk about this, and enough people agree that it’s not okay, that it’s almost impossible to be a member of the computer science community and not find yourself actively checking for this bias in your decision-making.

                                                                                                                                                                                  1. 0

                                                                                                                                                                                    But most likely, the change is going to have to be a cultural one.

                                                                                                                                                                                    Culture, social change, blog posts, are all part of the free market. These discussions are poisoned with the common assumption that anything lacking a credit card transaction is somehow not part of economics.

                                                                                                                                                                                    Has anyone considered that anti-discrimination laws may contribute to the problem? Hiring a protected class carries the perception of increased liability in terms of lawsuits, whereas hiring a non-protected class may carry less liability.

                                                                                                                                                                                    Maybe the laws did their job and now it’s time to enter “phase 2”: remove special protections. That was the goal, wasn’t it? Note that discrimination on the basis of liability is different in origin though not effect. The laws never cared about origin, only effect.

                                                                                                                                                                                    1. 6

                                                                                                                                                                                      Conversely, I feel as if your claim is poisoned by the common assumption that anything lacking government intervention is somehow part of the free market. Maybe economics in general has broader applicability, but if we’re talking about market forces, the topics of our discussion are explicitly going to be things related to the accumulation of capital. Culture, social change, blog posts, and so on are only related insofar as they have value that can be expressed in monetary terms. Whatever the case may be, it’s empirically true that whatever value they currently have isn’t sufficient to change hiring behaviors. So either we need to change that value or we need to effect changes that cause people to act for reasons unrelated to satisfying market pressures.

                                                                                                                                                                                      Your second argument might be correct (I don’t know), but if it is, it’s a red herring. You can’t argue that discrimination doesn’t exist in the market because anti-discrimination laws are such a poor remedy that they create incentives to discriminate. The original article is addressing a single, specific claim - that it is economically impossible for discrimination to exist, because if it did companies would find competitive advantage by not discriminating until the market reached equilibrium. If you want to find a cause for why discrimination does exist, that’s a different thing.

                                                                                                                                                                                      1. 3

                                                                                                                                                                                        Culture, social change, blog posts, and so on are only related insofar as they have value that can be expressed in monetary terms. Whatever the case may be, it’s empirically true that whatever value they currently have isn’t sufficient to change hiring behaviors. So either we need to change that value or we need to effect changes that cause people to act for reasons unrelated to satisfying market pressures.

                                                                                                                                                                                        This does not follow at all. Let’s say (although almost no one is explicitly calculating as follows) one is willing to hire men rather than women up to $1M of economic damage due to held value, and resulting inefficiency causes loss of $500K economic value. Also, social shaming (“culture”) causes $300K of economic damage. In this scenario, as you say, culture is empirically insufficient to change hiring. But it is simply incorrect to say the choice is either to change such held value, or to deploy non-monetary force. If social shaming intensifies 2x, the total damage reaches $1.1M and hiring changes.

                                                                                                                                                                                        1. 1

                                                                                                                                                                                          I might have miscommunicated - your example is exactly what I meant by changing the value of culture, etc.

                                                                                                                                                                                          1. 2

                                                                                                                                                                                            That must be the case. From what I can read, you and jmk are in agreement: quotes giving me such impression include “By enacting more laws?” and “market forces (which includes culture)”.

                                                                                                                                                                                        2. 3

                                                                                                                                                                                          Culture, social change, blog posts, and so on are only related insofar as they have value that can be expressed in monetary terms

                                                                                                                                                                                          It’s really simple why these are part of the free market: These things influence the reader, the reader’s thinking, and therefore they influence the reader’s spending.

                                                                                                                                                                                          1. 1

                                                                                                                                                                                            We agree. And since the existing influence on spending isn’t enough to force changes in hiring practices, then if different hiring practices are desired, the solution is either intensifying that influence, or relying on something other than economics, e.g. community norms.

                                                                                                                                                                                            1. 4

                                                                                                                                                                                              FYI, the entire point of contention is that community norms IS economics. That’s what jmk’s “common assumption that anything lacking a credit card transaction is somehow not part of economics” phrase is about.

                                                                                                                                                                                          2. 2

                                                                                                                                                                                            The original article is addressing a single, specific claim - that it is economically impossible for discrimination to exist, because if it did companies would find competitive advantage by not discriminating until the market reached equilibrium.

                                                                                                                                                                                            Framing the question as a binary (“perfect or not perfect”) is not meaningful and thus disingenuous. “Economically impossible” (assuming anyone used those words) is obviously a theoretical upper bound, since economics is dynamic (changes with time and context).

                                                                                                                                                                                            The meaningful question is whether market forces (which includes culture) tend to improve the situation. Are we going in the right direction or not?

                                                                                                                                                                                            1. 5

                                                                                                                                                                                              The claim the article argues against is explicitly a binary one - that the economic disadvantage of discrimination proves that discrimination can’t explain observations about women and minorities in the tech industry. If you agree that the economic effects are anything less than perfect, then you agree that discrimination can explain some of the observations, and you may agree with the article.

                                                                                                                                                                                              1. 4

                                                                                                                                                                                                I think dl and jmk are talking past each other, because dl’s article is mostly about diagnosis, and jmk is mostly concerned about solution. dl says observed disparity is not wholly explained by economics and it is likely explained by discrimination, and I think jmk agrees? (I agree.)

                                                                                                                                                                                                But to jmk (and to me), the important part is what to do about it. Existence of discrimination does not support any governmental intervention, since it is possible all government interventions are harmful. The thing is, I think dl also agrees. The article merely says “We can fix this, if we stop assuming the market will fix it for us”, it does not suggest or support any specific governmental intervention, it doesn’t even suggest or support governmental intervention is necessary.

                                                                                                                                                                                                To me, the whole debate is about what “market” means: which is boring terminological discussion. To dl, large scale social movement (aka jmk’s “culture”) is not part of the market, but to jmk, it is. So I think both agrees about the solution (mostly cultural, not legal), but disagree whether to call it market or not.

                                                                                                                                                                                      2. -2

                                                                                                                                                                                        By enacting more laws, or how exactly?

                                                                                                                                                                                        “muh free market” isn’t the perfect solution, but a pretty good solution that’s very easy to implement. Women and minorities can get what they can get, nothing is stopping them. If the boys are bad, then just make a women only corporation, crush the market with your 20% reduced salary expense, and counter-discriminate the boys. that will show them….

                                                                                                                                                                                        No it’s not perfectly workable. But it’s really good. Trying to ‘fix’ the ‘injustice’ is like balancing a ping-pong on a paddle while blind folded. There’s no guarantee that if we fix the 20% gap, we are not subsidising women for their choices that we simply didn’t know about.

                                                                                                                                                                                      1. 59

                                                                                                                                                                                        It’s going to be cheaper. Especially when you consider employee costs. The most expensive AWS RDS instance is approximately $100k/year (full price). It’s not an apples to apples comparison, but in many countries you can’t get a database architect for that salary.

                                                                                                                                                                                        “not an apples to apples comparison” is putting it mildly. You’re comparing the cost of some infrastructure with the cost of an application-level specialist you’d need either way. The equipment to run a comparable database instance on-premises should cost less than half that. Ops costs are harder to compare, but $work certainly doesn’t retain an operations engineer per big RDBMS instance.

                                                                                                                                                                                        More generally, though, I think this is the way things are going without encouragement, and I hate it. It feels like the list of places where ops involves working with computers is shortening. I could offer all sorts of reasons why I think it’s a bad trend—it’s concentrating people, information and resources in a few huge companies, network effects stifle innovation, bespoke architectures are more efficient, your NOC is more likely to answer your calls when they work for you, blah blah. Mostly, though, it just makes me sad to see the things I enjoy becoming increasingly irrelevant except to a small group of companies I don’t want to work for.

                                                                                                                                                                                        1. 30

                                                                                                                                                                                          TITANESQUE DISCLAIMER: I FIX USER OUTLOOK MAILBOXES FOR A LOCAL IT COMPANY

                                                                                                                                                                                          Yes, always cheaper at first. And then your tiny thing grows, and then you cannot live without your managed services, and your managed service knows it, and then it is not cheaper anymore.

                                                                                                                                                                                          1. 13

                                                                                                                                                                                            This. Half of the jobs I had could be summed up as: oh shit, managed service X got out of control and its cost became unbearable.

                                                                                                                                                                                            In one instance, it ended up in the company firing 70% of its employees, because one morning, some GCP service costs had sky rocketed causing the main project of the company to fail. To be honest, had they made a simple extrapolation when they signed up for the service, the situation would be 100% expectable.

                                                                                                                                                                                            Of course it depends. S3 value offer is difficult to replicate as a self managed service, but things like hosted RDMS or even ec2 instances are really only an advantage when starting up and toying with tiny loads. Once your serviece start scaling, they quickly result in 1-3 orders of magnitude of extra costs. Which is unlikely irrelevant.

                                                                                                                                                                                          2. 16

                                                                                                                                                                                            You’re comparing the cost of some infrastructure with the cost of an application-level specialist you’d need either way.

                                                                                                                                                                                            I beg to differ. Lots of places can get by without the application-level specialist. Until they can’t. Making that decision is of course is an art, but using a managed service will extend how big you can get without a FTE (maybe you will need some consulting for tuning a query, for example, but that’s cheaper).

                                                                                                                                                                                            More generally, though, I think this is the way things are going without encouragement, and I hate it.

                                                                                                                                                                                            I understand this perspective. I still think there are ops tasks and jobs, but yes, they are certainly changing. I do think that managed services lets people build a lot more software (the same way that blogs let a lot more content be created than hand written html) but appreciate that the effects aren’t entirely positive.

                                                                                                                                                                                            1. 16

                                                                                                                                                                                              (I think it’s kinda relevant that you are a developer evangelist for one of these hosted services. Neither good nor bad, just an important datapoint.)

                                                                                                                                                                                              One thing that I think gets lost in this is that a company is theoretically valued also at the in-house talent. If your company is basically just a glorified rebundler and reseller of service providers, you lost the ability to leverage that in-house talent. You also by definition reduce the ability to distinguish yourself from other companies that are doing the same thing.

                                                                                                                                                                                              Second, there is a very real problem where people buy a service provider and then just patch over the issues with it using…another service provider! This has this weird inflection point where suddenly any scaling is a heart-stopping event as you graduate from the “developer wants to pad resume tier” to the “somebody in the C-suite needs to sign a contract tier”.

                                                                                                                                                                                              1. 5

                                                                                                                                                                                                I think it’s kinda relevant that you are a developer evangelist for one of these hosted services. Neither good nor bad, just an important datapoint.

                                                                                                                                                                                                Thanks for pointing that out! I have actually been espousing this viewpoint for years. I also taught AWS certification courses and built a start-up in the last 5 years and both of those cemented my view about leveraging managed services.

                                                                                                                                                                                                But yes, where people sit definitely affects where they stand, and I am no different. (I will also submit that, in my opinion, my employer’s offering beats the pants off the hand rolled authentication systems I have seen over the years.)

                                                                                                                                                                                                One thing that I think gets lost in this is that a company is theoretically valued also at the in-house talent.

                                                                                                                                                                                                That’s a good point. I think every company needs to decide what it is good at. That may be infrastructure for some companies, for others it might be enterprise sales, etc, etc. I have left companies where I knew my department was never going to be the focus of the company, because that limited my growth. My favorite old post about this topic: https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/

                                                                                                                                                                                                From that post:

                                                                                                                                                                                                If it’s a core business function — do it yourself, no matter what.

                                                                                                                                                                                                As you mention service provider sprawl is a real problem. Being disciplined about managed services, including when to leave them, is just as hard as being disciplined about maintaining your own code. Maybe even harder because the effort is lower for the managed service (which would argue against my thesis, as you say).

                                                                                                                                                                                                1. 5

                                                                                                                                                                                                  But yes, where people sit definitely affects where they stand, and I am no different.

                                                                                                                                                                                                  Same here! And I didn’t mean that as a gotcha, more of as a “this poster has probably seen the spectrum of this philosophy in practice and that is relevant.”

                                                                                                                                                                                                  :)

                                                                                                                                                                                            2. 7

                                                                                                                                                                                              You bring up a lot of good points, especially about bespoke architecture. I think my only push back would be that the landslide majority of the time I set up a database (or any other service), it’s with the same configuration and features as everyone else. It makes more economic efficiency to cater to the general case, both for the vendor and the customer (or for the DBA and the company). Inevitably there will be divergence especially as a company or product grows in complexity.

                                                                                                                                                                                              I enjoy working on these architecture as well, but I find setting up the same old database again and again tiresome. I’d rather defer that action to a vendor until there’s a real problem worth solving and dive deep there.

                                                                                                                                                                                              It’s not fading into irrelevance when more companies are given the ability to use database (or whatever) at scale. On the contrary, more companies using databases mean more relevance for the people that know how to use them well. The statistical majority can stay under the middle 50% of the use case covered well by the vendor and leave me to cover the outer 50% where the inside and outside tails have interesting use cases.

                                                                                                                                                                                              1. 4

                                                                                                                                                                                                These complaints seem like general grievances with any kind of automation. More work is accomplished by fewer people, and those people are increasingly specialized. Bespoke widgets are replaced with cold, stamped-out widgets. Customer service decreases.

                                                                                                                                                                                                This isn’t to say your frustrations are invalid, only that they are normal and increasing as we automate away more and more skillsets. It’s a bummer to see your hard-won skills falling to a dramatically cheaper service.

                                                                                                                                                                                              1. 4

                                                                                                                                                                                                I’ve written some Go and some Rust. I feel like I usually enjoy Rust more, though I struggle to explain why.

                                                                                                                                                                                                I think, for Rust, I find the error handling really ergonomic. Using ? in a function that does a bunch of things that can fail is just so much nicer than having every other line be a if err == nil { return err }. I also find it easier to follow how references work in Rust, oddly enough maybe. And using modules through Cargo is just so nice, while Go modules is kind of a messy hack in comparison. Oh and the macros are just so nice too.

                                                                                                                                                                                                But on Go’s side, Go concurrency is really awesome and smooth, especially compared to the half-complete hacks that are tokio and the Rust async system. Did I mention how nice the built-in channels are, and how a bunch of places in the standard lib use them? And easy cross-compilation is pretty nice too. And you gotta love that massive standard library. And I suppose not having to wrestle with complex too-clever generic hierarchies is nice sometimes too.

                                                                                                                                                                                                1. 16

                                                                                                                                                                                                  side-note: i think it’s a bit off-topic (and meme-y, rust strike force, etc. :) to compare to rust when the article only speaks of go :)

                                                                                                                                                                                                  Using ? in a function that does a bunch of things that can fail is just so much nicer than having every other line be a if err == nil { return err }.

                                                                                                                                                                                                  i really like the explicit error handling in go and that there usually is only one control flow (if we ignore “recover”). i guess that’s my favorite go-feature: i don’t have to think hard about things when i read them. it’s a bit verbose, but that’s a trade-off i’m happy to make.

                                                                                                                                                                                                  1. 7

                                                                                                                                                                                                    i really like the explicit error handling in go

                                                                                                                                                                                                    I would argue that Go’s model of error handling is a lot less explicit than Rust’s - even if Go’s is more verbose and perhaps visually noticeable, Rust forces you to handle errors in a way that Go doesn’t.

                                                                                                                                                                                                    1. 1

                                                                                                                                                                                                      I have just read up un rusts error handling, it seems to be rather simila, except that return types and errors are put together as “result”: https://doc.rust-lang.org/book/ch09-00-error-handling.html

                                                                                                                                                                                                      my two cents: i like that i’m not forced to do things in go, but missing error handling sticks out as it is unusual to just drop errors.

                                                                                                                                                                                                      1. 4

                                                                                                                                                                                                        Well since it’s a result, you have to manually unwrap it before you can access the value, and that forces you to handle the error. In Go, you can forget to check err for nil, and unless err goes unused in that scope, you’ll end up using the zero value instead of handling the error.

                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                          i like that i’m not forced to do things in go, but missing error handling sticks out as it is unusual to just drop errors

                                                                                                                                                                                                          The thing is, while it may be unusual in Go, it’s impossible to “just drop errors” in Rust. It’s easy to unwrap them explicitly if needed, but that’s exactly my point: it’s very explicit.

                                                                                                                                                                                                      2. 3

                                                                                                                                                                                                        The explicit error handling is Very Visible, and thus it sticks out like a sore thumb when it’s missing. This usually results in better code quality in my experience.

                                                                                                                                                                                                        1. 2

                                                                                                                                                                                                          It did occur to me that it may come off like that :D It’s harder to make interesting statements about a language without comparing it to its peers.

                                                                                                                                                                                                          IMO, Rust and Go being rather different languages with different trade-offs that are competing for about the same space almost invites comparisons between them. Kind of like how temping it is to write comparisons between Ruby, Python, and Javascript.

                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                            I think Swift fits in quite well in-between. Automatic reference counting, so little need to babysit lifetimes, while using a powerful ML-like type system in modernised C-like syntax.

                                                                                                                                                                                                        2. 15

                                                                                                                                                                                                          But on Go’s side, Go concurrency is really awesome and smooth

                                                                                                                                                                                                          Concurrency is an area I feel Go really lets the programmer down. There is a simple rule for safe concurrent programming: No object should be both mutable and shared between concurrent execution contexts at the same time. Rust is not perfect here, but it uses the unique ownership model and the send trait to explicitly transfer ownership between threads so you can pass mutable objects around, and the sync trait for safe-to-share things. The only safe things to share in safe rust are immutable objects. You can make other things adopt the sync trait if you’re willing to write unsafe Rust, but at least you’re signposted that here be dragons. For example, the ARC trait in Rust (for atomic reference counting), which gives you a load of read-only shared references to an object and the ability to create a mutable reference if there are no other outstanding references.

                                                                                                                                                                                                          In contrast, when I send an object down a channel in Go, I still have a pointer to it. The type system gives me nothing to help avoid accidentally aliasing an object between two threads. To make things worse, the Go memory model is relaxed consistency atomic, so you’re basically screwed if you do this. To make things even worse, core bits of the language semantics rely on the programmer not doing this. For example, if you have a slice that is in an object that is shared between two goroutines, both can racily update it. The slice contains a base and a length and so you can see tearing: the length from one slice and the base from another. Now you can copy it, dereference it and read or write past the end of an array. This is without using anything in the unsafe package: you can violate memory safety (let alone type safety) purely in ‘safe’ Go, without doing anything that the language helps you avoid.

                                                                                                                                                                                                          I wrote a book about Go for people who know other languages. It didn’t sell very well, in part because it ended up being a long description of things that Go does worse than other languages.

                                                                                                                                                                                                          1. 2

                                                                                                                                                                                                            That’s a worthwhile point. I haven’t been bitten by the ability to write to Go object that have already been sent down a channel yet, but I haven’t worked on any large-scale long-term Go projects. I’ve found it straightforward enough to just not use objects after sending. But then, the reason why we build these fancy type systems with such constraints is that even the best developers have proved to be not very good at consistently obeying these limits on large-scale projects.

                                                                                                                                                                                                            I’m hoping that the Rust issues with async and tokio are more like teething pains for new tech than a fundamental issue, and that eventually, it will have concurrency tools that are both as ergonomic as Go’s and use Rust’s thread safety rules.

                                                                                                                                                                                                            1. 5

                                                                                                                                                                                                              I’ve found it straightforward enough to just not use objects after sending.

                                                                                                                                                                                                              This is easy if the object is not aliased, but that requires you to have the discipline of linear ownership before you get near the point that sends the object, or to only ever send objects allocated near the sending point. Again, the Go type system doesn’t help at all here, it lets you create arbitrary object graphs with N pointers to an object and then send the object. The (safe) Rust type system doesn’t let you create arbitrary object graphs and then gives strong guarantees on what is safe to send. The Verona type system is explicitly designed to allow you to create arbitrary (mutable or immutable) object graphs and send them safely.

                                                                                                                                                                                                          2. 9

                                                                                                                                                                                                            And using modules through Cargo is just so nice, while Go modules is kind of a messy hack in comparison.

                                                                                                                                                                                                            I have always found Rust’s module system completely impenetrable. I just can’t build a mental model of it that works for me. I always end up just putting keywords and super:: or whatever in front in various combinations until it happens to work. It reminds me of how I tried to get C programmes to compile when I was a little kid: put more and more & or * in front of expressions until it works.

                                                                                                                                                                                                            And of course they changed in Rust 2018 as well which makes it all the more confusing.

                                                                                                                                                                                                            1. 3

                                                                                                                                                                                                              Yeah, I’ve had the same experience. Everything else about Cargo is really nice, but modules appear to be needlessly complicated. I have since been told that they are complicated because they allow you to move your files around in whatever crazy way you prefer without having to update imports. Personally I don’t think this is a sane design decision. Move your files, find/replace, move on.

                                                                                                                                                                                                              1. 2

                                                                                                                                                                                                                And of course they changed in Rust 2018 as well which makes it all the more confusing.

                                                                                                                                                                                                                One of the things they changed in Rust 2018, FYI, was the module system, in order to make it a lot more straightforward. Have you had the same problem since Rust 2018 came out?

                                                                                                                                                                                                              2. 6

                                                                                                                                                                                                                For me Go is the continuation of C with some added features like CSP. Rust is/was heavily influenced by the ML type of languages which is extremely nice. I think ML group is superior in my ways to the C group. ADTs are the most trivial example why.

                                                                                                                                                                                                                1. 4

                                                                                                                                                                                                                  I generally agree. I like ML languages in theory and Rust in particular, but Rust and Go aren’t in the same ballpark with respect to developer productivity. Rust goes to impressive lengths to make statically-managed memory user-friendly, but it’s not possible to compete with GC. It needs to make up the difference in other areas, and it does make up some of the difference in areas like error handling (?, enums, macros, etc and this is still improving all the time), IDE support (rust-analyzer has been amazing for me so far), and compiler error messages, but it’s not yet enough to get into a competitive range IMO. That said, Rust progresses at a remarkable pace, so perhaps we will see it get there in the next few years. For now, however, I like programming in Rust–it satisfies my innate preference to spend more time building something that is really fast, really abstract, and really correct–but when I need to do quality work in a short time frame in real world projects, I still reach for Go.

                                                                                                                                                                                                                  1. 9

                                                                                                                                                                                                                    To me Go seems like a big wasted opportunity. If they’d only taken ML as a core language instead of a weird C+gc hybrid, it would be as simple (or simpler) as it is, but much cleaner, without nil or the multi-return hack. Sum types and simple parametric polymorphism would be amazing with channels. All they had to do was to wrap that in the same good toolchain with fast compilation and static linking.

                                                                                                                                                                                                                    1. 2

                                                                                                                                                                                                                      Yeah, I’ve often expressed that I’d like a Go+ML-type-system or a Rust-lite (Rust with GC instead of ownership). I get a lot of “Use OCaml!” or “Use F#”, but these miss the mark for a lot of reasons, but especially the syntax, tooling, and ecosystem. That said, I really believe we overemphasize language features and under-emphasize operational concerns like tooling, ecosystem, runtime, etc. In that context, an ML type system or any other language feature is really just gravy (however, a cluster of incoherent language features is a very real impediment).

                                                                                                                                                                                                                      1. 1

                                                                                                                                                                                                                        Nothing is stopping anyone from doing that. I’d add that they make FFI to C, Go, or some other ecosystem as easy as Julia for the win. I recommend that for any new language to solve performance and bootstrapping problem.

                                                                                                                                                                                                                      2. 3

                                                                                                                                                                                                                        Then, you have languages like D that compile as fast as Go, run faster with LLVM, have a GC, and recently an optional borrow checker. Contracts, too. You get super productivity followed by as much speed or safety as you’re willing to put in effort for.

                                                                                                                                                                                                                        Go is a lot easier to learn, though. The battle-tested, standard libraries and help available on the Internet would probably be superior, too.

                                                                                                                                                                                                                        1. 4

                                                                                                                                                                                                                          I hear a lot of good things about D and Nim and a few others, but for production use case, support, ecosystem, developer marketshare, tooling, etc are all important. We use a lot of AWS services, and a lot of their SDKs are Python/JS/Go/Java/dotnet exclusively and other communities have to roll their own. My outsider perspective is that D and Nim aren’t “production ready” in the sense that they lack this sort of broad support and ecosystem maturity, and that’s not a requirement I can easily shrug off.

                                                                                                                                                                                                                          1. 2

                                                                                                                                                                                                                            I absolutely agree. Unless easy to handroll, those kind of things far outweigh advantages in language design. It’s what I was hinting at in 2nd paragraph.

                                                                                                                                                                                                                            It’s also why it’s wise for new languages to plug into existing ecosystems. Clojure on Java being best example.

                                                                                                                                                                                                                  1. 8

                                                                                                                                                                                                                    If I understand it correctly, I like the idea. As far as I understand your focus is to provide a lightweight system written in Python and then for most use cases the deploy steps will just be written in standard shell commands with your shell function? I have always wondered whether a simple bash-script based idempotent deploy might be better for simple use cases than Ansible (background: I have written many ansible roles for my hobby deployments and it has cost me a lot of debugging and time)

                                                                                                                                                                                                                    Can you maybe elaborate a bit on:

                                                                                                                                                                                                                    • Why a Python surrounding is needed, i.e. what advantages it gives you?
                                                                                                                                                                                                                    • Why you needed to implement some functions like file or package as Python helpers instead of shell, because at first sight it seems to break the logic to use shell, but I guess there is some reason behind (package is one of the aspects I am a bit skeptical why it is abstracted, because they also do this in ansible, but many times packages have different names between Debian-based distributions and e.g. Archlinux anyway)

                                                                                                                                                                                                                    I might prefer it even a bit simpler/more reduced. When adopting new technology I came to love it when they support a scheme that I can continue working even if the technology dies. In this case this could e.g. work if you allow the user to write standard shell files (my-nginx-deploy.sh) and load these into pyinfra. If pyinfra might not exist anymore some day, the user could still execute the shell scripts manually.

                                                                                                                                                                                                                    1. 3

                                                                                                                                                                                                                      The most simple approach would be:

                                                                                                                                                                                                                      ssh my.server.com <setup.sh
                                                                                                                                                                                                                      

                                                                                                                                                                                                                      My question would be: Against this baseline, what problems does pyinfra solve?

                                                                                                                                                                                                                      For example, Ansible can work on multiple servers in parallel. It provides idempotent commands which you have to ensure yourself in shell. It skips commands already executed in previous runs.

                                                                                                                                                                                                                      1. 5

                                                                                                                                                                                                                        So pyinfra is built out of my personal frustrations with Ansible! pyinfra operations are idempotent similar to Ansible and it will skip commands just the same. The key differences:

                                                                                                                                                                                                                        • The deploy is executed in two phases, making it possible to do a “dry run”, this identifies where pyinfra can skip commands
                                                                                                                                                                                                                        • Instant debugging - I grew sick of debugging anything with Ansible, pyinfra just drops the output and the shell command itself
                                                                                                                                                                                                                        • Performance - not important but a small obsession of mine! pyinfra is significantly faster than ansible over large numbers of hosts
                                                                                                                                                                                                                        • Properly agentless - pyinfra does not require the target server to have anything other than a shell (vs Python + requirements for Ansible)
                                                                                                                                                                                                                      2. 3

                                                                                                                                                                                                                        So the idea is to roughly match some of Ansible’s abstractions - ie apt.packages(...) instead of executing the shelll directly. The advantage to this approach is pyinfra will only execute the underlying apt command if the package is not installed (by default). In this way pyinfra is very similar to Ansible.

                                                                                                                                                                                                                        This is the same for most other pyinfra modules, eg files.file, etc, which will check the current remote state before executing commands to update anything as needed. I have tried to remain true to each underlying tool, so there’s a dedicated pacman module, and so on.

                                                                                                                                                                                                                        Totally with you on the debugging thing! One of the reasons I started pyinfra was frustration debugging things with Ansible! pyinfra should always give the output and underlying commands that failed, making failures easily replicatable in a shell.

                                                                                                                                                                                                                        I think that answers your questions? Let me know if not/you’ve more :)

                                                                                                                                                                                                                        1. 1

                                                                                                                                                                                                                          There is at least one config management thing that uses bash: cdist. After looking at the examples/docs, the syntax doesn’t seem simple. I’ve never used it, so it could make sense after you spend enough time on the long learning curve for it.

                                                                                                                                                                                                                          1. 8

                                                                                                                                                                                                                            Each time I read about cdist I remember this:

                                                                                                                                                                                                                            Shell script is used by UNIX system engineers for decades. So when cdist is introduced, your staff does not need to learn a new DSL or programming language.

                                                                                                                                                                                                                            Which implies that « staff » knows how to write correct bash scripts… which, to be very honest, isn’t an easy task.

                                                                                                                                                                                                                            1. 3

                                                                                                                                                                                                                              I’ve been writing bash for 10 years and I think I’m halfway there. Hard to say for certain…

                                                                                                                                                                                                                              1. 2

                                                                                                                                                                                                                                I ran into a weird failure, recently, where bash redirection of files to stdin ( cmd < path) would result in no stdin input to the receiving command, but only when run under go generate, and only on one colleague’s machine.

                                                                                                                                                                                                                                I rewrote the script in golang. That’s the kind of BS I expect from JavaScript; I thought bash was better than that.

                                                                                                                                                                                                                          1. 28

                                                                                                                                                                                                                            There’s a huge funnel problem for computer science at the moment. Go and Rust have some pretty serious evangelical marketing teams, but they are a drop in the ocean compared to the emergent ultramarketing behemoth that feeds JavaScript to the new developer.

                                                                                                                                                                                                                            Part of this is that JS is constantly “new and modern” – with the implication that it’s a bandwagon that you’ll be safe on, unlike some of the old cobwebbed bandwagons. Constant change and “improvement” is itself a safety generator.

                                                                                                                                                                                                                            Another part is that it’s so easy to get to hello, webpage. The sweet spot on the racket is enormous. Every computer including your phone comes with at least 1 and usually several JS interpreters. Frictionlessness drives adoption.

                                                                                                                                                                                                                            The problem is that JS is, violently, garbage for most purposes. It’s a local maxima that has essentially everyone trapped, including the next generation. It’s not clear how we escape from this one.

                                                                                                                                                                                                                            1. 17

                                                                                                                                                                                                                              I feel about JS similarly to the way I felt about the x86 ISA taking over the world. “A local maxima that has everyone trapped”, that caused billions of dollars of R&D to be diverted into clever hardware, code generation, psychological treatment for programmers, etc. (I think the last thing is a joke, but I’m not sure.) One could even draw a parallel between the modern “micro-op” architectural approach to bypassing literal x86 in hardware and the WASM approach to bypassing literal JS in the browser.

                                                                                                                                                                                                                              1. 12

                                                                                                                                                                                                                                The longer it goes, the more this talk gets correctly.

                                                                                                                                                                                                                                1. 1

                                                                                                                                                                                                                                  I’m not sure any other ISA would have been better than x86 at the time x86 began to take off. Lots of companies were trying lots of things in the RISC world, and plenty of money was being spent on RISC hardware and compilers, and the x86 still began to take off. Intel had a lot of money? IBM had a lot of money, and IBM was working on RISC. HP had a lot of money, and HP was working on RISC. And so on.

                                                                                                                                                                                                                                  1. 2

                                                                                                                                                                                                                                    Of the obvious choices available at the time x86 began to take off (1984ish), I would say the 680x0 was a better choice, demonstrated by watching the parallel evolution of the two. At least the extensions to 32-bit and virtual memory seemed a lot more straightforward on the 68k. They both would have run out of steam and gotten weird by now, but I feel like it would have been less weird.

                                                                                                                                                                                                                                2. 2

                                                                                                                                                                                                                                  It’s not clear how we escape from this one.

                                                                                                                                                                                                                                  Simply wait. There are some better tools out there (for some value of the objective function “better.”)

                                                                                                                                                                                                                                  We’ve moved on from C, C++ and Java, all of which have had a similar level of death grip. JS is not invincible. The more users it attains, the more it suffers problems of perception due to the wide variance of quality. This gives rise to new opportunities.

                                                                                                                                                                                                                                  Really, I get a bit disappointed that everyone is content to rewrite everything every seven years, but, hey, it’s their life.

                                                                                                                                                                                                                                  1. 0

                                                                                                                                                                                                                                    I take strong offense at this proclamation of JavaScript as garbage. What kind of an opinion is that? If you don’t know JavaScript, don’t call out garbage. If you do know if well, you’ll see that it isn’t any more garbage then any other modern language for most purposes for which it is used - at least on backend.

                                                                                                                                                                                                                                    The entire ecosystem has some issues, but every ecosystem does. And considering that node was created only a decade ago and has vastly more users then some “serious” things that exist for ages, it’s obvious that there’s something that it’s going correctly.

                                                                                                                                                                                                                                    1. 29

                                                                                                                                                                                                                                      I take strong offense at this proclamation of JavaScript as garbage.

                                                                                                                                                                                                                                      You are offended on behalf of Javascript? People can dislike things that you like. It doesn’t do anything.

                                                                                                                                                                                                                                      1. 4

                                                                                                                                                                                                                                        Okay, inprecise choice of words on my part. I’ve wanted to state that I strongly disagree with his statement, english isn’t my first language and so I didn’t think every word completely through. I think you can still get the message. Be flexible a bit and you’ll understand it.

                                                                                                                                                                                                                                        1. 8

                                                                                                                                                                                                                                          I’m not sure what other languages you know, but compared to most popular languages:

                                                                                                                                                                                                                                          • Javascript has a weird type-system that doesn’t really pay off. Sure, they added inheritance recently (welcome to the 80s), but there are all kinds of inconvenient relics like having to do Object.keys(x) when in Python you can just do x.keys() (as in most popular languages)

                                                                                                                                                                                                                                          • Javascript makes it much harder to catch errors. Its implicit typecasting (undefined+“1”==“undefined1”, really??) and misuse of exceptions in the API means that when something goes wrong, you’ll often find out a few functions later, and then struggle to zero-in on the actual problem.

                                                                                                                                                                                                                                          • The ecosystem is too fractured. The lack of a curated “standard library” sends novices into all sorts hacky solutions, and makes other people’s code less familiar.

                                                                                                                                                                                                                                          I could really go on for a long while, and there are tons of example that I could give. I can say positive things too, like it has a good JIT, lots of interesting libraries, and some nifty syntax features (while lacking others), but overall think it’s a really bad language, that just happened to be in the right place and in the right time.

                                                                                                                                                                                                                                          1. 1

                                                                                                                                                                                                                                            For the record, JavaScript has always had inheritance, it just hasn’t had a class syntactical sugar that made it trivial to use until ES6.

                                                                                                                                                                                                                                            1. 1

                                                                                                                                                                                                                                              I wouldn’t call it bad. It just has bad parts. The == operator you mentioned is a trap for many beginners. On the other hand, there’s no inheritance problem because the inheritance was always there - you just have to know how prototypes work. The type system without extra tools and some practice is a pain. Yet the closure or say prototypical inheritance and composability you get is great.

                                                                                                                                                                                                                                              JavaScript got really lousy reputation because unlike, say, C++ or Java, everybody wrote it, not just people who studied software engineering for five years and know how to use tools, have structure and not break the rules.

                                                                                                                                                                                                                                              And it’s keeping the lousy reputation because it is still being done - randos adding jquery plugins for perfectly css-able animations even today.

                                                                                                                                                                                                                                              Plus it’s got 25 years of backwards compatibility to maintain, so those bad parts never leave. Yes, it has been at the right place at the right time - but many others have tried and are still trying.

                                                                                                                                                                                                                                              But despite all the bad parts and lack of standards, it’s still immensely flexible and productive and for a lot of use cases actually provides the best concepts to do them. Could you put something like elixir in a browser engine? Or java? Or Rust? Probably. Would it be better? Maybe, but I suspect not by much.

                                                                                                                                                                                                                                              I don’t know, I’m probably not seeing it. I’m not claiming that it’s a great language or that it’s even good for everything and everyone. But people only see the ads and single page apps where they don’t belong or where they simply don’t like it, and ignore a lot of directness that the language provides, look down on flexibility, and don’t allow the little language that could its deserved praise (where it does deserve it).

                                                                                                                                                                                                                                              Once again, as I’ve said in another comment - I don’t claim it’s the best language ever. I’m just saying it is not garbage. These days the tooling and the entire ecosystem is mature and there are no more language issues in writing a typical NodeJS application then in most other similar languages.

                                                                                                                                                                                                                                              1. 1

                                                                                                                                                                                                                                                Javascript has a weird type-system that doesn’t really pay off. Sure, they added inheritance recently (welcome to the 80s)

                                                                                                                                                                                                                                                It added inheritance as a sop to people who didn’t know composition and refused to learn. Are you not satisfied with that? Does it have to become a pure Smalltalk clone for you? Composition is more powerful but it’s less familiar. Now JS has easy ways to do both.

                                                                                                                                                                                                                                          2. 24

                                                                                                                                                                                                                                            I have a deep understanding of JavaScript; I promise that my opinion is rooted in experience.

                                                                                                                                                                                                                                            1. 6

                                                                                                                                                                                                                                              Even though you personally find Node impressive, there might be people who don’t get impressed by languages (or any software really).

                                                                                                                                                                                                                                              Being impressed or having respect (for a software) makes no sense. It is just a tool that should be used or discarded at will. Not a cultural icon.

                                                                                                                                                                                                                                              If you do know if well, you’ll see that it isn’t any more garbage then any other modern language for most purposes for which it is used - at least on backend.

                                                                                                                                                                                                                                              You have stated no arguments that support your conclusion. I believe that the jury is still out on the matter of language effect on productivity. All the studies I know of were totally botched.

                                                                                                                                                                                                                                              Anecdotally, I have seen more poor Node backends than Python ones. I have also seen less high quality Haskell backends, which confuses me greatly. Still, I wouldn’t go as far as to conclude that everything is the same crap.

                                                                                                                                                                                                                                              1. 6

                                                                                                                                                                                                                                                Denying the role of aesthetic judgement in programming is madness.

                                                                                                                                                                                                                                                1. 1

                                                                                                                                                                                                                                                  I didn’t state I find Node impressive. I do love it for the productivity it brings to me. And that is just the point of my reply. The guy claimed JavaScript is garbage, also without arguments. I’ve just pointed out that. No more garbage then any other language, in my opinion. If anybody brings arguments into this whole discussion, including the original post of the thread that claims people are pushing node, we can talk about with arguments. Otherwise we’re all just giving opinions and estimations.

                                                                                                                                                                                                                                                  Anecdotally I’m seeing much more crappy Java Enterprise and Spring backend code lately then node. Likely because I work at a java shop now. But I don’t claim that people are pushing Java exclusively for backend (even though they do at my company, we literally have 100% Java in my 800 people department), nor do I claim Java is garbage.

                                                                                                                                                                                                                                                  I hope that clarifies my objection to the claim of garbageness.

                                                                                                                                                                                                                                                  1. 4

                                                                                                                                                                                                                                                    I think you are right that JavaScript brings great initial productivity. Especially in the single developer case. For many simple tasks, it is easy to use node, easy to use npm, and easy to deploy code. Where I have seen problems that I know are avoidable in other languages is in its long term sustenance and operation, which are vitally important parts of software engineering.

                                                                                                                                                                                                                                                    Other languages have, for example, highly vetted and deep standard libraries of functions which are included in the system and move very slowly, which eliminates large classes of dependency management issues. Or, they have good type systems, which helps prevent common problems, especially in dynamic languages. Or they have exceptional tooling that enforces good practices. Or they are especially operable in production, with good intrinsic performance or observability characteristics.

                                                                                                                                                                                                                                                    But the most important thing, to me, is that most other languages have a culture of remembering, but this is distinctly lacking in JavaScript. I attribute this to many JavaScript programmers starting from scratch in their software career inside JavaScript, and not having broader exposure to the vast surface of other kinds of software. And I attribute it also to the “stack overflow” method of programming, in which rather than engineer your software, you assemble it from the guesses of others, losing fidelity and getting more blurry with each iteration.

                                                                                                                                                                                                                                                    It could sound like I’m being a pretentious jerk. I’ll confess to that. But having been a professional software engineer for now 32 years, and having seen probably a hundred languages and environments, the current JavaScript one is my least favorite. I appreciate that it’s one that you have significant personal investment in, but I would also encourage you to step out and up, and look around.

                                                                                                                                                                                                                                                    1. 1

                                                                                                                                                                                                                                                      Thanks, this also raises some quite relevant concerns. And I agree with these things. And now I have to fall back to the fact that despite these problems, it’s not garbage. I did step out and I try other languages and their frameworks, but I’m simply personally the most productive with it. And when I worked in teams where Node was used on the backend, the teams were professionals and mostly didn’t have problems with the language itself - maybe more or less then if it was done in, say, Spring or Rails, but I would say the typical problems are always stupid things like commas in the database where they break serialization somehow.

                                                                                                                                                                                                                                                      And that is the point of my original comment. Which was that I object to the claim that JavaScript is garbage. Maybe a lot of garbage is written in JavaScript today, but it in itself is not that, and can provide perfectly productive envrionment for doing our jobs.

                                                                                                                                                                                                                                                2. 6

                                                                                                                                                                                                                                                  I wouldn’t call JavaScript “garbage” myself, but it sure has some problems that few other languages have. [1] + [2] resulting in "12" being a simple example. JavaScript definitely took the 90s/00s vogue of “all things should be dynamic!” more than a few steps too far.

                                                                                                                                                                                                                                                  considering that node was created only a decade ago and has vastly more users then some “serious” things that exist for ages, it’s obvious that there’s something that it’s going correctly.

                                                                                                                                                                                                                                                  Well, just because it’s popular doesn’t mean it’s good ;-)

                                                                                                                                                                                                                                                  I notice myself that I often use tools that I know, even when it’s not necessarily the best fit, simply because it’s so much easier. Yesterday I wrote some Ruby code for a Jekyll plugin and had to look up a lot of basic stuff and made a few simple mistakes along the way; there was quite a lot of overhead here. And I programmed Ruby for a living for 2 years (but that was 5 years ago, and looks like I have forgotten much).

                                                                                                                                                                                                                                                  JavaScript is rather unique in the sense that almost everyone has to deal with it because it’s the only language supported by browsers[1], so there are a lot of people familiar with JS who would rather like to use it in other scenarios as well: not necessarily because it’s the “best”, but because it’s just easier as they won’t have to re-learn a whole bunch of stuff.

                                                                                                                                                                                                                                                  That’s not necessarily a bad thing, by the way; I’m all for giving people the tools to Get Shit Done. My point is merely that much of NodeJS’s popularity probably stems from factors other than intrinsic qualities of the language, runtime, and/or ecosystem.

                                                                                                                                                                                                                                                  [1]: Ignoring wasm, which isn’t quite ready for production-use, and “X-to-JS” compilers, which typically still require knowledge of JS.

                                                                                                                                                                                                                                                  1. 1

                                                                                                                                                                                                                                                    Oh, I wasn’t claiming that the popularity of NodeJS comes from it’s quality. I’m just saying JavaScript is not garbage, which the commenter claimed without argumenting it.

                                                                                                                                                                                                                                                    I mean, I know that [1] + [2] is “12” in JavaScript. But if you ask me how many times I’ve had a problem because of that in the last year, I would possibly be mistaken, but I would say 0 times.

                                                                                                                                                                                                                                                    Again, it’s not the best language and it has its problems. But it’s not garbage.

                                                                                                                                                                                                                                                    1. 2

                                                                                                                                                                                                                                                      I mean, I know that [1] + [2] is “12” in JavaScript. But if you ask me how many times I’ve had a problem because of that in the last year, I would possibly be mistaken, but I would say 0 times.

                                                                                                                                                                                                                                                      I find this interesting, because a few comments upwards, you state this:

                                                                                                                                                                                                                                                      The typical problems are always stupid things like commas in the database where they break serialization somehow.

                                                                                                                                                                                                                                                      It might just be me, but in no other language have I ever heard of specifically this problem. If you dig a little deeper, you’ll notice that there are a few fundamental issues in the language. But definitely the most prominent root issue is that types are treated extremely loosely, which causes all sorts of offshoot problems, like the two above.

                                                                                                                                                                                                                                                      I always try to think a bit more holistically about this, and when you do, you start to see this pop up everywhere. Just yesterday I was debugging an issue with a colleague where he accidentally was throwing a JSON-encoded string at a program where in fact he should have been taking the JSON document, extract a specific key’s string value and send that to the program. Basically the same thing: it’s too easy to mix up types.

                                                                                                                                                                                                                                                      I occasionally see this in Python as well: when you accidentally have a string instead of a list of strings; because of the “everything is a sequence” abstraction it’s too easy to mix things up, and you end up chasing down the rabbit hole before you figure out where it’s going wrong. It’s better if things error out early when you try to do something that makes no sense.

                                                                                                                                                                                                                                                      Having type-specific operators makes it easier to get your bearings when reading unfamiliar code, too, in my experience.

                                                                                                                                                                                                                                                  2. 3

                                                                                                                                                                                                                                                    And considering that node was created only a decade ago and has vastly more users then some “serious” things that exist for ages, it’s obvious that there’s something that it’s going correctly.

                                                                                                                                                                                                                                                    No, it means JS has a powerful monopoly (the web) and thus commands a huge mindshare. Some subset of those people want to take their painstakingly earned experience to the server.

                                                                                                                                                                                                                                                    1. 0

                                                                                                                                                                                                                                                      So, ‘heads I win, tails you lose’, eh? Good argument. /s

                                                                                                                                                                                                                                                  1. 6

                                                                                                                                                                                                                                                    There are vulnerabilities that can only exist in memory-safe languages (e.g. use of eval on untrusted inputs; eval tends to only exist in very high-level languages, which are all memory-safe)

                                                                                                                                                                                                                                                    eval exists for C programs for any system that can shell out to gcc. I’m not sure if this is a nitpick or not given the prevalence of gcc. Hopefully these kinds of security issues are rare for any programming language.

                                                                                                                                                                                                                                                    1. 9

                                                                                                                                                                                                                                                      (Author here)

                                                                                                                                                                                                                                                      eval exists on x86, just JMP to a buffer! (This worked better before no-exec was a ubiquitous thing). Still, I think it’s important to recognize that as an empirical matter, eval of source code doesn’t exist in memory-unsafe languages in a meaningful sense.

                                                                                                                                                                                                                                                      An early draft of this post said that I honestly wasn’t sure what belonged in this category :-)

                                                                                                                                                                                                                                                      1. 3

                                                                                                                                                                                                                                                        “Static typing where possible, dynamic typing where needed” argues that eval is quite pervasive:

                                                                                                                                                                                                                                                        Many people believe that the ability to dynamically eval strings as programs is what sets dynamic languages apart from static languages. This is simply not true; any language that can dynamically load code in some form or another, either via DLLs or shared libraries or dynamic class loading, has the ability to do eval. The real question is whether your really need runtime code generation, and if so, what is the best way to achieve this.

                                                                                                                                                                                                                                                        This is not just a theoretical argument, dynamic compilation and class loading is not unusual in Java, it’s the way Ruby’s current draft JIT works and Haskell wraps its own compiler in hint. Varnish’s config language is working in similar ways.

                                                                                                                                                                                                                                                        I still agree it’s rather fringe, but not unheard of and I’ve seen it considered in practice.

                                                                                                                                                                                                                                                        1. 2

                                                                                                                                                                                                                                                          Your paragraph on vulnerabilities specific to memory managed languages mostly talks about “unsafe deserialization”. I don’t see how unsafe deserialization is limited to memory-safe languages. Is that what you meant to imply?

                                                                                                                                                                                                                                                      1. 4

                                                                                                                                                                                                                                                        Where can I find more information about why Plan 9 is amazing, especially how it compares/contrasts to Linux or Unixes?

                                                                                                                                                                                                                                                        1. 10

                                                                                                                                                                                                                                                          I found this paper to be a wonderful walkthrough. I highly recommend getting a copy of 9front running, and going through some the exercises in the paper.

                                                                                                                                                                                                                                                          It’s very long, but definitely a great way to get a feel for how some of the concepts in Plan 9 are applied.

                                                                                                                                                                                                                                                          Edit: Since I was reminded how much I like this paper, I decided to submit it as a story.

                                                                                                                                                                                                                                                          1. 5

                                                                                                                                                                                                                                                            Some goodies from Plan 9 were ported to *nixes, for example procfs, unfortunately not all of them (Plan 9 like process namespaces).

                                                                                                                                                                                                                                                            1. 7

                                                                                                                                                                                                                                                              Unfortunately, the best piece of plan 9 is impossible to port: A unified, interposable way of doing everything, so you don’t have to think about huge numbers of special cases and strange interactions between features. 9p is, more or less, the only way to talk to the OS, and the various interfaces that are exposed over it can be transparently swapped out with namespaces, allowing you to replace, mock out, or redirect across the network any part of the system that you want.

                                                                                                                                                                                                                                                              1. 4

                                                                                                                                                                                                                                                                Well, Linux namespaces got 90% of the way there, although they certainly didn’t get their ergonomics.

                                                                                                                                                                                                                                                              2. 3

                                                                                                                                                                                                                                                                I just watched the video https://www.youtube.com/watch?v=3d1SHOCCDn0

                                                                                                                                                                                                                                                                Found the way the presenter explained the core concept very understandable. It is 40 minutes long.