Brian Lovin
/
Hacker News
Daily Digest email

Get the top HN stories in your inbox every day.

iherbig

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.

baryphonic

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.

AlphaSite

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.

Haga

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.

meheleventyone

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.

throwaway894345

> 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).

meheleventyone

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.

HelloNurse

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.

bfrydl

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.

munificent

> 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.

swsieber

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.

meheleventyone

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.

FullyFunctional

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

pjmlp

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.

kbenson

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?).

beders

A lot more in-depth about caching, avoiding branching etc. can be found in this classic talk by Mike Acton who is Engine Director at Insomniac Games

https://www.youtube.com/watch?v=rX0ItVEVjHc

Very enlightening and entertaining!

nwsm

This video is linked in the first paragraph of the article.

Jare

Was, now pushing DoD at Unity.

narwally

I find it interesting, and somewhat amusing, that we're seeing Data-Oriented-Design becoming popular in C++ and Rust while Data-Oriented-Programming/Data-Driven-Design[1] is being promoted in languages like Clojure and Elm. Both have similar names, and seem to have arisen out of frustrations with OOP. However, their solutions went in completely opposite, though not unrelated, directions. Seems like DOD is about improving program performance by optimizing for data locality in memory; while DOP/DDD is about improving programer performance by optimizing for data locality in source code.

On the other hand, maybe this isn't interesting at all and I'm just thinking about it too hard.

[1] This one isn't a well defined, and there's no commonly agreed upon terminology for the concept. But there is this: https://livebook.manning.com/book/the-joy-of-clojure-second-...

Jtsummers

"Data-driven programming" tends to give more results than "data-driven design" which mostly (on my Google search) turned up content about usage data driving interface design.

https://en.wikipedia.org/wiki/Data-driven_programming

narwally

Thanks, I knew it was some permutation of those words.

Jtsummers

NP. You may also want to check out Norvig's Paradigms of AI Programming if this interests you. A lot of that text involves creating data-driven programs, and some of the benefits (like creating a grammar lets you recognize sentences that satisfy it, or with little extra effort generate sentences from it).

pjmlp

It has its roots in CLOS / Objective-C protocols / Smalltalk traits / Eiffel multiple inheritance, but somehow it got twisted as not being OOP.

knowuh

For a 2x speed up, I am not sure I would be willing to sacrifice legibility as in the example. The OOP method definition reads like english.

The article suggests the true benefits of DOP aren't all that great unless you understand the target architecture.

I feel like the pendulum is at its new zenith.

ekidd

As always, it depends on the problem you're solving.

A 2x speedup in the inner loops of a game can be a very big deal. And for business workloads, I occasionally spend time babysitting clusters running batch jobs. A 2x performance increase in the right inner loop might save a couple hundred dollars per run.

So certainly, profile before you optimize, as the article demonstrates. But 2x speedups can be worth applying a "struct of arrays" transform.

estebank

The interesting thing to me from these patterns is the possibility of using proc_macros to write code in the "array of structs" style while the code gets desugared to "struct of arrays". I don't know how beneficial that would be, but having it as an option would make this pattern more approachable to people that would otherwise not use it, due to verbosity, mental model mismatch or any other reason people might have not to do this.

I don't think Rust itself will ever incorporate this feature into the language, just like it doesn't transparently wrap a `dyn Trait` into a `Box<dyn Trait>`, but I would expect that it will never put active roadblocks for libraries to extend the language in such a way. (The regular proc_macros caveats would apply, of course.)

Rusky

It seems likely to me that Rust will use ECS queries as the idiomatic way to write struct-of-arrays code.

In archetype-based ECS libraries (which the ecosystem seems to be converging on or near) you write a query asking for a particular subset of "component" types, where each type is stored in its own array(s), and then for each iteration of the query you get back one reference to each component type.

As a result, all the extra zipping (which I'm assuming is what people find less readable about the article's example) is handled in the query implementation, and you get this sort of hybrid between the two, syntactically speaking:

    for (location, velocity, acceleration) in players.query::<(Location, Velocity, Acceleration)>() {
        *location = (
            location.0 + velocity.0,
            location.1 + velocity.1,
        );
        *velocity = (
            velocity.0 + acceleration.0,
            velocity.1 + acceleration.1,
        );
    }
