Handles are the better pointers (2018)
&gt; and may even be useful in higher-level garbage-collected languages to reduce pressure on the garbage collector.<p>&gt; The approach described here works very well though with a data-oriented architecture, where central systems work on arrays of data items packed tightly in memory.<p>I have been pushing us into a new data-oriented architecture for our software, but for reasons of domain modeling (managing complexity) rather than performance. This is a very interesting read from my perspective.<p>Let me give an example - We took deep, circular object graphs like:<p><pre><code>  Account.Customers[0].Accounts[1].Customers[2].FirstName
</code></pre>
And turned them into 2 flat arrays of Account and Customer. A 3rd relation type is also developed to arbitrarily relate these types together. The relation type also conveys all facts that pertain to the nature of the relationship, rather than forcing this knowledge onto Account or Customer.<p>This ideology is carried to the logical extreme - We do not permit <i>any</i> nesting of complex types in our revised domain model object graph. There is a root type which contains all of the List&lt;T&gt;s of domain types (and applicable relation types). The domain model is composed such that we can directly map every single type &amp; public property into SQL tables. And we do. Because SQL is amazing for executing business logic.<p>Now that I am thinking this through, performance is certainly also seeing a benefit here. We are no longer serializing these absolutely horrific JSON object graphs. It&#x27;s just a bunch of flat complex type arrays now, with everything related together using GUIDs.<p>From a developer QOL perspective, one could argue that this is more difficult to work with because everything is separated by relations. I would say if you are fortunate enough to be working with something like .NET, you can abuse the shit out of LINQ and not really feel the added complexity.