Hacker Newsnew | past | comments | ask | show | jobs | submit | iherbig's commentslogin

I'm not sure if you do, honestly. The point of the exercise is exactly the ambiguity that stood out to you.

Also, the question was very explicitly not asking if an ambulance in the park is "okay." The question is asking is it a rule violation.

It's an excellent analogy, in my opinion, because what it's trying to be analogous to is the general ambiguity of language that makes content moderation difficult. It's hardly even an analogy because it is about precisely an identical concept: determining whether behavior is violating a rule.


That makes a ton of sense. I was always confused by that. Reddit has a ton of rules in place, particularly against advocating for violence. I reported a few comments that called for death penalty for someone. Those comments were always greenlit. Maybe I just take stuff to literal. But some people sure have a hard-on for the death penalty...


In the US legal system, probably elsewhere as well, we have the concept of an "affirmative defense." That means "I committed the crime, but it's OK because of extra facts." That's different from denying one or more elements of the crime.

Example #1: I didn't poison Joe. I was out of town when it happened.

Example #2: I poisoned Joe. He had been sentenced to death, and my job is prison executioner. That's why I injected him with poison.

The second example is an affirmative defense. A murder occurred, but it was not illegal because it was authorized by the state.

I have a feeling that lawyers who took this quiz were more likely to answer yes for the ambulance and police car, but nonlawyers would answer no. That's because most people were answering the question "would they get in trouble?" But lawyers might have been thinking "is there a valid defense to a violation that actually did occur?"

In your example, calling for the death penalty isn't advocating for violence because executing someone in the justice system is legally permissible (let's not get into ethics or morality). The Reddit rule is generally understood to cover only illegal violence.


It specifically notes that some jurisdictions might have exceptions to this sort of rule, but that in this case there isn’t one.


It doesn't say that. It says to ignore your own real life jurisdiction.

There may or not be exceptions in universe that this sign is in. The sign clearly has no exceptions however.


Exactly. By the strictest literal terms a rule prohibiting any call for violence would prohibit things which many people would find entirely unobjectionable like standing up for a country’s right to defend itself (with violence) against an aggressive invader.

All rules have countless unspoken caveats and are inherently only able to be interpreted in a cultural context; rules cannot be made so specific as to remove the need for that context. Problems come in when essential parts of that context are not shared by everyone who interacts with the rules.


> Exactly. By the strictest literal terms a rule prohibiting any call for violence would prohibit things which many people would find entirely unobjectionable like standing up for a country’s right to defend itself (with violence) against an aggressive invader.

Having rules against advocating for violence means that you want to prohibit such calls (otherwise you would have written down such exceptions and admit that calling for violence is sometimes OK).

Let me put it this way: what Reddit secretly wants is not standing up against advocating for violence, but avoiding the reputation risk that might happen if there exist to many post that advocate for violence in a way that causes an outcry.

In other words: the hidden problem is rather Reddit's "secret" agenda behind the rules.


I think that the rule, usually unstated, is: "it's o.k. if it doesn't make me look bad", or maybe "it's not a problem, if it's not a problem".


For whatever reason, it seem like people usually exclude acts undertaken in connection with the state’s monopoly on violence from the scope of these things.


The spirit is that governement is an extension of "the people" and as such this violence is an extension of their own - i.e. in a healthy society the violence perpetrated bt the state is fully known and sanctionned by its citizens.

Like having prisons or letting police use lethal force on dangerous people, some things fit this description - but at some point lines have to be drawn and the leashes have to be reigned in if the violence is not agreed upon anymore - institutionalised racism and the likes.


> Reddit has a ton of rules in place, particularly against advocating for violence. I reported a few comments that called for death penalty for someone.

Note that taking it literally even calling for imprisonment is advocating for violence (unless convict accepts imprisonment voluntarily and not under threat of legal violence by law enforcement).


But what if the statement is in context of jokes, like:

A: *saying something stupid as a joke B: "I hope the country will impose death penalty to those who support it"

Or when it's used as discussion, like this, is it violating the rule?


Strictly speaking, I think calling for the death penalty is advocating for a legal ruling. The violence following such a ruling is a second-order consequence.


"Calling for someone to be shot is advocating for a lever to be pressed. The violence following such a pressing is a second-order consequence."


Calling for someone to be shot is a call for violence. Calling for a trigger to be pulled is not.

The death penalty is a legal ruling that is often not even the final decision.


Sure, if you don’t understand causality.


It's calling for the state to kill someone. Doesn't seem any less an advocation of violence than advocating for a vigilante killing or advocating for some specific person to do the killing.


You don’t think there is a difference between the state killing someone and a vigilante killing someone?


I was solely addressing the fact that both are violence, and asking for either is advocating for violence. Exercise for the reader to decide if they think either is moral or just, which is a completely different issue.


By that logic, no one is advocating violence unless they intend to participate in the violent act directly. It’s a logically consistent position, but it’s also a highly implausible one.


Of course one can advocate for violence without participating in it directly. For example, you could call for a riot. Or for the death of someone directly.

No reasonable person would confuse “the traitor should get the death penalty” with “kill the traitor!”.