Some libraries even let you write a query as a struct with a #[derive] on it, rather than a tuple, so you can use essentially the same syntax as the "OOP" example from the article, rather than destructing the "fields" up front.

zozbot234

> The interesting thing to me from these patterns is the possibility of using proc_macros to write code in the "array of structs" style while the code gets desugared to "struct of arrays".

This is not possible in the general case, because you can have a general pointer/reference to a single struct in an "array of structs" but a "struct of arrays" can only be accessed by indexing each array separately. So only very simple and self-contained programs can possibly be "desugared" in this way.

tgb

This is Jonathan Blow's goal with his in-development language Jai, see for example this video:

https://www.youtube.com/watch?v=YGTZr6bmNmk

oehtXRwMkIs

I think the data-oriented version is very appropriate for a game, where performance is king and there's not that much maintenance afterwards once its done. Perhaps I'm wrong but games seem to be very much a finish and toss it over the wall sort of project. Much less iteration than other contexts.

Hammershaft

That is changing over time as post launch support grows and some games shift to games as a service

nikki93

I think DoD can be ergonomic, actually, if you're doing it just for the architecture reasons vs. the optimizations reasons, to the point that you choose DoD due to them. At least I personally have found that eg. an ECS architecture can lead to separations and structurings of logic code that were helpful, while still defining data in ways that I could just make accessible to tooling and so on.

In this talk on their architecture for Overwatch: https://youtu.be/W3aieHjyNvw (highly recommend) you can see that the wins / concerns they talk about have to do with architecture more than perf. Big insights at 8:00 in the video.

hknapp

When i first started programming and before i had learned of structs, my intuition led me to organize data with arrays of fields. Turns out, i was on to something.

zozbot234

As they say, you can write FORTRAN in any language.

TheRealKing

you can write write anything in anything these days. This sentence bears no value.

FartyMcFarter

I find it sad that every time the subject of DoD comes up, lots of people act like it's incompatible with Object Oriented Programming.

This is not the case. You can program in a data-oriented, cache-efficient way using OOP. To give a super basic example: in a game, this could mean writing a class that contains data for many game objects, instead of a single one.

blovescoffee

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 computer architecture - thus DOD would be lost on them. It would be a huge barrier to entry to introduce cache hit rates as a design concern when people are just learning what a class is (in the current standard model of CS education).

Still, it feels like there are other practical reasons to keep OOP around. Perhaps OOP is the React Native of design patterns - poor performance but quicker to write and add new members to. It does seem like there are also legitimate concerns about refactorability and extensibility of DOD code. Anyone have any more refined ideas here?

cogman10

DOD generally implies a high level of coupling on the system. That's it's biggest weakness. It also pushes even more data management problems onto programmers which makes it easy to get things wrong.

You take those downsides and you trade them for higher performance.

Now, that doesn't mean that you can't have hybrid systems and get most of the benefits of both worlds. It does, however, mean that you will end up with a more complex system to manage and maintain.

A simple OO system is relatively easy to craft without a whole lot of ceremony. That's the prime benefit of OO.

jessermeyer

'The hardware is the platform' is the DOD mantra.

It's not a weakness to integrate more information about the problem space into the solution. It's engineering. To _ignore_ information about the problem space is certainly a weakness, and is partly responsible why the Windows boot time appears to be a cosmological constant.

SquishyPanda23

> It's not a weakness to integrate more information about the problem space into the solution. It's engineering.

You want your solution to depend on the right abstract model of the problem, not on the particulars of the problem.

Otherwise your solution is difficult to extend, and is generally expensive and error prone to change when your problem changes, which happens with 100% probability.

Arelius

> DOD generally implies a high level of coupling on the system. That's it's biggest weakness.

I'm not sure I understand what you mean by DOD generally implies a high level of coupling? Could you perhaps elaborate a bit?

dragontamer

Lets say you have "struct Point {int x; int y;};", and all things are fine and dandy. You write your OOP as such (or your DOD version), and things are going great.

Suddenly, you want "struct Point3D {int x; int y; int z;}". How would you change the code?

