Data, objects, and how we're railroaded into poor design (2018)

63 dvrp 20 8/21/2025, 5:06:05 AM tedinski.com ↗

Comments (20)

2d8a875f-39a2-4 · 2h ago
Maybe it's just me but I find the complaint confusing and the suggested remedy absent in TFA, despite reading it twice.

Data comes from outside your application code. Your algorithms operate on the data. A complaint like "There isn’t (yet?) a format for just any kind of data in .class files" is bizarre. Maybe my problem is with his hijacking of the terms 'data' and 'object' to mean specific types of data structures that he wants to discuss.

"There is no sensible way to represent tree-like data in that [RDBMS] environment" - there is endless literature covering storing data structures in relational schemas. The complaint seems to be to just be "it's complicated".

Calling a JSON payload "actual data" but a SOAP payload somehow not is odd. Again the complaint seems to be "SOAP is hard because schemas and ws-security".

Statements like "I don’t think we have any actually good programming languages" don't lend much credibility and are the sort of thing I last heard in first year programming labs.

I'm very much about "Smart data structures and dumb code works a lot better than the other way around" and I think the author is starting there too, but I guess he's just gone off in a different direction to me.

arethuza · 1h ago
My main complaint with SOAP was how leaky an abstraction it inevitably is/was - it can look seductively easy to use but them something goes wrong or you tried to use it across different tech stacks and then debugging would become a nightmare.

