News for hackers. Stuff that matters.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @06:57AM (#48597155)
First, your parent comment misunderstood what the section they were critiquing is referring to. It's not about nullability (which is orthogonal) but about reference/value projections.

Now, as a member of the Java team (although I'm not directly involved in Valhalla), I'm obviously biased so let me just say that both designers and fans of programming language features would do well to remember two things:

1. Opinions about features are almost never universal, even among experts, and almost each of them is about a tradeoff where different people prefer different sides. It is rare that some scientific study settles the issue.

2. These preferences are often not evenly split. Even when both sides are equally confident that their preference is the right one, sometimes 80% or 90% of programmers share a preference. The people with the strongest opinions are more often than not in the minority, because most programmers don't think so much about the programming language (nor, I would say, should they).

All of the language differences between .NET and Java fall in this "non-consensus" zone, and at least in one area I was deeply involved with, virtual thread, I can say that we thought that whatever we do we mustn't do what .NET did and that what they chose didn't work out well for them at all.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by nixon_why69 on Friday June 19, 2026 @08:32AM (#48597839)
Value types kind of definitively don't have null, right? You can have a zero int but not a null int. So nullability is not entirely orthogonal to value types, its an advantage for value types where they are practical.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @09:09AM (#48598161)
I didn't say nullability is orthogonal to value types; I said it was orthogonal to the two-projections world, which is what that text in the article was about rather than nullability.

As to value types and null, I'm not sure about the current picture, but the general idea is that you declare what semantic properties you want - identity or not, nullable or not, tearable or not - and then the compiler picks the best technical in-memory representation for each use. For example, the compiler could choose not to flatten variables that could be null in the heap but to flatten them in the stack. That's the general idea, but I'm not sure about the details, some of which may yet change.

More generally than just Java, nullability is often a property not of a type but of a variable. For example, in C, an int may not be null, but a pointer to an int may be. Now, in C, `int` and `int*` are two different types, but that's exactly a distinction that the original projection-spit design made and we wanted to avoid. But you could still end up with a variable that could hold either an integer or a null and another that may hold an integer but not a null, only this is separate from the reference/value projection, which combines both identity and nullability (in C, `int*` is not only nullable, but also has identity).

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by ScoobleDoodle on Friday June 19, 2026 @10:57AM (#48599370)
In case you want to edit it back in: in the 3rd paragraph second sentence, the star in your int* got gobble up by formatting to italics.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by zoogeny on Friday June 19, 2026 @01:33PM (#48600939)
> More generally than just Java, nullability is often a property not of a type but of a variable.

This is a tangent, but I'm not sure I follow this. Can you give an example to make this clear?

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @02:29PM (#48601616)
Yes, but it comes from Java having both runtime and compile-time types; it's harder to make the distinction in languages that don't have runtime types.

In Java, you can ask, `x instanceof T` (and this is a runtime test), which means, is x one of the values in the set of values allowed by T. `null instanceof Integer` is false, even though a variable of type `Integer` can be assigned a null. So you can think of `Integer x` as being `Integer|null x`, i.e. x can hold a null, even though `null instancof Integer` is false.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by zoogeny on Friday June 19, 2026 @02:47PM (#48601802)
I think I mostly got this, but just to test it, it would be like in Typescript where I might say:

    type Foo = { x: number; }
    type Bar = { x: number; y: number }
    type FooBar = Foo | Bar;
    function baz(x: FooBar) {
      if ('y' in x) {
        // compiler now knows x is a Bar
      }
    }
In this case, the variable `x` has a property that is determined by the compiler based on control flow. i.e. it isn't explicitly carried by the type of `x`.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by stickfigure on Friday June 19, 2026 @03:09PM (#48602062)
> More generally than just Java, nullability is often a property not of a type but of a variable

I'm going to hard disagree here. And the syntax proposed in the Null-Restricted Value Class Types JEP is a major step backwards.

I want to banish nulls from my codebase, completely. I can currently do this with a variety of annotations (at the package-info.java level) and tooling, though it's not integrated well with the language.

Forcing exclamation marks into every variable and parameter is a lot of annoying noise that quite simply nobody will do. The default should be non-nullable, especially for value types.

Declaring whole types as non-nullable is less noisy and errorprone than annotating every variable declaration. If you aren't going to give me "declare the whole codebase as non-nullable" then at least give me something coarse-grained.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @03:18PM (#48602175)
> the syntax proposed in the Null-Restricted Value Class Types JEP is a major step backwards. Forcing exclamation marks into every variable and parameter is a lot of annoying noise that quite simply nobody will do. The default should be non-nullable, especially for value types.

Then you didn't read the JEP draft (it's not an accepted JEP) carefully. It says, under "future work":

Providing a mechanism in the language to assert that all types in a certain context are implicitly null-restricted, without requiring the programmer to use explicit ! symbols.

In other words, the draft already incorporates your point, but JEPs (both drafts and actual JEPs) follow the pattern we've found to work so well, that features are best delivered piecemeal rather than in a big bang.

Having said that, I don't know the current plans for this matter, as that document is only in Draft status, so saying it's good or bad is pointless, as it's not even a proposal yet, just something being explored.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by stickfigure on Friday June 19, 2026 @03:49PM (#48602493)
It's a proposal for a proposal, fine. Consider this my proposed feedback.

I don't think this syntax is desirable as currently proposed, and that one line under "future work" is doing far too much lifting. My sincere hope is that there are people closer to the process that also feel this way, they will provide similar feedback, and the next draft will be something completely different.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @06:15PM (#48603897)
Except we like delivering features by pieces, so unless your proposal is to first deliver global flags with no instance-specific control and later add more control (and I think you're not suggesting that), I don't see any difference between what you're suggesting and what that draft is suggesting. That a one-line under "future work" is doing a lot of lifting is just how we usually do it (and it's okay, people always complain, but we've tried the big-bang approach and this one just works better for us).

So consider that draft as an idea for how the site-specific nullability annotations could work rather than an idea for how nullability could work in the language in general.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by stickfigure on Sunday June 21, 2026 @01:06PM (#48620549)
> how the site-specific nullability annotations could work

That's fine but it's still a bad choice. The problem is that it defaults to everything nullable and adds noise for non-nullable. This is backwards; in the overwhelming majority of software that people use Java for, non-null is the common case and nullability is the exception.

Kotlin and Typescript got this right. Nobody wants! to! write code! like! this! And they won't, so the feature won't get used and we're back to everything being nullable.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Sunday June 21, 2026 @05:12PM (#48622648)
> it's still a bad choice

Except there's no choice here. It's a draft of an exploration of a portion of a feature.

Drafts are ideas that have not even been submitted for consideration for inclusion in the roadmap. You can find drafts over ten years old that have long since been superseded by other ones or abandoned altogether: https://openjdk.org/jeps/0#Draft-JEPs. Some JDK engineers write JEP drafts when they feel they get close to something they would like to propose, while others write drafts for pretty much any idea they have.

> The problem is that it defaults to everything nullable and adds noise for non-nullable

It doesn't, though. Even if this draft ever becomes a JEP (and I don't know if it or anything like it will), in its present form or another, it would still, like most JEPs, describe only part of the feature. It's perfectly on point for one JEP to describe the explicit nullability annotations, while another describes the defaults. Smaller features than this have been split into two or three JEPs. This is just how Java features have been described and delivered for years now (see how many JEPs patterns were split into: https://openjdk.org/jeps/0).

It's perfectly okay to dislike some design, but I find it strange to assume, based on a draft of a portion of a feature that one of the most experienced and successful programming language design teams in the history of software is likely to get it wrong. Maybe wait until there's an actual proposal and a roadmap for the complete feature before critiquing it? It's like seeing a draft of some building's foundations by a prestigious architectural firm and saying, these idiots forgot to plan a roof.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by stickfigure on Monday June 22, 2026 @09:56AM (#48630205)
This is a strange conversation; you must be misinterpreting me.

I'm not saying that the people who wrote this are dumb, or that Java is a bad language, or that it's time to move to Kotlin, etc. I use Java every day. I pick Java for greenfield projects. I'm on Team Java.

I'm saying I don't like this proposal. I happily accept that this proposal might not become part of the Java language. That's great! I'm spending time writing this in public specifically to discourage it in some tiny way.

It would be fair to tell me "you should write this to the proposal writers directly". And I understand how the language snobbery on HN might make you feel defensive - I often feel that too. But I think my criticism here is valid.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Monday June 22, 2026 @02:10PM (#48633744)
> I'm saying I don't like this proposal

And I'm trying to tell you that this document is not what you think it is. It's a rough sketch of a building's foundations and your critique is about the roof. Even if this were to become a proposal, it's likely the matter of defaults of this feature will be covered by a different JEP, because Java features are usually broken down into multiple JEPs. What you're complaining about may be part of the feature, but it is not covered by this document. If this becomes a JEP and another JEP talks about nullabilty defaults, then you could criticise the selection of defaults, but that particular aspect of this feature is outside the scope of this particular document. So one, this is not a proposal, and two, you haven't seen the description of the part of the feature you want to criticise.

We are well aware that splitting features over multiple JEPs can invite such misunderstandings, but that doesn't change the fact that Java features are, at least currently, split over multiple JEPs. We are also well aware that if this does become a proposal, adding ! everywhere is not what we want, but we want to cover that aspect in a different document, as we usually do. Most Java users aren't confused by this because they don't read the JEPs at all, but such splits help focus the discussion on one aspect of a feature at a time. So your desire for a non-nullable default is very understandable, it's just not relevant as a critique of this document.

For example, the virtual threads JEP described a pinning limitation. We knew it reduced the applicability of that JEP and said as much. We just wanted to address it in a different JEP, and so we did (https://openjdk.org/jeps/491). Ever since the JDK switched to time-boxed, semiannual releases, this is how we've delivered features: in multiple pieces. The same applies to Valhalla.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by tsimionescu on Friday June 19, 2026 @08:59AM (#48598062)
This won't be true in Java, though - in Java, you will have null Integers at least. It seems that int will remain a different thing entirely from Integer, and will remain a JVM-only concept.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by joe_mwangi on Friday June 19, 2026 @12:08PM (#48600142)
But with null-restricted types, Integer! and int has no difference semantically and representation. They plan to introduce null-restricted types in future.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by gf000 on Friday June 19, 2026 @08:47AM (#48597965)
You can have a null int, it's called Integer.

What was taken away is the other, identity-having functionality of Integer and similar (e.g. no synchronization).

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by resonious on Friday June 19, 2026 @08:37AM (#48597878)
This is great advice and it applies to a lot more than just language features. Different architecture, deployment setups, QA approaches are all like this. It's always "approach A is no good", "but company X uses approach A and they're doing very well", "yeah but look at all of these problems they have". Maybe a fair argument but the approach B people also have their fair share of problems...
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by throwaway2037 on Friday June 19, 2026 @12:53PM (#48600535)
GUI frameworks have similar arguments around their design choices.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @02:18PM (#48601470)
What's funny is that the only languages in the same popularity league as Java are Python and JS/TS (and possibly C and C++ if you want to extend things to more domains) yet I rarely ever hear people saying Java should be more like these languages. It's because many of the people who dislike Java also don't like any of the most popular languages (even those who like, say, Python better don't think Java should be more like Python).

These people may point out that languages become more or less successful not because of the things these people care about but because of other factors. And they're right, but then the question is, shouldn't a smart product team focus more on the things that actually matter more to more people?

Programming languages are tools, and so their value is not intrinsic, but comes from the value of the software they're used to create. Now, some people claim that Java's success is largely the result of it being one of the most hyped languages of the late 90s and early 00s, alongside VB, Delphi, FoxPro, and C#. But this claim doesn't stand up to even the slightest scrutiny.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by bradleyjg on Friday June 19, 2026 @07:05PM (#48604330)
I definitely see people asking for features from c++. In part because virtually every feature is in c++.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by wbl on Friday June 19, 2026 @10:11PM (#48605675)
That tends to be a reason to say no- remember the vasa!
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by ptx on Friday June 19, 2026 @11:43AM (#48599895)
What's wrong with what .NET did with threads? Having async tasks sharing the GUI thread seems like a nice feature. Will we be able to use virtual threads and structured concurrency with Swing, e.g. to wait for a background task in an event listener?
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by revetkn on Friday June 19, 2026 @11:58AM (#48600053)
Regarding "What's wrong with what .NET did with threads?", see https://cr.openjdk.org/~rpressler/loom/Loom-Proposal.html (relevant part below):

  An alternative solution to that of fibers to concurrency's simplicity vs. performance issue is known as async/await, and has been adopted by C# and Node.js, and will likely be adopted by standard JavaScript. Continuations and fibers dominate async/await in the sense that async/await is easily implemented with continuations (in fact, it can be implemented with a weak form of delimited continuations known as stackless continuations, that don't capture an entire call-stack but only the local context of a single subroutine), but not vice-versa.

  While implementing async/await is easier than full-blown continuations and fibers, that solution falls far too short of addressing the problem. While async/await makes code simpler and gives it the appearance of normal, sequential code, like asynchronous code it still requires significant changes to existing code, explicit support in libraries, and does not interoperate well with synchronous code. In other words, it does not solve what's known as the "colored function" problem.
Regarding Swing, virtual threads are "just" threads so no reason they (and structured concurrency) can't be used.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by Athari on Friday June 19, 2026 @02:40PM (#48601730)
The colorless functions approach has well-known disadvantages though, including providing less control and making interop a pain. It isn't like one approach is the correct one and another is a mistake.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @08:30PM (#48605000)
> including providing less control and making interop a pain

This is true in some languages but not in Java. The limitations (and performance cost) are not from the nature of continuations/stackful coroutines/"colourless functions", but from their interaction with other constraints and existing designs in the language. E.g. in Java, virtual threads have zero impact on FFI.

In general, the costs and limitations associated with a feature in language X don't extrapolate to language Y, because they often stem from interaction with existing constraints in language X.

The design of FFI is a very common source of problems for various features. For example, if the FFI is designed such that you frequently pass pointers to to objects to C, that can have a big impact on other features. In Java, you nearly always only pass pointers to "off heap" memory, i.e. memory that's not managed directly by the JVM. While this has no performance cost, you could say that this, in itself, has some convenience cost, except Java programs need to rely on FFI much less than other languages, so the overall cost to convenience is low.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by int_19h on Saturday June 20, 2026 @12:27AM (#48606340)
How can green threads have zero impact on FFI in the presence of callbacks across the boundary? I mean, as soon as the other side uses TLS in any way, for example, you have to figure out how to handle that, and it's not free.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Saturday June 20, 2026 @08:12AM (#48608671)
In every user-mode thread or stackless coroutine (async/await) implementation I know, the construct is pinned (i.e. can't be preempted) while there's a foreign frame on the stack. There is no advantage to either design on that front.

But 1. there's no speed penalty in Java for doing that, and 2. In Java, calling native functions that block (which is the only time this limitation matters) is rare, especially in high concurrency situations where you'd use virtual threads in the first place.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by ptx on Friday June 19, 2026 @03:32PM (#48602318)
So does Java provide an API for continuations or just the virtual threads hidden behind the threading API? You can't use threads to wait for something on the UI thread (which is why e.g. SwingWorker exists), but you can with await.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by jayd16 on Saturday June 20, 2026 @12:33AM (#48606365)
Look at their structured concurrency stuff. But IMO it ends up gaining not too much over async/await with worse syntax.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by revetkn on Saturday June 20, 2026 @07:16AM (#48608373)
There is no public-facing continuations API afaik.

Structure concurrency/virtual threads seem like a good fit for Swing; just have your event handler fire off virtual thread[s] and do your work and call SwingUtilities.invokeLater to schedule the result to be applied on the event loop thread when you're done. Structured concurrency simplifies managing groups of concurrent tasks, cancelation, etc.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by jayd16 on Saturday June 20, 2026 @12:27PM (#48610502)
Regarding coloring...

You still can't block in UI code, right? You don't know whether you're on a virtual thread or the UI thread (even if its virtual) by design. You still have to bifurcate your APIs into blocking and non-blocking, don't you? Virtual threads will help you keeping the CPU fed but it won't handle separating UI and non-UI work, or know when a frame deadline ends.

Have there been Swing specific updates to deal with that?

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by mixolydianagain on Friday June 19, 2026 @03:10PM (#48602075)
> All of the language differences between .NET and Java fall in this "non-consensus" zone

Curious if you think fibers vs async/await is still in this zone (amongst experts). It seems fibers are objectively better. But I'm no expert*

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Friday June 19, 2026 @03:15PM (#48602130)
I think user-mode threads are better when the language already has threads. I'm not sure they would have been better for JS. But yeah, this one is probably less controversial than things like properties and extension members, which we also said "yeah, nah" to.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by sroussey on Saturday June 20, 2026 @01:37AM (#48606630)
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by aardvark179 on Saturday June 20, 2026 @10:33AM (#48609513)
Although the work being done to enable multiple threads in JS is impressive I think it will be hard to make robust in many casss without locks, or fairly strict limits what operations can be performed on objects shared between threads.

The property lookup and modification process in JS is complex enough as is, is not specified in an atomic kind of way, and has many opportunities for user code to be run as part of accessor properties. Enabling it in multithreaded implementations is tricky without opening up deadlocks when modifying property collections, and even with that could likely be broken by some suitably evil code. Ive worked on more than one implementation that offered some degree of multithreaded access and it’s generally only safe when limited to simple properties.

Async / await avoids those issues because none of the places where user code can be executed allow async code, so there is no opportunity for the world to be changed under your feet during something like property access.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by sroussey on Saturday June 20, 2026 @01:54PM (#48611325)
https://tc39.es/proposal-structs/

Structs, Shared Structs, and Synchronization Primitives

There are a few things that would be required to make it all work, this would be one of them.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Saturday June 20, 2026 @12:21PM (#48610442)
I'd be very surprised if Google go for it.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by jayd16 on Saturday June 20, 2026 @12:26AM (#48606334)
This is pretty funny...

"All differences are opinions....except what .net did. Those are wrong!"

I personally think Java continues to to waste a lot of time and come to a slightly more verbose and worse solution again and again.

Structured concurrency is like c# async/await with less sugar. Streams are just LINQ but worse.

It's probably exactly because of the "not like .NET! We must be different to explain being late" mentality.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by egeozcan on Saturday June 20, 2026 @01:07AM (#48606514)
As a person with a lot of .NET experience but has been working on other tech since 6 years, the wow effect I had from using LINQ has never been repeated with anything else.

It felt like magic, maybe too much magic, but so useful nevertheless.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pjmlp on Saturday June 20, 2026 @06:27AM (#48608094)
LINQ comes from FP, and was introduced into C# via Haskell, and actually the first version (.NET 3.5) was quite similar to Smalltalk or Common Lisp collections.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Sunday June 21, 2026 @09:01AM (#48618602)
Java is getting that power in a different, more orthogonal way, IMO, through Project Babylon: https://openjdk.org/projects/babylon/
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by parampampam on Saturday June 20, 2026 @01:20AM (#48606568)
Nothing funny there. They shared their opinion as an example. Yes it differs from others, that’s what they was talking about.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by gf000 on Saturday June 20, 2026 @05:04AM (#48607622)
Both languages/runtimes are decent, stable and good choices for running production systems.

They have different philosophies though, C# is mostly "give the developer a complex toolkit so they can do whatever they want, but keep the runtime simple", while Java is more like "keep the language as simple as possible, and put new features mostly into the runtime making it more complex, but benefiting even old code".

Async vs virtual threads is a clear example of that. The former makes the language much more complex, and has a huge surface area where it may clash with other features, so a developer has to remember all of these. But it's a simple machinery under the hood.

Meanwhile virtual threads don't change the language at all, it's the same as it was with Threads, but under the hood it is a very complex feature.

And in this particular instance I think it is quite clear cut that Java made the correct decision, for the most common use case of these languages having non-blocking IO "automatically" makes for significantly better user experience.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by jayd16 on Saturday June 20, 2026 @12:10PM (#48610331)
I do think Java is a fine language but I don't really agree that it looks more simple in any way shape or form.

For things like UI programming where you need a main thread or where you do need a cross language OS thread, I think Java is going to end up more complex. Under the hood it is very complex and that _will_ show itself.

So from my perspective it's not virtual threads, it's virtual threads with structured concurrency vs async/await. When you look at it that way, the comparison of complexity is certainly not seamless or simple.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Saturday June 20, 2026 @08:07AM (#48608636)
.NET do what they do because they believe many people like it, and we do what we do because we believe many people like it. Because different developers like different things, we may both be right. The only explanation to why we do what we do is that we believe it works well for us, and we know what everyone should know, which is that what we do can't be universally liked because developers have different preferences.

But that doesn't mean the preferences are equally distributed. Some people liked Betamax's better picture quality while others liked VHS's better recording times, but they didn't do it in equal numbers. And that's what's funny, because there are two languages doing as well as Java or better (one of them is much more popular), and yet what's almost universal is that when people say "Java is worse than X", X is invariably a language that's doing much worse than Java.

I'm not saying that there isn't much to learn from less popular languages, but the claim "Java is consistently making the wrong decisions compared X" doesn't make sense when X is consistently losing to Java.

And I can even give you the secret to our strategy: Make Java the language that people who choose it regret less than people who choose other languages.

Re:Project Valhalla, Explained: How a Decade of Work Arrives... by jayd16 on Saturday June 20, 2026 @12:14PM (#48610371)
I like Java too but this is pure cope. By this logic Python's threading model is the best.
Re:Project Valhalla, Explained: How a Decade of Work Arrives... by pron on Saturday June 20, 2026 @12:18PM (#48610413)
I think you misunderstood my point. I'm not claiming that the most successful products necessarily have all the best features. I am saying that the claim that "team X consistently makes worse decisions than team Y" is hard to support if team X is winning. At least some of their decisions are probably better, and those ones also probably matter more.