I guess I’m not a reasonable person then? Advocating for state sanctioned killing is no different to me, in terms of advocating violence per se, than advocating anyone else do the killing. There are surely other distinctions to be made, but “the state should implement violence” isn’t categorically different from any other actor in the same configuration.


Now the interesting question is, what would happen if I was to ask for the death penalty on a crime that does not carry the death penalty? Or only carries the death penalty in countries with legal systems that we object to, like Iran?


I doubt their mother sees it in such bloodless terms.


Why is that relevant?


I think what's being noted is slightly more nuanced than what you're responding to. The analogy is slightly flawed because a few additional indicators remove a lot of the ambiguity, which is possibly not the case at all with moderation, which is often about far more nebulous things. In that way, the comparison is flawed.

Asa an example, I'm seeing most people (based on people saying they match the majority at 11%, but there's some indication that may be broken) that chose to go with the common understanding of what the sign meant (as opposed to some literal definition they decided to follow) seemed to have an inherent idea of how we might better define "vehicle" to match those expectations (such as whether the conveyance provides power itself or whether it requires power from a person, or whether it houses a person, or whether it is assisting normal motion in some manner).

Also, without further analysis of the data it's hard to tell whether removing or redefining slightly a few questions might bring a core consensus far above 11%. And even if we can get this specific question to a good consensus, there's no real proof that it indicates that content moderation could similarly come to a consensus on specific concepts (I doubt it could for many important things).

In those ways, this is a clever and interesting experiment to take part in, but I'm not sure how much it really says about content moderation, as I think (as perhaps the GP thinks) it was made slightly too simplistic in an effort to be approachable, and in that case lost some of the aspects it was trying to convey.


I mostly thought it was easy to tell if the rule was being violated (the vast majority disagreed with me), but where it gets much more complicated is deciding if a rule should be allowed to be violated. I think most people don't want rules that are blindly enforced without consideration to circumstance/context. We carve out exceptions to rules everywhere in life.


I do get the point, I'm saying that the analogy was bad. The point could have been made better.


it's a nearly perfect analogy for a laymans view of what content moderation should look like.

"my children will see no violence" looks wonderful on paper but there are a great many edge cases where this simple rule is plainly broken all the time in harmless ways.

in reality, what crosses the line one has in mind when they create the simple rule is created is far, far more complex than anyone who makes these rules is prepared to admit.

there is so little "black and white" in these things; it's almost entirely "grey" areas. that's what this quiz is meant to convey.

it is extremely effective at this.


> it's a nearly perfect analogy

People are saying that it's not, and that it's a strawman for what a layman's view of what content moderation should look like.


Heh, I thought the quiz was almost entirely not grey areas. It seems like the police car and ambulance were about as gray as it got, the others seem pretty obviously non-gray.


That's why the analogy is so good! The police car and ambulance were the most obvious ones to me (other than the Honda Civic); surfboard and ice skates were much tougher. It shows how we're really seeing things through our own lenses, even when they seem so obvious that no one could conceivably disagree.

Also interesting: the fact that 50% more people described a skateboard being used as a vehicle than a skateboard being carried.


Are you saying that everyone easily agrees on what a “vehicle” is, except in the case of a police car or an ambulance?

That roller skates are clearly either a vehicle or not, but a police car is a gray area?

note that the question was whether the rule “no vehicles in the park” has been violated, not whether it should be allowed to be violated.


You and antihero are talking about two different kinds of "good listening," though.

"Being a good listener" has both a practical and a social component. You are referring to the social component ("in Japanese culture..."). The tenets of social interactions in Japanese culture which have been ingrained in speakers of the language to one extent or another. The performance aspect of the act of listening.

antihero is talking about the practical form of "good listening" when they say "that makes you a terrible listener though." That is, what is the function of "listening" in a social interaction? I would hazard a guess that they believe the function of listening is to understand what another person is saying.

And by that benchmark, an individual who is not actually reaching any sort of understanding is a "bad listener" irrespective of how successful they are at performing the cultural/social component of the act of listening.

There's the additional implication that because signaling you are understanding when you are not leads to misunderstanding (which is the antithesis of the intended function of listening), it makes the listener an even worse quality listener than if they were not performing.


I agree, they are using two different definitions of "good listening". I'd say the "fit in with the social interaction" one is usually the most relevant. This reminds me of Wittgenstein's "language games"[1]. Maybe I'm butchering Wittgenstein's thought, but my understanding is that language works in a social situation as a game, as an activity where things "work ok" or don't work ok. It's not about me communicating my inner mental state and you making sure you're understanding my inner mental state (Wittgenstein's argument is that this is not generally possible, but also maybe it's not even what we usually care about)

Of course, when you're in a specific setting (such as doing science or a police investigation) the other definition can be more relevant.

[1] https://en.wikipedia.org/wiki/Language_game_(philosophy)#:~:....


OP was not suggesting that search engines cannot be used as a tool in the process of taking the test. Rather, that your test should not be something which a candidate can Google a pre-existing solution to and submit as their own.


