4 ms·
The comment was mainly related to in-memory variables within an application process...focusing on scoping/syntax...but the thinking was definitely inspired by t
by valty 3y ago
The comment was mainly related to in-memory variables within an application process...focusing on scoping/syntax...but the thinking was definitely inspired by the fact that most apps center around an external database without realizing its essentially a global variable.
In application code, when I talk of global vars, I mean that every function has access to all data...as opposed to access being abstracted and modularized into various services which are exposed via being passed through a chain of function args, or some kind of dependency injection system.
But this global variable could actually be an abstraction (a store) allowing data integrity checks on writes.
> there is probably data that we’re working with that is not the state that ultimately persists within the database
If you think about all your data in one big graph, this transient data still has a relation to the final persisted state. There is a data flow of transient values into the persisted data values. And separately, your intermediate data structures might also contain relations to your persisted data structures.
Most dev tools don't track these relationships, and you have this tangled ad-hoc mess where data is dumped from one structure to the next.
> “UI state” data...we’d need to include every possible piece of UI state for the whole application in the global store.
Yep, this is what you should do.
If I am sorting something on a webapp and I refresh the browser, I probably want to have see the same things as they were sorted. This might vary between use case, but adding the functionality should be easy to do if necessary. So therefore it is good practice to allow all local ui state to be persisted by default.
The ui state is being persisted anyway, inside a component or inside the HTML document. Somewhere in the heap this data is stored. And if we think about our one big graph again, this data is related to other things...its just that we lose these relations.
> A related issue is how to represent temporary clones of significant parts of the data
All rendered UI values should be in their own _ui_ models (view model is similar), separate from the source of truth models.
These ui models basically allow all rendered UI to be editable without immediately committing changes to the database. This allows for optimistic UI updates. They get notified of any incoming changes from the source of truth, and can decide what to do with them.
If you want to batch them up, you just create a Batch entity, and add a relation to these ui models. The main thing is to treat the ui models like any other models. Whether they are persisted or not should simply be flipping a flag in your code.
For UI, everything should be in one big graph. Code is data.
I find with modern programming, all of the popular programming languages, frameworks, libraries, databases, platforms, really get in the way of being able to do things simply.
- Chris_Newton 3y agoAgain, I like a lot of the thinking behind this. I’m personally a big fan of having clear data models and data flows, and I think there is a lot of potential in ideas like reactivity that clearly define sources of truth and relationships in single places so derived state gets updated automatically when its underlying source(s) of truth change. I also believe realising the full potential of some of these ideas will, as you’ve mentioned yourself, need better tools than we currently have. However, we can already get pretty far with these ideas, and when they work well, it certainly does make for a nice, clear, easy-to-follow design compared to having state and relationships scattered all over the code base. Where I suspect we might disagree is the idea that everything should fit into this model. Sometimes the data models and relationships get more complicated and the one-way flows implied by the basic idea of reactivity are no longer sufficient. Sometimes the shape of the data flow graph changes on the fly, because we need multiple instances of certain parts of the state. Then we need a way to distinguish between those instances and often some way to connect the repeated parts of the graph back to the wider graph so that we can make changes to the duplicated parts but still enforce relationships with other parts of the data model. I have never so far seen a reactivity-based approach to modelling state that handles more demanding scenarios like these gracefully, nor a convincing theory for doing so without introducing more than just a general global data store and simple reactivity. This is where I believe there is still a lot of potential for finding better ways to model the data and then better tools to implement those models. The trick, as again you said yourself, is to find the essential aspects and make it simple to describe them without the accidental complexity from the tools becoming excessive.
- PeterisP 3y agoIn this context when people say "global variable" it is effectively shorthand for "arbitrary accessible shared mutable state" and the associated risks of mutating something which other code expects to stay the same, and also often unintentionally coupling things without it being clear that they are coupled. I'd argue that an external database is not necessarily such a thing - it can be and sometimes is, but in many (most?) applications there generally is a somewhat well-defined layer that manages that state mutation and enforces any constraints needed, isolating the "global variable" from the rest of the program, just as a singleton class with constrained setter functions could do for an OOP approach to a shared state that's arguably fixes most issues with "naked" global variables; and standard data flow analysis in specifications can make explicit any coupling between components that happens "through the DB".