There is a controller in the sense you are describing, but the reads and writes are clearly decoupled as separate, functional steps, while the data is just a plain composition of maps and lists.
Putting these operations into classes is a regression from this point of view. You suddenly get these artificial objects (models) that get harder to extend, reuse and change, because you have relations between objects that you somehow need to model and synchronize as well.
Imagine if databases worked this way. Gladly they don't. They have a uniform, declarative language that you use to interact with them and the data is just data, no matter if it is a Person, Cat or w/e.
So in a sense these libraries are re-inventing databases to handle GUI state in the browser, which is a good thing.
Mutable data makes mutation easy and undo hard.
I don't know if there's a good solution. The command pattern is based off mutable data, and works, but has lots of boilerplate and implementation (to mutate the document forwards and backwards).
I don’t grok how one can write 100+ ceremony loc to filter a todo by a “.completed” flag and still think it is okay to burn a barrel of cash and half a day to implement that [1]. I also don’t grok how this approach can work any “faster“ or battery/memory-saving or be used sanely in apps slightly bigger than my generic todolist. It is both millions of dollars of bootstraps, boilerplates and learning curves for what supposed to be a simple logic.
Maybe I’m wrong, but it feels almost like a conspiracy to justify 6.5-figure contracts and nothing more. And the rest of developers just rationalizing around this phenomenon.
That’s what react/redux has done to you, selling this ‘immutable functional’ flavoured thing. While it is immutable at the programming surface, it is actually a series of complex updates with little to no help from the ‘store’ for convenient access. In pure js, when you want project.tasks, you just:
In “immutable functional state transformer based on async-dispatched store”, which these re-whatever buzzwords are, you cannot have neither smart data items, nor a good controller that could join unrelated objects together, nor recombinable data sources, nor nice testable api boundaries. And when someone whispers MVC, you think about web 1.0 patterns, with it’s “MC in MVC is backend roundtrip” meaning.This particular example is a set of five dead-simple classes (DB, Project, Task, TaskListController and TaskListView), almost all orthogonal and useful/testable on their own. Easy for imperative thinking and managing^, cause UI is suddenly imperative. You constantly battle with immutability, lack of control, state copy-transfer and tons of boilerplate for a simple action, can’t you see? You’re doing a monad bind operation by hand, because there is no do-notation in your language, and where there is, it exists and is called “do” for a reason. How did they miss that completely? /rant
^ e.g. want to see deleted tasks? Write a getter in a controller or a db (depending on locality requirements) and use it in a view as if it was a pojo array. Reimplement on demand to leave your tests and logic intact.