While I agree with both sentiments, I find the juxtaposition between the two interesting as it implies a relationship between them but they don't seem to be related at all.


>...he should seriously consider putting more effort into the documentation and distribution side.

In addition to what other people have said, Blow is explicitly working on documentation over time and closed beta users have access to a fair number of documents detailing both language features and the philosophy behind the language.

One huge reason why the language IS still in closed beta is because Blow believes heavily in not releasing half-assed work. Documentation is a part of that.


It is no longer in the language. Much of this document is extremely out of date.


It is available as a metaprogram in the standard library, afaik. Someone asked about it on one of his streams before.


"This version of the sentiment which you did not express is totally reasonable, therefore it seems nuts to hate people for the sentiment that you DID express."


I would imagine it's because WSL is a terribly confusing name itself for a lot of people.

There are two ways to read "Windows Subsystem for Linux":

1. This is a subsystem that runs on Windows that enables Linux binaries.

2. This is a subsystem that runs on Linux that enables Windows binaries.

The confusion comes in the fact that when I write those two sentences, I naturally want to write "This is a subsystem FOR Windows..." or "This is a subsystem FOR Linux... ." I had to consciously avoid using "for" in that sentence to highlight the problem.

So when someone who doesn't know what the thing does reads "Windows Subsystem for Linux" they may walk away with the false impression that the subsystem allows Windows binaries to run on Linux. Likewise, what you're seeing now is that people are seeing "DOS Subsystem for Linux" and thinking that this enables you run DOS on Linux.


The WSL terminology really only makes sense if you are aware that Windows has the concept of subsystems - and which is why swapping other labels makes even less sense. I.e. the run-Windows-on-Linux thing would probably not be called Linux Subsystem for Windows, because what is a "Linux Subsystem"?

And of course WSL2 isn't a subsystem anymore, but is stuck with the product name. ¯\_(ツ)_/¯


A "Linux subsystem" is a Linux system that is a part of a bigger system. And "Linux audio subsystem" is an audio system that is a part of Linux. And if you swap the words, you get "audio Linux subsystem" which doesn't make sense, not really.

So the proper name would be "Windows Linux subsystem", but I concede that it does sound really weird (because both Windows and Linux are the same kind of things, they're OSes).

And of course, if it was named "Windows's Subsystem for Linux", there would be much less confusion, but apparently the English for some reason doesn't use the possessive case here (although that's the perfect place for it) and prefer to use the noun as a possessive adjective.


This is helpful, but the composition rules are weird and confusing.

It's true that a Linux Subsystem is a subsystem of Linux, but an "X for Linux" is a component of Linux or an application for Linux.