In OOP, maybe you'd compose a Point3D as such: struct Point3D { Point xy; int z; }; You can now "capture" all of the Point xy; functionality, and extended it to a 3rd "z" coordinate just fine. All old Point code still works, and you have a few functions that work with Point3D now (maybe with a bit of redundant wrapper functions, but such code is straight forward)

The equivalent in DOD seems less obvious. You'd have to make a new "z" array. But the arrays of Point and Point3d wouldn't line up anymore. (If you had 300 Points, and 20 Point3Ds, is Point#315 a Point3D, or is it a Point? Do you "pad" the "z" arrays to ensure that the struct-of-arrays line up?)

There's no obvious way to benefit from a "z-vector", extending the functionality off of your Point to Point3D. I think the DOD design would create a 3rd "z-vector", and shove a "dummy value" into z for all of the points, to make sure all the vectors would have an ideal set of indexes.

Which demonstrates the coupling factor: its not really easy to compose objects in DOD. While in OOP, composing and inheriting classes and objects is the very point.

jayd16

I would phrase it in the inverse. OOP implies some encapsulation/abstraction that you give up when you use sets of arrays instead.

cogman10

From what I've seen in DOD systems, there are generally common structures that hold data for the entire application. The entire application has to know about these structures in order to function.

Take ECS [1] as an example.

In order to create a new entity on the system you might need to talk to a location component, a health component, a velocity component all to register a brand new entity on the system. Now, you might have an entity creation service that hides those creation details from you, and that's fine. But you need to make sure as you are talking to each of the component you are doing the right thing.

This is the coupling.

The traditional OO approach here would be to create a new entity with health, position, velocity, all contained within the same object and potentially referencable via a common interface for each.

Now, for ECS in a game there are definite benefits to this coupling. For example, it is a LOT easier in games to create universal systems which handle the physics for all objects irrespective of object type. Further, composing behavior onto entities can be much easier. You are free from a strict hierarchy. There's a reason this approach is popular there.

Now consider a very simple rest webservice. Now imagine trying to do that as an ECS system. You might have one component that is the header component and one component that is the body component and an entity that contains both. Now imagine processing that entity through the system. Who would be in charge of making sure all the right interactions happen at the right time? Who would be in charge of responding? Who would be in charge of deleting requests that had been fully handled? I'm sure that's all possible (I wonder if anyone has tried it? could be a fun side project) I'm also sure I'd very likely not want to deal with such a system, no matter how fast it is. It would be unreasonable to try and figure out all the life cycles of everything.

For business applications with a lot of rules to follow, this sort of system would be nightmarish to maintain. It'd be almost impossible to track down what is changing what. You need a lot of gatekeepers because the goal of business apps isn't to enable novel and unexpected interactions, but rather to very explicitly define what happens when and why. For a game, those novel and unexpected interactions are a huge boon and a feature. They make games fun!

As a side note, the coupling of ECS systems is one thing that makes it hard to properly thread games. That's because you've got this globally shared mutable state being accessed through a ton of systems throughout the game. It's frankly impressive that games are threaded at all!

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

adamnemecek

DOD couples less than OOP. What is data management in this context?

mamcx

Is more than OOP. Look at this as the difference between OLAP/OLTP databases: DOD is OLAP(Columnar) that make easy to do "query" by columns but awkward to do piece meal updates and OOP/Row-nar(?) code stay because frankly is the default everywhere. And far easier for make updates.

Iterate by rows is far more common that by just "a column". Also, constant update of the rows is more common that have a static, full materialization of the data that only need to be queried.

So, doing DOD only work in some scenarios, but do "by rows" is the common one.

P.D: I tried to go full columnar building a relational language, but get very obvious very fast that it not work for the general case. Is telling that kdb+ (probably the biggest proponent in the area) work in a OLAP-like niche...

Jtsummers

I was going to write something similar. The example in this article is a comparison between row-oriented and column-oriented approaches, not OOP and DOD. Which you prefer depends on the operations you expect to perform during program execution.

If you generally only add new entities, and generally perform operations on all entities (or large subsets) and specifically only need some columns, then the column-oriented approach is more likely what you want.

If you find you delete entities frequently enough, or operate on individual entities more than groups, then row-oriented may be better. Performance will improve (deletes are expensive in arrays/vectors) and code may be cleaner.

There are lots of other factors, but these are the bigger ones (IME).

CyberDildonics

"OOP" is really three different things that people conflate together.

1. Making data structures as tiny databases with an interface that simplifies storing and retrieving data correctly (no transformations in the class itself to other data types hopefully to minimize dependencies!)

2. The school taught java/old C++ debacle of inheritance. This is where things fall apart. Inheritance means not only dependencies but opaque dependencies. It almost always means pointer chasing and lots of allocations. It used to be necessary because it was the only way to get generic containers. The speed hit to use a chain of pointers was also much smaller. In modern times this destroys performance and is not needed due to templates.

3. Message passing - 'at a certain scale, everything becomes a network problem'. I think the flexibility in having this integrated into the core of a language like smalltalk is not a good trade off, but I do think message passing at a courser architectural level offers large benefits without limiting the speed of more granular and fundamental data structures and functions.

I think OOP will always be debated in a circle because people conflate these three aspects. The first I think is extremely useful and vital. The second I think is obsolete. The third I think should be treated as a higher level architecture approach with large chunks of data passed around to large non-trivial modules/libraries/nodes/plugins etc. The higher level can be more dynamic and flexible because the overhead for a flexible structure is much smaller if it is done with large chunks of data and not integrated into a language and used for vectors / hash maps / one line math functions, etc.

erichocean

> It does seem like there are also legitimate concerns about refactorability and extensibility of DOD code.

On the contrary, that's why people adopt DOD designs. It's way easier to add new stuff without breaking existing code/designs in a way that harms them.

blovescoffee

If your data changes then won't you need to refactor more than if your data changes in OOP? I suppose "data changing" is an arbitrary measurement but I think that's what people refer to when they talk about refactoring DOD vs OOP.

Arelius

Likely, yes, but the corollary is if your data structure stays similar and well defined, then you'll have smaller, cleaner and less refactors for reasons that are unrelated to a fundamental shift in your actual data

jayd16

They're not really exclusive concepts and you don't want to bother with DOD if your n is low.

I would go as far as to say most DOD implementations are done along side the use of objects.

blovescoffee

Sure, although there's room for distinction between programming with objects and OOP.

genuine_smiles

A lot of languages have OOP built into them. If want to use patterns like polymorphism it’s the tool on hand. Associating data with functions is helpful for organization as well.

adamnemecek

In DOD you have row level polymorphism.

adamnemecek

I think oop is easier to understand in small examples but gets really inscrutable as your code base grows so you only start questioning oop if you have worked on large code bases.

Also the lack of dod/ecs languages is a problem. I realized the other day that row polymorphism is the type theoretical concept that would make this work.

https://en.wikipedia.org/wiki/Row_polymorphism

mdtusz

Partially, but DOD like in the article examples work great when you have a "rigid" architecture like a game where having a struct to contain vecs/arrays of player attributes makes sense. This can break down when your "objects" require more flexibility and are used in multiple different contexts where an aggregate `PlayerState` struct doesn't play nicely.

Not to say that DOD is bad, just that it shouldn't always be the go-to choice. Rust _does_ make this sort of design much nicer to work with because you can in many ways have your cake and eat it too using `from` and `into` and go back and forth from DOD to OOP type structures.

runevault

ECS style DOD arguably makes putting things together easier though, because instead of having to update your actual object when you want to make a change, you only have to add the right component that contains the functionality you need to the given entity ID.

jbjbjbjb

OOP isn’t necessarily slower. One thing you get is lazy evaluation for free. There’s no better performance gain that no computation. It’s also much easier to extend the types than in functional programming (where it is easier to extend the functions). I find OOP is a lot better for programming in the large too, interfaces and other abstractions are really useful as a project grows.

strictfp

I share the opinion that DoD is an optimization technique, and that it shouldn't be applied too generously from the get-go; you're essentially optimizing for specific usage patterns, which might be difficult to predict and often are contradictory.

What one can consider is to use ECS. The separation of data and logic into components allows you to apply DoD in a more predictable way. The data which is unique to a particular component can in this way be vectorized across entities.

The ECS approach doesn't solve the problem of data shared between components though, and like others in here I'm also interested in solutions which could optimize access in the same way that relational databases can optimize multiple different access patterns to the same data.

undefined

[deleted]

jakuboboza

Correct if i'm wrong: The general conclusion is Vectors are faster and pattern matching is slower in observable way when generating vectors.

I wonder if it changes when vec items becomes bigger structs and size goes to millions.

Rust dosc says with LinkedLists that you should better use Vec for speed. I think just raw array of bytes is always faster than linked pointers. But LinkedList will probably have less of a memory pressure in cases where you have to maintain large list and remove elements at random while keeping coherency.

from Rust docs: Vector = "A contiguous growable array type, written Vec<T> but pronounced 'vector'."

LinkedList = "A doubly-linked list with owned nodes.

The LinkedList allows pushing and popping elements at either end in constant time.

NOTE: It is almost always better to use Vec or VecDeque because array-based containers are generally faster, more memory efficient, and make better use of CPU cache."

undefined

[deleted]

hu3

This is known and heavily used by the game industry for a long time now.

Ultimately it comes down to data locality and there's no silver bullet. Performance varies with your data access pattern and code must be adapted to keep caches as warm as possible.

There are also maintainability trade-offs. In general I'd advise this kind of optimization only for performance-critical code like games.

For more information on how game development approaches this, read about Entity Component Systems. Here's a good start: https://www.youtube.com/watch?v=JxI3Eu5DPwE

hu3

I like that my constructive comment is currently downvoted even below another that reads "Rust is a scam". Absolute state of the language's community. And yes, it happens specially on rust related posts. I'm not the first to write about this.

Someone else's comment about jai received similar treatment. Good thing that on important technologies their communities tend to be friendly. As a niche language striving to become relevant, I'd adopt similar approach.

As a consultant I get asked almost on a daily basis: what technology could solve my problem? Community is heavily weighted in that decision because once I deliver the project, my clients will invariably have to deal with the tech communities.

Regardless, maturity problems like this currently rule it out anyway: https://www.reddit.com/r/rust/comments/iab9iv/i_must_be_doin...

adamnemecek

A lot of people in the Rust community (yours truly including) are trying to work out how to build UI frameworks in this paradigm. It's a really interesting question, if anyone has any good input, I'm alll ears.

eyesee

I'm not in the Rust community, but it seems like one could have their cake and eat it too, using OOP with DOD storage.

  * Use a special allocator for objects which reserves a vector slot from your structure-of-arrays.
  * Objects records are offsets instead of pointers
  * Object definition includes getter/setters which index the columnar vectors
  * Store fields declared 'columnar' in a value vector. This could even give flexibility to group columns for locality where needed, and allow ancillary data to be stored in a "leftover" struct.

adamnemecek

Yes, generational arena allocations are very popular. The larger question is more about the application architecture. Like where does one handle user input? Where does rendering happen? Etc.

fsociety

Modern React/Relay with GraphQL fragments does this semi-well I think. Sources of data include the fragment in their GraphQL query and can blindly pass that to components which depend on it.

That lets you re-use components quickly and easily. Changing the downstream component which consumes the fragment just requires changes in that component and nothing else.

adamnemecek

Modern React meaning Hooks?

fsociety

I like Hooks a lot but I’m not sure how it’d apply in the Rust UI sense (maybe well, maybe not). It is nice to not be forced into building classes and to also ensure that specific state changes will force partial re-renders.

I’m talking more about https://relay.dev/docs/en/fragment-container. Creating opaque types that can be fetched from a data source and passed off to a child component is more what I am thinking of.

I mention it because I recall working on a Qt product where you have to parse data from a source, then you bring it throughout your program and try to keep it in the right form for every UI component that uses it.

It was easy for the project but we had no composability of components.

With fragments, you don’t really care and duplication of data between fragments on the same source of data generally just works. That way you can pass the fragments to each component as required.

The idea behind that being that, you can have “efficient” and opaque data structure received from a data source which can be blindly passed to a component to consume.

I say data source but in this instance I mean GraphQL... so maybe it doesn’t apply to a generic UI library.

Daily Digest email

Get the top HN stories in your inbox every day.

An Introduction to Data Oriented Design with Rust - Hacker News