| The argument isn't that complexity is being hidden, but how it's managed and where it shows up in your experience of solving other problems. OP mentions: > The complexity was always there... it merely shone a light on the existing complexity, and gave us the opportunity — and a tool with which — to start grappling with it It's not about Rust vs. TypeScript per se but uses garbage collection and borrow checker as examples of two solutions to the same problem. For whatever task you have at hand, what abstractions offer the best value that lets you finish the solution to the satisfaction of constraints? > they are tightly coupled with the code written around them Which is where the cost of the abstractions comes in. Part of the struggle is when the software becomes more complicated to manage than the problems solved and abstractions move from benefit to liability. The abstractions of the stack prevent solving problems in a way that isn't bound to our dancing around them. If I'm working on a high-throughput networked service shuffling bytes using Protobuf, I'm going to be fighting Node to get the most out of CPU and memory. If I'm writing CRUD code in Rust shuffling JSON into an RDBMS I'm going to spending more time writing and thinking about types than I would just shuffling around arbitrarily nested bag-of-bags in Python with compute to spare. I always thought this was why microservices became popular, because it constrained the problem space of any one project so language abstractions remained net-positives. |
That’s what I’m talking about. Encoding complexity in your types does not manage where that complexity lives or where you have to deal with it.
It forces you to deal with that complexity everywhere in your codebase.