When you put them together, it seems that the "for" wins the battle. In parsing terminology, it has lower precedence (though I'm sure the actual rules of English are more complex than that indicates).

I'd love to see an actual linguist comment on why this phrase is so confusing.


I have an English degree and can confidently say the issue is the implicit understood possessive in the correct parsing. As it stands, “for” dominates mentally because the phrase obviously needs a possessive to make sense and “for” denotes possession. If it were “Window’s Subsystem for Linux” or “DOS’s Subsystem for Linux”, explicating the proper possession, the parsing trouble would disappear.


So would just saying Linux subsystem for windows.

Which was raised when this name came up but they didn't like that Linux came first so went with gymnastic language instead.

Its even more obvious with this new name.

Its a Linux subsystem for DOS.


You could use the possessive form here: "Windows' Subsystem for Linux", but that's not a thing product managers like to use in naming...


It probably had an internal name like "winix" or "lindows" - but PM took the reins and came up with a much worse name, as is tradition.


Oh yes. My favourite example is [0] (and the parent twit).

[0] https://twitter.com/ericlippert/status/1205372172534874112


Oh, true, Linux actually uses the term in that context, somehow didn't think of that.


> And of course WSL2 isn't a subsystem anymore, but is stuck with the product name

Even WSL1 is not a classic Windows NT subsystem. Its implementation (picoprocesses) is quite different from that of the classic Windows NT subsystems (Win32, OS/2, POSIX/Interix/SFU/SUA). The classic Windows NT subsystems all involve using ntdll.dll to make NT syscalls; WSL1 processes make Linux syscalls and can't actually make NT syscalls or call ntdll. There is nothing technically stopping an OS/2 1.x executable from realising that it is running on NT and start talking to the NT kernel using the normal NT API; by contrast, a Linux executable running under WSL1, even if it detects it is running under WSL1, isn't allowed to talk to the normal NT kernel interfaces.


Aren’t you describing personalities instead of subsystems?


Windows NT user mode code is divided into programs and subsystems.[1][2] Programs are the actual applications/utilities/etc you run. Subsystems are OS components executing in user mode, generally composed of DLLs and server EXEs which expose LPC services (a little bit like Unix daemons).

There are two types of subsystems – environment subsystems (which provide APIs to programs) and integral subsystems which provide services to the environment subsystems. Integral subsystems include the security subsystem (lsass.exe). (Sources are a bit unclear about whether there is one "integral subsystem" composed of multiple parts, or multiple integral subsystems – e.g. are lsass.exe and smss.exe separate integral subsystems, or two subsystems of the integral subsystem???)

There are three environment subsystems in Windows NT – Win32, POSIX and OS/2, although the latter two have been discontinued in newer versions. The design was always open to adding more (e.g. maybe an OpenVMS subsystem) but that never happened in practice. (Win32, despite its name, doesn't just run Win32, it also runs Win16 and DOS; also, in practice the POSIX and OS/2 subsystems were dependent on the Win32 subsystem and borrowed functionality from it, despite in theory being independent of it. csrss.exe, despite having "subsystem" in its name, is not a separate subsystem, but rather the primary LPC server for the Win32 environment subsystem.)

The term "personality" is sometimes used to describe the environment subsystems, but it is not the term the Windows NT developers used. The term "personality" actually comes from Mach. The idea with Mach was that existing operating systems could be ported to run on top of the Mach microkernel through layers called "personalities" which would map the existing OS API to the underlying Mach API. The original CMU Mach team built such a layer for BSD Unix – the BSD personality – and it actually survives in XNU (macOS/iOS/etc), but they never implemented any other personalities. However, IBM's abortive Workplace OS project actually did implement an OS/2 personality for Mach, which could run alongside an AIX personality, so they actually got closer to delivering on CMU's original vision (albeit the whole project was cancelled before being fully released.) Possibly, NT's environment subsystem idea took some influence from the Mach personality concept; plus, outside observers quickly noticed the similarity between NT environment subsystems and Mach personalities, and started using the term "personality" for the former; but it has never been the officially preferred terminology for Windows.

I've never heard anyone call WSL1 an "environment subsystem". Its method of implementation is very different from the classic NT environment subsystems. You might call WSL1 or WSL2 "personalities", but as I said that's never been official Windows terminology.

[1] https://en.wikipedia.org/wiki/Architecture_of_Windows_NT

[2] http://vig.pearsoned.com/samplechapter/0201791064.pdf


I was under the impression that the name arose out of trademark requirements.

https://news.ycombinator.com/item?id=14093517


Windows has had subsystems since the OS/2 era, and WSL1 was actually such a subsystem. Initrix was the Microsoft POSIX Subsystem.


There was a POSIX subsystem in Windows NT before Microsoft acquired Interix (which became Windows Services for Unix).


Yes, but the name "Linux Subsystem for Windows" would have been much less confusing.


WSL1 isn't actually an NT subsystem like Interix was.


Could they have just called it the Windows Linux Subsystem?


I assumed it was marketing. They didn't want to put the other guy's name first.


And if you think "Windows Subsystem for Linux" is bad, the subsystem that enables the Win32 API is csrss or "Client/Server Runtime Subsystem" and it makes you think: why does that subsystem not mention Windows but the Linux one does?


I have to assume the answer to that question is marketing. They really want to hammer into you that you're running Linux on Windows.


Agreed. "Linux on Windows" is more clear to me.

The "on Windows" part makes it clear that Windows is the host OS.

Many Microsoft's past products used "for $PLATFORM" in the product name. For example:

Microsoft Word for Windows

Microsoft Word for DOS

Microsoft Word for Mac

It makes it clear that it was the version of the product FOR a given platform.

At first glance "Windows Subsystem for Linux" seems like Microsoft's version of WINE.

Maybe we'll get a real "Windows Subsystem for Linux" when the desktop version of Microsoft Linux arrives.


Better choice would have been "Subsystem for Linux on Windows". Its all indeed a big naming confusion


It still doesn't even make sense when you know about Windows subsystems though. True, it is a "Windows subsystem" in Windows terminology, but from my native-English speaker point of view, it's not "for" Linux in the way that the word "for" is used in standard English.

It does work if you assume it's a shortening of something like "Windows Subsystem for Running Linux Applications (on Windows)"

But I get that naming it is a tricky problem, because even a technically accurate name like "Windows Linux Subsystem" (after the old 'Microsoft POSIX Subsystem' name) is still confusing.


It doesn't matter at all if you write 'for', as the possession is totally unclear.

"Windows Subsystem for Linux"

-----

Is the 'windows subsystem' for linux?

or is the 'subsystem for linux' a windows branded feature?

If you asked most people they would probably choose incorrectly.


As bad as the original name was, "Bash on Ubuntu on Windows", I think it was still better than WSL.


It's worse because it can run other distros and shells. hell.


It's really confusing. Windows Linux Subsystem would be more clear. Windows Subsystem for Linux always hinted me to a Vine competitor. Then I know what it is so I read this DOS Subsystem for Linux in the right way (and right to left!)


Also, why linux? Linux is the kernel, which is not what is being run, more like everything on a gnu/linux system apart from linux.


As I pointed out when WSL came out, the name always includes the thing that is being replaced by the Windows NT kernel: be that OS/2 or Linux.

* https://news.ycombinator.com/item?id=11417059

* https://news.ycombinator.com/item?id=18948258


WSL1 emulated Linux kernel syscalls. GNU was run on top of it unmodified, but could be used without GNU. on WSL2 the actual kernel is what is being run, in a thin VM wrapped by lots of wrappers to provide a native-like experience.


Why not use "in"/"on"?

Linux Subsystem on Windows

Linux Subsystem in Windows


I expect Microsoft doesn't want to have "Linux" come first in the name from a branding perspective.


I saw a discussion that it was mostly concerns about the Linux trademark when WSL1 didn't actually use a Linux Kernel with the leading part of the name/term.


Yep - the sentence "X subsystem for Y" reads to me like you're adding an X thing to your Y - i.e. you're adding some Windows thing to your Linux, but what Microsoft means by it is the other way around.


Windows (Subsystem for Linux)

- vs -

Windows Subsystem (for Linux)


((Windows Subsystem) for Linux)

is probably closest to WSL1’s intent.

It was a Windows subsystem (the first new one in years), and its goal was to let you run Linux apps.


"Windows Linux-ABI Subsystem" would have been crystal-clear.


Microsoft has a tradition with these confusing backwards names.

They used to have a product called Windows Services for UNIX [1] which was, you guessed it, UNIX Services for Windows: NFS, Telnet, cron, rsh, etc.

[1] https://en.wikipedia.org/wiki/Windows_Services_for_UNIX


My understanding, especially with WSL1, was that there was a concern about the Linux trademark if MS used the name "Linux Subsystem for Windows" which would have been a better name, since WSL1 didn't actually use a Linux kernel. WSL2 does though.

"Windows' Linux Subsystem" might have been better as well (WLS), using it as a posessive statement, or "Windows' Subsystem of/with Linux" which would keep the same WSL abbreviation.


Perhaps the confused commenters should read the post before commenting. Crazy as that sounds.


It makes sense as "A windows subsystem for Linux". Unfortunately, dropping the "A" makes it ambigious.


It seems like a lot of the discussion surrounding DOD that gets popular interest is centered on a small set of patterns that you can apply. And the implication that DOD is the application of these patterns usually follows.

Taking this article as an example, it frames DOD as an optimization technique and explicitly states that these patterns are the main concepts of DOD.

But while these patterns are interesting and often show up in data-oriented designs, they are not themselves foundational to data-oriented design.

This is interesting to me because it seems to obviously be missing something. If the article went through a list of the design patterns present in the GOF book and framed them as the main concepts of OOP, I would imagine people would be a little bit suspect, right?

That's because it's kind of the reverse, isn't it? The main concepts of OOP may result in certain common PATTERNS of code structure and layout -- which have usually been given names like "Strategy" and "Visitor" and "Singleton" -- but those patterns are not themselves the main concepts of OOP.

Likewise, data-oriented design might lead you to convert an array-of-structures into a structure-of-arrays or avoid branching on a hot path but those patterns are not themselves DOD.


In my understanding of DOD, I'm not sure there really is much of a basis that can be explored in a general way, beyond just adapting to whatever platform you are ultimately targeting. "The data" is supreme (this, along with an information theoretic understanding of "data," should be a hint that something is rotten in the state of DODmark; EDIT: this is extremely dismissive, which is not my intention, and I think DOD makes total sense in combination with other design approaches) and so the programmer tweaks representations of the data to best fit the platform she's working with. Thus DOD would have different positions for x86 or AArch64 or GLSL. DOD seems like a map of constraints x capabilities to strategies. For example, use struct-of-arrays when you need to access sequential elements repeatedly in a von Neumann system with CPU cache. A GPU-based solution might be entirely different, involving weird zipping and index mapping or something. The DOD approach (if it can be called that) seems undecidable when considering how an FPGA might be configured to solve this (or any) problem.

Maybe I'm way off-base, and if so, please correct me. Everything I've seen with DOD (from its inception years ago) seems in line with it, though.


I think for low level high throughout systems that makes sense, but then how do you go up a level when networking gets involved, dealing with back pressure, load balancing, and lots of other things, etc.


Dod taken to its extremes, is to give up on alot of other concepts like avoiding data duplicates. Usually you build a oop prototype to identify the hot loop and then build datastructures optimized for this process. Imagine it like a chemical plant that no longer receives one type per train or wagon, but instead processor batch sized pre mixed ingredients on wagons, that might even be reused as storage and staging for the refinery traveling overhead. A classic oop objects attributes might be distributed over several of such data wagons and the problem here is synchronization and updating. So what if your Algo processed it fast but is bow stuck waiting for another to sync its data back to arrays of optimal accessstructs.


Likewise the focus on ECS architecture as being the one true DoD pattern when it’s not necessarily data oriented at all and the unfounded assumption it’s used everywhere in game development when it isn’t . And somehow the idea that DoD is a replacement for OOP when it’s really an orthogonal concern.

DoD is about recognising data use patterns in your software and organising your software architecture around them in a way that suits the constraints of modern hardware. That’s all.


> And somehow the idea that DoD is a replacement for OOP when it’s really an orthogonal concern.

I’m sure this is true for some definition of OOP, but I’ve seen too much OOP code that insists on hanging every method off of the most plain-old-data of classes. A Book class has to have a buyFromAmazon() method and consequently each instance has a private reference to an Amazon SDK client, and if you want to buy 10K books, you iterate over a list and invoke this method 10K times.

Of course, some will argue that this is bad OOP and true OOP doesn’t look like this, and anyway you can write bad code in any paradigm! Of course, OOP is uniquely plagued with bad code (much more so than other paradigms) and this pretty transparent no-True-Scotsman argument is just moving semantic goalposts (as such arguments do).


Whilst it’s impressive you’ve managed to hold an argument with yourself I think it’s more the case that anything as broad as a programming paradigm will naturally hold multiple approaches. Is immutability a defining feature of FP? Let the battles commence.

Likewise critics might focus heavily on inheritance or some other feature of OOP that is easy to critique.

And whilst I’m not particularly interested in defending OOP I think describing it as uniquely plagued with bad code is not something anyone should just take axiomatically.


> Whilst it’s impressive you’ve managed to hold an argument with yourself

I like to address the boringly predictable responses up front so we can avoid rehashing the same silly arguments over and over. I apologize if that spoiled your fun.

> Is immutability a defining feature of FP? Let the battles commence.

I think most would agree that immutability is more prevalent in FP even if struct immutability isn’t required. Moreover, everyone would agree that first class functions and functional composition are key characteristics. Contrast that with OOP where you have some OOP enthusiasts arguing that inheritance is a defining feature and others who argue it isn’t. Some argue that the “kingdom of nouns”, banana-gorilla-jungle design is inherently OOP and others argue it’s “bad programming and not true OOP”. Others argue that message passing is required, but many others argue to the contrary. While other programming paradigms have fuzzy edges, OOP has no discernible shape at all.

> And whilst I’m not particularly interested in defending OOP I think describing it as uniquely plagued with bad code is not something anyone should just take axiomatically.

Why are there no equivalent criticisms of FP or DO? We might find FP codebases that are overly abstract or a bit slow, but we don’t tend to find (m)any that are designed such that a Book object holds a reference to an Amazon SDK client or a banana with a reference to the gorilla holding it with a reference to the entire jungle. There aren’t prevalent guidance to write code like that in other communities like there is (or perhaps “was”) in OOP circles. Similarly, there aren’t enterprise-y abstract factory beans or anything like that in the FP world.

Mind you, I’m not dumping on OOP—indeed I couldn’t if I wanted to because it has no agreed upon definition, per its proponents.


alankay on June 20, 2016

Object oriented to me has always been about encapsulation, sending messages, and late-binding.

https://news.ycombinator.com/item?id=11940050


I’m well aware of Alan’s definition. Nevertheless relatively few people hold that view.


I think the problem with OOP is that the paradigm itself doesn't offer much. It's a very generic paradigm with a massive sandbox. It needs to be more opinionated.


This is only "bad OOP" if you need to buy 10K books at once and it is actually too slow and there is a significant amount of fat to trim (if you need to call a web service once for every book, incoherent memory access is likely to be negligible).

Otherwise it's obvious, cheap to write, easier to get right than more complicated approaches, and good enough. True OOP is OOP that meets goals.


Other approaches aren’t more complicated, and this is worse even if you never need to send books in batch because it tightly couples “book” to the Amazon AWS SDK client. Anything that interacts with books now has to take a dependency on the Amazon SDK. A much simpler, better design would be to just call client.buyBook(book) or client.buyBooks(books).

But more importantly, my point is that you have your definition of whether this is OOP or not but lots of OOP proponents will say that this is not true OOP.


Actually, the Amazon client could be a component that is managed by a sane dependency injection system (e.g. a factory of "books that can be bought on Amazon") and is used by a book to implement the abstract book operation "buy a copy of me". This would be basically equivalent to a "book buyer" object with a "try to buy this book" operation, with small advantages and disadvantages (either the books or the bookstores are privileged as the main entity in the many to many "can be bought at" relationship).


Better, but the book still needs a dependency on your "book buyer" (let's call it "Retailer" for sanity) interface even though there are likely lots of things to do with a book besides buy it, and those applications shouldn't have to care about the details of book buying. For every verb, the book field needs at least one new field to support that verb (e.g., the `Book.retailer` field to support the `buyBook()` method), even though each thing you might want to do with a book involves at most a few of those fields.

Moreover, inevitably someone downstream from the author of the Book class will have a use case for dealing with books that the author hasn't accounted for, so they have to extend the book class for their own use case, tacking ever more fields onto that book even though their use case only cares about a few of the fields.

Additionally, some of the things you might want to do with a book might also involve some other plain-old-data-structure--how do you determine which plain-old-data should host the method? Why is it `Book.doThingWithCar(Car c);` and not `Car.doThingWithBook(Book b);` or simply a static method `doThing(Car c, Book b);`?

Further still, why create a Book.buy() method that's just going to delegate to `Retailer.buyBook(this)` anyway? If the advantage is that you don't have to explicitly pass the `retailer` around, that's fine enough but there are ways to do that without baking retailer details into every book instance (e.g., a closure: `buyBook = function() { retailer.buyBook(book) }` or if you're a glutton for punishment, you can create a class weds a book and a retailer together:

    class BuyBookOperation {
        private Retailer _retailer;
        private Book _book;

        public BuyBookOperation(Retailer retailer, Book book) {
            this._retailer = retailer;
            this._book = book;
        }

        public do() { this._retailer.buyBook(this._book); }
    }
Further, you might want to buy a book from many retailers--why should you have to do `book.setRetailer(amazonClient); book.buyBook(); book.setRetailer(barnesAndNobleClient); book.buyBook();`? Why not simply `amazonClient.buyBook(book); barnesAndNobleClient.buyBook(book);`? Even if you abstract away the mutation by creating a `Book.buyFromRetailer(Retailer r)` method that sets the retailer and then calls Book.buy(), you now have a potential race condition in parallel code and you still have no advantage over retailer.buyBook(book).

Lastly, if at some point you do need to buy books in batch, how do you support that? Does each book class also need a reference to every List<Book> that references it so it can do book.buyInBatch()? Do you make a book.buyInBatch(List<Book> otherBooks) method? Do you just eat the performance hit and make individual calls to book.buy() even though the Retailer interface has a buyManyBooks(List<Book> books) method that could buy all books in a single HTTP request? What advantages do these approaches have over `retailer.buyManyBooks(books)`?

So this "plain old data needs to depend on everything that might be necessary for any activity involving a book" pattern has no obvious benefits, but it creates a lot of unnecessary coupling, creates a lot of awkward interface decisions when there are other objects involved in an action (including efficiently dealing with collections of your plain old data structure), and it probably pushes you into mutation unnecessarily which makes it a lot more difficult to parallelize your code.

This pattern seems to be a pretty transparent anti-pattern to me, and if it's "inherently OOP" then OOP is problematic.


I think this is because of Rust. In my opinion the Rust game dev community is overly fixated on ECS.

On the bright side, Rust has some damn good ECS libraries.


> the Rust game dev community is overly fixated on ECS.

Not just Rust. The game dev community everywhere is infatuated with ECS.

It's basically cargo culting. There is a large base of amateur or indie game developers who want to feel like they are doing game development the "right" way. One big aspect of that is performance. ECS has a reputation for efficiency (which is true, when used well in a context where your performance problems are related to caching), so you see a lot of game devs slavishly applying it to their code in hopes that the "go as fast as a AAA game" Gods will land on their runway and deliver the goods.

Every time I see a new ECS framework in JavaScript, I die a little on the inside.


The problem is that software design in general is an incredibly messy field that's still basically in its infancy. Developers want simple solutions to complex design problems, or at least they want some decent architectural guidelines so they can avoid constantly reinventing the wheel, badly. Remember when MVC was all the rage?

ECS is good though, it's a perfectly solid answer to a lot of thorny design questions. Where problems frequently arise is when you try to jam absolutely everything in your game into the ECS structure. In practice you're probably going to have a lot of data which lives outside the system and is not attached to any entity.


Most of what I see about ECS is how much easier it is to have dynamic behaviors without inheritance, and it is, so I don’t see why it would be bad for newcomers to use it or to have an ecs lib written in js.


> how much easier it is to have dynamic behaviors without inheritance

I think you're getting at the idea that instead of having objects differ in their behavior by overriding methods, you have them differ by having fields bound to objects that implement different behavior.

Assuming I understand you right, that's an excellent insight, but it's just the classic principle:

Favor object composition over class inheritance.

There's nothing new in that idea or anything special to ECS. Do you know how I know? Because that sentence here is directly quoted from page 20 of "Design Patterns", which ECS and DoD are often claimed to be in direct opposition to. :)


> I think you're getting at the idea that instead of having objects differ in their behavior by overriding methods, you have them differ by having fields bound to objects that implement different behavior.

I guess I'm more getting at the idea of changing the game design at any point by adding or removing components, a way to make it easier for devs to cope with changing requirements (and they are always changing ofc), but you are right about favoring composition over inheritance, that by itself is pretty good.

I can't really talk about "things that are often claimed" and from the way you talk about this it seems like you have come across different opinions from mine on what ECS is or its value. Sad to see such a useful pattern get "corrupted", but I suppose that is inevitable.


Just like VBX, COM, SOM and Obj-C Protocols/Categories based architectures, now that is something incredibly new.


Not only that, it is incredible how it gets trumped as a new idea, when stuff like COM, Objective-C protocols and plenty of other component based architectures were already a subject in OOP related papers during the late 90's.

But that is how cargo cult usually goes.


It's a totally different composition pattern though. It uses more trait-style multiple inheritance, unlike the typical "has-a" composition typically used in object-oriented languages. Additionally, it intentionally breaks encapsulation, which is a key tenet of object-oriented design.


I wouldn't dismiss the JS ECS frameworks without measurement.

Polymorphism has costs, and while dynamic languages work hard to remove them, they still work best when they're able to monomorphize the call site, because that enables inlining without combinatoric explosion from chained polymorphic calls.

Having a single type in your array means field accesses, method calls etc. have the potential to be monomorphized. There are performance wins to laying out your data in ways that avoid the need for polymorphism.


> I wouldn't dismiss the JS ECS frameworks without measurement.

I think the burden of proof is on the part of JS ECS frameworks to show they do have better performance by virtue of DoD and, if so, why. JS engine programmers have been optimizing object-oriented code for literally forty years, all the way back to when they were making Smalltalk VMs.

If somehow a couple of folks hacking on ECS frameworks have managed to write code that runs faster on those JS engines than the kind of code they were designed for, I'd like to see it.

> Having a single type in your array means field accesses, method calls etc. have the potential to be monomorphized.

Sure, but object-oriented code does not require any more polymorphism than DoD does. Consider:

* Iterate over an array of monomorphic components and call a method on each one.

* Iterate over an array of monomorphic entities, access a monomorphic property, and call a method on the latter.

There's an extra property access in the latter (which can easily be inlined), but no polymorphic dispatch. In practice, yes, it is possible to reorganize your JavaScript code in ways that play nicer with inline and possibly even code caching. But I have never seen any evidence that JS ECS frameworks actually do that. Instead, the few I've poked around in seem like typical slow imperative dynamically-typed JS.

If someone is going to take a pattern that was invented specifically for a language like C++ that gives you precise control over memory layout and then apply it to a language that not doesn't give you that control but often uses hash tables to store an object's state, I think the burden of proof is on the framework to show that the pattern actually applies.


Okay, here you go

https://github.com/thi-ng/umbrella/tree/master/packages/ecs

Optimized Typescript ECS with a demo rendering 100,000 live 3D particles


That one's pretty interesting. Here you can see they are putting real effort into thinking about the performance of the underlying VM. Using typed arrays is neat.


The author, Karsten Schmidt is one of the most talented devs I've ever seen.

Super nice guy too, always willing to share information or explain stuff to you if he's around.


Modern JS engines won't use a hash table for the object state, they'll use a hidden class, and member accesses will be fixed offset indirect loads guarded by a type check. Initialize your objects carefully in a deterministic order, and I'd expect you can control field order and adjacency.

I'd expect the wins from reworking your JS so that your target JS engine lays out data out better would often be larger than the wins in C++, simply because the worst case is so bad.

I'd add a third option to your pair: iterating over several arrays of properties - especially numeric properties - rather than an array of objects which each have numeric properties. That can get you substantial wins in Java, never mind JS.


> Modern JS engines won't use a hash table for the object state, they'll use a hidden class, and member accesses will be fixed offset indirect loads guarded by a type check.

The type checks themselves have significant overhead, and it's easier to fall off the shadow class fast path than you might expect.

> Initialize your objects carefully in a deterministic order, and I'd expect you can control field order and adjacency.

True, but that's equally true of non-ECS architectures. I have yet to see much evidence that the ECS JS engines I've looked at are actually taking that into account.


I don’t believe any JS engines do any “shape” or “hidden class” caching other than for call site polymorphism?


> ... so you see a lot of game devs slavishly applying it to their code in hopes that the "go as fast as a AAA game" Gods will land on their runway and deliver the goods.

I watched this sentence unfold with bated breath, waiting to yell "and ze sticks the landing!", only to see it end with "goods" instead of "cargo". It's frustratingly close to perfect, though perhaps to end the paragraph with "cargo", you'd have to begin with some synonym for cargo culting.


I used "goods" as a synonym for "delivered packages". I think it works OK. Maybe "shipment" would have been a better choice.


Rust lends itself to ECS a lot more than it lends itself to behavior hierarchies using inheritance. That's an over simplification, but a useful one.


I agree that Rust is more suited to ECS than hierarchies. However, the choice is not between ECS or inheritance. The reason I say that the community is overly fixated on it is that many of the benefits attributed to ECS aren't unique to ECS.


I’d agree to a point but it really crosses the whole gamut of hobby game engine development. It’s weirdly self reinforcing even in the face of more interesting architectural choices like DOOM Eternal’s.


The way Eternal's engine is described it could simply be an ECS with a more advanced job system for farming out work because it can parse how the various objects are updated and only do reads after all writes to the objects happen.


Interested what the architecture of DOOM Eternal is like, was there some talk / blog post about it?


I believe it’s only been mentioned in passing and likely will be talked about at conferences soonish. Here’s a HN thread from when it was first talked about:

https://news.ycombinator.com/item?id=22700563

There was an early talk about using a job system to run the Destiny renderer and then this one for the whole engine which is a very similar premise to the way DOOM(2016) and then DOOM Eternal evolved.

https://www.gdcvault.com/play/1022164/Multithreading-the-Ent...

The renderer talk is here: https://youtu.be/0nTDFLMLX9k


It took me a fair amount of searching to establish that ESC refers to https://en.wikipedia.org/wiki/Entity_component_system


Basically it boils down to making use of Objective-C protocols or multiple inheritance, with data separated from behavior in regards to implementation.

So a 1986 concept rediscovered by game developers and cargo culted ever since, although it has its roots on the OOP they love to hate.


That's okay, now that you're familiar with the term, you'll end up noticing it a lot more (or maybe it's just that articles that happen to lend themselves to it showing up in their comments look slightly more appealing now?).


If you look at the URL you'll see "commentisfree".


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: