As we know, when saving data in a redux store, it's supposed to be transformed into a normalized state. So embedded objects should be replaced by their ids and saved within a dedicated collection in the store.
I am wondering, if that also should be done if the relationship is a composition? That means, the embedded data isn't of any use outside of the parent object.
In my case the embedded objects are registrations, and the parent object is a (real life) event. Normalizing this data structure to me feels like a lot of boilerplate without any benefit.
State normalization is more than just how you access the data by traversing the object tree. It also has to do with how you observe the data.
Part of the reason for normalization is to avoid unnecessary change notifications. Objects are treated as immutable so when they change a new object is created so that a quick reference check can indicate if something in the object changed. If you nest objects and a child object changes then you should change the parent. If some code is observing the parent then it will get change notifications every time a child changes even though it might not care. So depending on your scenario you may end up with a bunch of unnecessary change notifications.
This is also partly why you see lists of entities broken out into an array of identifiers and a map of objects. In relation to change detection, this allows you to observe the list (whether items have been added or removed) without caring about changes to the entities themselves.
So it depends on your usage. Just be aware of the cost of observing and the impact your state shape has on that.
I don't agree that data is "supposed to be [normalized]". Normalizing is a useful structure for accessing the data, but you're the architect to make that decision.
In many cases, the data stored will be an application singleton and a descriptive key is more useful than forcing some kind of id.
In your case I wouldn't bother unless there is excessive data duplication, especially because your would have to then denormalize for the object to function properly.
Related
Very simple:
Let’s say we use RTK-Query to retrieve the current weather.
For that, I pass to the endpoint the arg ‘Paris’ as city.
It will serve the current weather of my « game ».
Then later, in a Redux selector, I need to compute some derived state based on that current weather.
How to read the state without having to pass the cache key « Paris »?
Indeed, that knowledge of « Paris » was only necessary at the beginning of the app.
It seems that with RTK-Query we’re stuck since you have to pass the argument that was used (the cache key) to the endpoint#select method.
Am I right in saying that RTK-Query does not currently allow that kind of state reading:
« select that current (and single) store entry X whatever the argument that was needed at loading time is ».
No, since that's an edge case.
Usually, there are multiple cache entries per endpoint, and there is also no concept of a "latest entry" or something, since multiple different components can render at the same time, displaying different entries for the same endpoint - the concept of a "latest" there would come down to pretty random React rendering order.
The most common solution would be to just safe "Paris" somewhere in global state to have it readily available, or to write your selector against RTKQ store internals by hand (although there might be changes to the state internals in the future).
Hello,
I'm working on a project in which the main part of the data has a complex structure as you can see in the above picture.
Now, the object, in reality, is much complex than that but what I showed it servers the purpose.
Because in DB they are linked together in tables relationship the first time when the website is launched, after log in, a list of projects will come together with some small details of technology and dataObjects.
I created separated action and effects files but everything is handled by a single reducer. What I mean is at the start, the list of projects will be saved on a state, than any other actions like Create a project, technology, data object, edit, delete has to perform actions over the same state "projects-state".
For example besides technologyAPIS will be another 3-4 technologies, inside each technology object will be another list of objects.
The issue here is that the reducer file is getting bigger and bigger when it handles all kinds of actions that will perform actions over the specific data from the state. It is important that the chain of Objects stay together.
My question is, is this a bad approach? it can be handled in a different way? I know I can create a reducer for each entity (project, technology, data app) but I will lose that relationship between them, where one belongs to the other?
Thank you so much for your feature response
I've only been doing reactive/NGRX for a few months now, but from my understanding, thats defiantly a bad approach. It should still work, but may be a hassle to debug/maintain.
Ngrx seems to be promoting 'Normalising' data, just like the usual Relational Database concept.
You could break down your project-state into smaller states, with relational keys in them.
Example
Projects state (not to be confused with project-state)
id:number
projectDescription:string
createdBy:string
techAPIs:number[] //where the content here is the id of the TechApi
TechApi state
id:number
otherInfo:any
And then when you need to access the TechApi state for a project, you retrieve it and filter/map it in a selector.
This is a some what General Example if my explanation is not understandable.
I have a Core Data model with something like 20 entities. I want all entities to have common attributes. For example, all of them have a creation date attribute.
I therefore introduced an common entity containing all the common attributes, and all the other entities inherit from this common entity.
This is fine and works well, but then, all entities end up in one single SQLite table (which is rather logical).
I was wondering if there was any clear drawback to this ?
For example, when going in real life with 1000+ objects of each entity, would the (single) table become so huge that terrible performance problems could happen ?
This question has been asked before:
Core Data entity inheritance --> limitations?
Core data performances: when all entities inherit from the same parent entity
Core Data inheritance vs no inheritance
Also keep in mind that when you want to check the SQLite file for debugging purposes, seperate tables are easier to examine.
I would use a common NSManagedObject subclass instead of a parent entity.
Don't worry about this. From Core Data documentation:
https://developer.apple.com/library/tvos/documentation/Cocoa/Conceptual/CoreData/Performance.html
... The SQLite store can scale to terabyte-sized databases with billions of rows, tables, and columns. Unless your entities themselves have very large attributes or large numbers of properties, 10,000 objects is considered a fairly small size for a data set.
What is way more important is that if you are doing any heavy operations, like fetching a lot of objects, or parsing objects based on some JSON from a webservice, you do this not on the mainthread. This is not very hard to do, look into parent/child managedobjectcontexts and how they can be used with managedcontextobjects with a private / main queue concurrencytype. Many good blog posts about this subject exist all over the interwebs.
I've been working on a project with one base entity for around 20 subentities and easily overall 50k instances for over 2 years now. We've never had performance problems with selects, inserts or updates.
The keys to using Core Data inheritance with large data sets are
optimized fetch requests (tune predicate, exclude irrelevant properties, prefetch relationships, omit subentities, set fetchLimit, use dictionary result type or count-requests if sufficient etc.)
batch saves (meaning not saving the MOC after every insert etc.)
setting up proper indices (they can speed up selects a looot)
structuring your UI appropriately so you won't have to load and display many thousand objects in one viewController
We do not even use parent/child managedObjectContexts or private queues (which introduce a lot of extra complexity on their own) when importing JSON, as our data model and mapping code is so highly optimized, that the UI doesn't even flicker or hang considerably when importing a few thousand objects.
I have several graphs. The breadth and depth of each graph can vary and will undergo changes and alterations during runtime. See example graph.
There is a root node to get a hold on the whole graph (i.e. tree). A node can have several children and each child serves a special purpose. Furthermore a node can access all its direct children in order to retrieve certain informations. On the other hand a child node may not be aware of its own parent node, nor other siblings. Nothing spectacular so far.
Storing each graph and updating it with an object database (in this case DB4O) looks pretty straightforward. I could have used a relational database to accomplish data persistence (including database triggers, etc.) but I wanted to realize it with an object database instead.
There is one peculiar thing with my graphs. See another example graph.
To properly perform calculations some nodes require informations from other nodes. These other nodes may be siblings, children/grandchildren or related in some other kind. In this case a specific node knows the other relevant nodes as well (and thus can get the required informations directly from them). For the sake of simplicity the first image didn't show all potential connections.
If one node has a change of state (e.g. triggered by an internal timer or triggered by some other node) it will inform other nodes (interested obsevers, see also observer pattern) about the change. Each informed node will then take appropriate actions to update its own state (and in turn inform other observers as needed). A root node will not know about every change that occurs, since only the involved nodes will know that something has changed. If such a chain of events is triggered by the root node then of course it's not much of an issue.
The aim is to assure data persistence with an object database. Data in memory should be in sync with data stored within the database. What adds to the complexity is the fact that the graphs don't consist of simple (and stupid) data nodes, but that lots of functionality is integrated in each node (i.e. events that trigger state changes throughout a graph).
I have several rough ideas on how to cope with the presented issue (e.g. (1) stronger separation of data and functionality or (2) stronger integration of the database or (3) set an arbitrary time interval to update data and accept that data may be out of synch for a period of time). I'm looking for some more input and options concerning such a key issue (which will definitely leave significant footprints on a concrete implementation).
(edited)
There is another aspect I forgot to mention. A graph should not reside all the time in memory. Graphs that are not needed will be only present in the database and thus put in a state of suspension. This is another issue which needs consideration. While in suspension the update mechanisms will probably be put to sleep as well and this is not intended.
In the case of db4o check out "transparent activation" to automatically load objects on demand as you traverse the graph (this way the graph doesn't have to be all in memory) and check out "transparent persistence" to allow each node to persist itself after a state change.
http://www.gamlor.info/wordpress/2009/12/db4o-transparent-persistence/
Moreover you can use db4o "callbacks" to trigger custom behavior during db4o operations.
HTH
German
What's the exact question? Here a few comments:
As #German already mentioned: For complex object graphs you probably want to use transparent persistence.
Also as #German mentione: Callback can help you to do additional stuff when objects are read/written etc on the database.
To the Observer-Pattern. Are you on .NET or Java? Usually you don't want to store the observers in the database, since the observers are usually some parts of your business-logic, GUI etc. On .NET events are automatically not stored. On Java make sure that you mark the field holding the observer-references as transient.
In case you actually want to store observers, for example because they are just other elements in your object-graph. On .NET, you cannot store delegates / closures. So you need to introduce a interface for calling the observer. On Java: Often we use anonymous inner classes as listener: While db4o can store those, I would NOT recommend that. Because a anonymous inner class gets generated name which can change. Then db4o will not find that class later if you've changed your code.
Thats it. Ask more detailed questions if you want to know more.
This is a common case for a developer. You want to add a feature for every content types of your website that need to store data. It is a kind of metadata, not configuration data.
I see two solutions:
zope.annotation
setattr: add attribute to the persistent object
I don't really know why but from Plone2.5 it was nice to use zope.annotation and now it seems to not be the prefered way to store additionnal data. For example plone.uuid use setattr to store the unique id.
Either one, depending on how often your data changes and how big it is. It's all about how the ZODB stores this information.
Storing data directly on the object using setattr means that data is stored in the persistent record for that object. If that's a big object that means there is a big transaction going to take place for that write.
Storing data in a zope.annotations annotation means you get a separate persistent record for each annotation entry, so any changes to your data will result in a smaller transaction. But if you want to access this data often, that extra persistent record will need to be loaded, on top of all the other persistent records. It'll take a slot in your ZODB cache, your ZEO server or RelStorage server will need to serve it, etc.
plone.uuid uses setattr because it is generally generated only once for a given object, usually at a time it is being created already. It is also a piece of data that is accessed often and quite small. So, by putting it directly on the object itself it'll be loaded as soon as you load that object, no extra trips to the ZODB required, and it'll only be changed once in it's lifetime.
Note: the above presumes that the annotations are stored with the AttributeAnnotations adapter, which is the most common method and the default for Plone content.