When I first encountered RESTful web services using JSON the ability to easily invoke them using curl was such a relief... (and yes, like lots of people, I went through a phase about being dogmatic about what REST actually is, HATEOAS and all the rest - but I've got over that years ago).

NB I also am puzzled as to the definition of "data" used in the article.

2d8a875f-39a2-4 · 21m ago
Sure, SOAP was often awful, I agree with that. But I can't see any angle where one can credibly assert that a SOAP XML payload isn't equivalent to a REST JSON payload in terms of the operation of a receiving application. Both are a chunk of structured information, your application parses it and operates on the resulting data structures.
arethuza · 18m ago
Sorry about getting sidetracked there by my SOAP rant - I completely agree with your point.
BlackFly · 56m ago
Yeah, a leaky abstraction with abstraction inversion on top of it! So within the actual payload there was a method identifier so you had sub-resource routing on top of the URL routing just so you could have middleware handling things on the payload instead of in the headers... So you had an application protocol (SOAP) on top of an application protocol (HTTP).
mcdeltat · 4h ago
IMO the nice thing about Erlang and Elixir is their foundation of representing data is rock solid. Because data is fully immutable, you get a lot of nice things "for free" (no shared state, reliable serialisation, etc). And then on top of that you can add your interfacey, mutable-ish design with processes, if you want. But you will never have oddities or edge cases with the underlying data.

In contrast with languages like C++ and Java where things are shakey from the ground up. If you can't get an integer type right (looking at you, boxing, or you, implicit type conversions), the rest of the language will always be compensating. It's another layer of annoyances to deal with. You'll be having a nice day coding and then be forced to remember that int is different to Integer and have to change your design for no good reason.

Perhaps you disagree with Erlang's approach, but at least it's solid and thought-out. I'd take that over the C++ or Java mess in most cases.

jasode · 2h ago
>IMO the nice thing about Erlang and Elixir is their foundation of representing data is rock solid. Because data is fully immutable, you get a lot of nice things "for free" (no shared state, reliable serialisation, etc). [...] >In contrast with languages like C++ and Java where things are shakey from the ground up.

Yes, immutable does provide some guarantees for "free" to prevent some types of bugs but offering it also has "costs". It's a tradeoff.

Mutating in place is useful for highest performance. E.g. C/C++, assembler language "MOV" instruction, etc. That's why performance critical loops in high-speed stock trading, video games, machine learning backpropagation, etc all depend on mutating variables in place.

That is a good justification for why Erlang BEAM itself is written in C Language with loops that mutate variables everywhere. E.g.: https://github.com/erlang/otp/blob/master/erts/emulator/beam...

There's no need to re-write BEAM in an immutable language.

Mutable data helps performance but it also has "costs" with unwanted bugs from data races in multi-threaded programs, etc. Mutable design has tradeoffs like immutable has tradeoffs.

One can "optimize" immutable data structures to reduce the performance penalty with behind-the-scenes data-sharing, etc. (Oft-cited book: https://www.amazon.com/Purely-Functional-Data-Structures-Oka...)

But those optimizations will still not match the absolute highest ceiling of performance with C/C++/asm mutation if the fastest speed with the least amount of cpu is what you need.

Towaway69 · 1h ago
> Because data is fully immutable, you get a lot of nice things "for free"

This. I discovered this by implementing Flow Based Programming[1] (FBP) in Erlang[2] - the FBP is best suited to languages that are message based and immutable data structures. When using a mutable language, messages are constantly being clone as they are passed around. This does not need to be done using Erlang/BEAM.

My feeling is that FBP is a much under-rated programming paradigm and something really worth exploring as an alternative to the current programming paradigms.

My take on FBP is that data is being passed to functionality, as opposed to function being passed to data - the functional programming paradigm, or data and function is passed around as is the case with OOP.

IMHO it makes sense to pass data to functions, particularly in the times of SaaS and cloud computing.

[1] = https://jpaulm.github.io/fbp/index.html

[2] = https://github.com/gorenje/erlang-red

brabel · 1h ago
That's also Clojure's approach. It's very nice to program with immutable data at a high level, but for certain things, you just need to use the computer's primitives as they actually are, with all the mess that entails. So, I would say we need languages like C++ and Java (but perhaps we should all be using Rust, which makes the mess much more manageable, despite bringing in a lot of complexity that programmers need to wrap their head around, by for example, making it really easy to represent data, and defaulting to immutability) even if it would be "nice" to avoid them where possible.

Erlang and Elixir (and Clojure), however, lack a static type system, which makes it really difficult to use them at large scale (I am happy if you can provide convincing evidence to the contrary - I just haven't seen any). There's Gleam, which is a beautiful, simple language, that has a very good type system, but unfortunately, it's a bit too simple and makes certain things harder, like serialization (e.g. https://hexdocs.pm/gleam_codec/).

Haskell and Ocaml are more usable, but for some reason are extremely niche. I don't think there's any popular language that's in the "statically typed, functional" school, which I think shows that humans just don't prefer using them (they have been hyped for decades now, yet they just never stick). Perhaps a new generation of these languages will change things, like Unison for example (which stays away from Monads but provide an arguably superior abstraction, Abilities - also known as Effects). I think I would love for that to happen, though as I said before: sometimes you still need to reach out for bare metal performance and you have to use Rust/C++/D or even Java.

cbsmith · 3h ago
I didn't like how this essay misunderstood the design principles in Java's class files. With dynamic binding to the runtime, you can't know for certain the layout of a data structure in memory (e.g. what is the ideal memory alignment?). If the class file is untrusted, you can't even be sure you have a valid data structure in the first place. So allocating the array and then assigning elements one at a time is what you do.
nopurpose · 3h ago
So much written about relation between objects and data, but not a single mention of Lisp and derivatives?
mort96 · 2h ago
An excellent opportunity for you to elaborate on the connection, since I'm not seeing it.
lmm · 4h ago
I've had thoughts along this line for a while. I think Scala does better than this article gives credit for; case classes are a significant step in the right direction, particularly post-Scala 3 (or with Shapeless in Scala 2) where you have many tools available to treat them as records, and you can distinguish practically between case classes (values) and objects with identity even if in theory they're only syntax sugar. It also offers an Erlang-style actor system if you want one.

In my dream language I'd push this further; case classes should not offer any object identity APIs (essentially the whole of java.lang.Object) and not be allowed to contain non-value classes or mutable fields, and maybe objects should be a bit more decoupled from their state. But for now I wouldn't let perfect be the enemy of good.

arethuza · 3h ago
"objects should be a bit more decoupled from their state"

Do you mean allowing the "class" of an object to be changed - CLOS can do that. Mind you it's a long time since I wrote any code using CLOS and even then I'm pretty sure I never used change-class.

lmm · 2h ago
The thing I'm envisioning is something akin to typeclass instances / trait impls, but specialised to the case where you have a service with identity rather than being for general function implementation. Just making the bridge between the "bag of state" piece and the "interface implementation accessible via a name/reference" piece a bit more of a first-class citizen.
chuzz · 4h ago
Good post, for what is worth Java is slowly and painfully correcting course with features like records and project Valhalla. As with the other language improvements though we will have to live with the tech debt for decades to come…
high_na_euv · 3h ago
I'd say majority of programming languages struggle with elegant, robust and exhaustive check error handling
mananaysiempre · 1h ago
> Extensibility

> [Data] The schema gives us a fixed set of variants, over which you can of course write any function you want.

> [Objects] We have a fixed set of exposed operations, but different variants can be constructed (including an improved ability to evolve a variant without impacting clients).

No mention of the expression problem? The TL;DR is, sometimes[1] we want both. And sometimes[2] it’s an exceptionally good idea for a lot of slightly different sets of variants to coexist withn the same program, which there also isn’t really a satisfactory solution for.

[1] https://www.craftinginterpreters.stuffwithstuff.com/represen...

[2] https://nanopass.org/

dzonga · 1h ago
clojure + lisps have this approach - everything is data. I encourage everyone to dabble in clojure. it changes your mindset. that when you go back to your regular language you will write better programs.
danieltanfh95 · 3h ago
clojure exists.