I've read quite a few articles about DOD. I get how DOD is great but there are reasons OOP is still around (surely?) I suppose I'm still hung up on, what are the benefits of OOP that I'm missing? It seems like there are reasons OOP is so ingrained. I can see a couple of reasons that are environmental. For instance, OOP is taught in schools because students are often taught to program before they're taught about compu…
An Introduction to Data Oriented Design with Rust
141–150 of 161 posts
Re: An Introduction to Data Oriented Design with Rust
#142Earlier quoted context omitted.
> 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.…
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
Re: An Introduction to Data Oriented Design with Rust
#143Earlier quoted context omitted.
> 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 book…
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.
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.
Re: An Introduction to Data Oriented Design with Rust
#144Re: An Introduction to Data Oriented Design with Rust
#145Earlier quoted context omitted.
So your OOP version creates many layers which impedes understanding and extension as well. DRY is also not a law which must always be followed. You often don't even know when you're repeating yourself until you do, and the first time you see a repetition is not when you should eliminate it (in most cases). You often see people reference the rule of three here. The first repetition should make you pay attention. The s…
If you don't care about DRY in this case, that's fine. There's more than one problem with your proposed DOD solution. Your proposed solution violates the open-closed principle. Which means you have to modify "old working code" to get anything done. If your "solutions" to fixing code issues is "rewrite and extend the old code to cover the new case", then it becomes impossible to build libraries. ---------- Lets say Ap…
Re: An Introduction to Data Oriented Design with Rust
#146Earlier quoted context omitted.
If you don't care about DRY in this case, that's fine. There's more than one problem with your proposed DOD solution. Your proposed solution violates the open-closed principle. Which means you have to modify "old working code" to get anything done. If your "solutions" to fixing code issues is "rewrite and extend the old code to cover the new case", then it becomes impossible to build libraries. ---------- Lets say Ap…
> Your solution forces you to rewrite Point2D, which therefore creates a change in ApplicationFoo. I don’t see how this is the case. You don’t change Point2D at all, you simply add a second type Point3D. ApplicationFoo can happily continue to use Point2D from your library while you use Point3D. I think the example of Point2D and Point3D is not very well chosen. Your proposed solution of Point3D = { xy : Point2D, z :…
Point2D, under DOD, doesn't exist. There's "array_x" and "array_y". See the article under question. Point2D would be the index into the "x" and "y" arrays, or an "id" returned by the ECS system.
The "x" and "y" fields, under DOD, are dispersed into different areas, allegedly for SIMD / auto-vectorization benefits. I'm trying to discuss the effects of a decision like this.
> I think the example of Point2D and Point3D is not very well chosen.
There are multiple users who understand software engineering who disagree with me, but understand what I'm trying to discuss.
There are also multiple users who prefer to be pedantic and focus on this issue. For the most part, I'm able to ignore these unimaginative users pretty easily. So the example is working pretty well as a filter.
If you wish for more people to participate in the discussion without getting distracted, maybe a better example would have been recycling the example from the article:
pub struct Enemy {
name: String,
health: f64,
location: (f64, f64),
velocity: (f64, f64),
acceleration: (f64, f64),
}
pub struct FastEnemy {
name: String,
health: f64,
location: (f64, f64),
velocity: (f64, f64),
acceleration: (f64, f64),
jerk: (f64, f64), // 3rd derivative of location
jounce: (f64, f64), // 4th derivative
}
pub struct GalaxianEnemy{
name: String,
health: f64,
location: (f64, f64),
velocity: (f64, f64), // Constant vertical velocity
loopiness: (f64, f64), // cos / sin based horizontal movement
}
Doesn't really matter. There are plenty of data / classes where you need to just "add one more parameter" to a previously created class to make it perfectly work. The above "GalaxianEnemy" and "FastEnemy" classes follow this pattern.---------
But if we focus on this pedantry, we wouldn't be able to discuss software engineering. Surely you've come across an example in your programming life where code-reuse would be useful with a subset of parameters, but needed to be extended into an additional parameter?
> The main problem with this solution, I think, is that you picked one specific projection from 3D space to 2D space. It might line up with a projection that is relevant to your domain but it probably won’t. So if you use inheritance and call a function requiring a Point2D with one of your Point3D’s you secretly project the point to the xy-plane which seems like something that should be explicit in the code.
Is it so hard to imagine a video game, where my Point2D and Point3D interpretation is in fact correct? The point of the discussion is to point out software engineering principles: recycle code where possible, open-to-extension but closed-to-modification, and other such principles.
Re: An Introduction to Data Oriented Design with Rust
#147Earlier quoted context omitted.
> 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 book…
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…
Re: An Introduction to Data Oriented Design with Rust
#148Earlier quoted context omitted.
That is changing over time as post launch support grows and some games shift to games as a service
Are the "games as a service" games adding significant code after launch? I think most of the performance critical stuff is in the engine and core game loops. Content packs and seasons aren't likely to change those core bits, and instead be more assets and scripting intensive.
Re: An Introduction to Data Oriented Design with Rust
#149Earlier quoted context omitted.
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…
Re: An Introduction to Data Oriented Design with Rust
#150Earlier quoted context omitted.
> 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…
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 w…
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.