Syncing Javascript State across UI - reactjs

There are a lot of questions on syncing state between devices or from external storage to/from the UI. This question is about state within the UI.
The UI may have multiple state objects that can point to one entity.
Eg. Multiple User Models that have the same ID and are essentially the same User in the Database.
The second option is to have a pattern that prevents multiple entities and enforces a single Entity is never duplicated.
Eg. Retrieving a User Model with ID=1 will always return the same Model.
So the options I currently face:
Have multiple Models point to the same DB entity
Enforce a single Instance of a Model reflects a DB entity
Both of these have their tradeoffs:
Have multiple Models point to the same DB entity
This requires syncing the Models with the same ID when a copy if updated.
This becomes non-trivial in implementation.
The current implementation we have is an EntityManager that keeps copies of each model and will propagate writes to all copies.
It however has complexities in syncing due to async writes to the remote copies, reads from other devices and remote fetches as well as reactions (mobx) within models need to ensure they are reacting to a consistent state of the model.
Enforce a single Instance of a Model reflects a DB entity
This requires no work to sync. However we have the complexity of ensuring we don't have any copies of a Model pointing to the same DB entity.
This becomes subject to coding conventions.
Eg.
model.fromJSON({ title: 'foo' })
model.fetch()
Becomes
model = model.fromJSON({ title: 'foo' })
model = model.fetch()
This is hard to understand for new developers and can be missed over time creating hard to debug errors.
The question is how do you generally solve this scenario with a consistent and the least complex in terms of bugs case.

Related

Avoid auto persist when deleting document from embedded association

MongoID currently auto persist the parent document along with the embedded association when removing anything from the embed-many association. Is there a way to avoid this auto persist?
Document model
User has many embedded hobbies
Both the method below auto persist meaning it makes call to DB.
user.hobbies.pop
user.hobbies = [hobby1]
I need to avoid that because I am doing a bulk operation on list of users and want to save extra db calls that are made for embedded associations.

How to model related objects without tight database coupling

I'm designing entities where one is related to another, but keeping application/database separate and also performance in mind.
I've read on many architectual concepts (SOLID, separation of concerns, etc.).
ORM frameworks solve this internally and lazy load the related data when it is accessed.
But is there a practical way without tightly coupling my objects to the ORM and keeping database logic out of them?
Separating the data for a relational database is simple.
For example:
Orders-Table, Customers-Table, Addresses-Table, Countries-Table
Order: id, date, customerId, ...
Customer: id, company, email, defaultAddressId, ...
Address: id, street, countryId, ...
Country: id, name, code, ...
I want to keep the database-related functions separate, so I would create separate repositories, which fetch the data from the database.
For example:
$orderRepository->getById(123);
$customerRepository->getById(234);
$addressRepository->getById(345);
$countryRepository->getById(456);
Sometimes I only need the order data. Sometimes I would need the related Customer and sometimes I need to know in which country the customer lives of the current order.
If I'm only reading a single order, that would all no problem. As I could fetch the needed data in separate variables:
$customer = $customerRepository->getById($order->getCustomerId());
$defaultAddress = $addressRepository->getById($customer->getDefaultAddressId());
$country = $countryRepository->getById($defaultAddress->getCountryId());
But if I want to list many orders on one page (or any other use case with many related objects in one view) and display for each the country name, from which it comes, this would be complicated.
Ideally I would write in the view:
foreach ($orders as $order) {
...
$order->getCustomer()->getDefaultAddress()->getCountry()->getCode();
...
}
From my current knowledge there are three possible solutions:
Lazy loading
The call of $order->getCustomer() will call (maybe a singleton of) the customer repository to fetch the customer object. Then will be the address repository called to fetch the address, then the country repository.
Disadvantage:
many single database calls and each object must know anything about the needed repositories
Fetching all related data, when the orders are fetched
So maybe the repositories call the other repositories to fetch all the data, which their objects need:
OrderRepository:
function getCurrentOrders() {
...code to fetch order data from database...
$relatedCustomers = $this->customerRepository->getByMultipleIds($relatedCustomerIds);
...assigning fetched customer objects to order objects
}
The call to customer repository will lead to call to address repository, which will lead to call to country repository. This would reduce the database calls at first.
Disadvantage:
Data is loaded which is most of the time not needed. It is fine for the list view, but when I only need the direct order infos or only a single order, there are still 3 other calls to the database (in larger object trees maybe many more).
Tailor-made objects for each required view
Either a customized database query which builds a new object with all needed data or some wrapper objects which keep the related objects inside.
Disadvantage:
Could be really complicated when also business logic is needed, as I have to implement the same logic at several points.
How do you keep business logic separate from database code and design entities?

DDD, Databases and Lists of Data

Im at the beginning of my first "real" software project, and I'd like to start off right. The concept of DDD seems like a very clean approach which separates the various software parts, however im having trouble implementing this in reality.
My Software is measurement tracker and essentially stores list of measurement data, consisting of a timestamp and the data value.
My Domain Models
class MeasurementDM{
string Name{get;set;}
List<MeasurementPointDM> MeasurementPoints{get;set;}
}
class MeasurementPointDM{
DateTime Time{get;set;}
double Value{get;set;}
}
My Persistence Models:
class MeasurementPM{
string Id{get;set;} //Primary key
string Name{get;set;} //Data from DomainModel to store
}
class MeasurementPointPM{
string Id{get;set;} //Primary Key
string MeasurementId{get;set;} //Key of Parent measurement
}
I now have the following issues:
1) Because I want to keep my Domain Models pure, I don't want or need the Database Keys inside those classes. This is no problem when building my Domain models from the Database, but I don't understand how to store them, as the Domain Model no longer knows the Database Id. Should I be including this in the Domain model anyway? Should I create a Dictionary mapping Domain objects to Database ids when i retreive them from the Database?
2)The measurement points essentially have the same Id problem as the measurements themselves. Additionally I'm not sure what the right way is to store the MeasurementPoints themselves. Above, each MeasurementPointPM knows to which MeasurementPM it belongs. When I query, I simply select MeasurementPoints based on their Measurement key. Is this a valid way to store such data? It seems like this will explode as more and more measurements are added. Would I be better off serializing my list of MeasurementPoints to a string, and storing the whole list as an nvarchar? This would make adding and removing datapoints more difficult, as Id always need to deserialize, reserialize the whole list
I'm having difficulty finding a good example of DDD that handles these problems, and hopefully someone out there can help me out.
My Software is measurement tracker and essentially stores list of measurement data, consisting of a timestamp and the data value.
You may want to have a careful think about whether you are describing a service or a database. If your primary use case is storing information that comes from somewhere else, then introducing a domain model into the mix may not make your life any better.
Domain models test to be interesting when new information interacts with old information. So if all you have are data structures, it's going to be hard to discover a good model (because the critical element -- how the model entities change over time -- is missing).
That said....
I don't understand how to store them, as the Domain Model no longer knows the Database Id.
This isn't your fault. The literature sucks.
The most common answer is that _people are allowing their models to be polluted with O/RM concerns. For instance, if you look at the Cargo entity from the Citerus sample application, you'll find these lines hidden at the bottom:
Cargo() {
// Needed by Hibernate
}
// Auto-generated surrogate key
private Long id;
This is an indirect consequence of the fact that the "repository" pattern provides the illusion of an in-memory collection of objects that maintain their own state, when the reality under the covers is that you are copying values between memory and durable storage.
Which is to say, if you want a clean domain model, then you are going to need a separate in memory representation for your stored data, and functions to translate back and forth between the two.
Put another way, what you are running into is a violation of the Single Responsibility Principle -- if you are using the same types to model your domain that you use to manage your persistence, the result is going to be a mix of the two concerns.
So essentially you would say that some minimal pollution of the domain model, for example an Id, is standard practice.
Less strong; I would say that it is a common practice. Fundamentally, a lot of people, particularly in the early stages of a project, don't value having a boundary between their domain model and their persistence plumbing.
Could it make sense to have every Domain Model inherit from a base class or implement an interface that forces the creation of Unique Id?
It could. There are a lot of examples on the web where domain entities extend some generic Entity or Aggregate pattern.
The really interesting questions are
What are the immediate costs and benefits of doing that?
What are the deferred costs and benefits of doing that?
In particular, does that make things easier or harder to change?

Normalized Tables in MVC with Concurrency Checking (ACID)

Two part question:
Number 1: What is the best approach in creating a model for an object that references another object, when some of the properties/attributes of the referenced object are not always necessary?
Imagine if you have two objects: PERSON and BUSINESS
Person
+ PersonID
+ Name
+ Age
+ Sex
+ Skill
+ Business *
Business
+ BusinessID
+ Name
+ Address
+ CorporateVision (this is large)
In the example above: A PERSON has a reference to a BUSINESS as their current employer.
In the database, I would have two tables for each object. While in code, using the MVC architecture pattern, I would have two classes for each object. The database would have a foreign-key relationship between BUSINESS-->PERSON, while in code the PERSON object would have a member variable that holds a reference to a BUSINESS object.
Now let's say I want to enumerate on a collection of PERSONS and find out the total number of those that work for a specific company (based on BUSINESS . Name).
Without using MVC, I could just create a function that would query the database and get a count. Simple and efficent.
WITH MVC, I need to instantiate every PERSON object, which in turns, instantiates a BUSINESS object for the reference (if one was not already done for it... the BusinessFactory would check a collection first). Furthermore, it MUST pull in BUSINESS . CorporateVision from the database for every object. And because most of these businesses are Media Marketing Companies, most of their corporate visions are large text blobs. So it is very unnecessary to read CorporateVision from the database when all we need is the name of the business.
I could solve this problem by having changing the PERSON object in code to:
Person
+ PersonID
+ Name
+ Age
+ Sex
+ Skill
+ BusinessID
+ BusinessName
So now when I create my PERSON object, I do a JOIN with BUSINESS and cache the name. Now I can get the BusinessName quickly and efficiently... and I still can get the full BUSINESS object as needed by doing a lookup on the ID. But I just denormalized the model... and I just introduced a new problem... and a new question.
Number 2: How does MVC handle concurrency with a multi-user database?
Lets say while my client application is enumerating (using the enumeration that I mentioned above that finds all people that work for a particular business), another user merged two of the BUSINESS objects.
Now my in-memory collection is wrong because all of the BusinessName caching is stale. The same could be true if I had just left the PERSON . Business as a BUSINESS object reference: The BUSINESS object would be stale.
In summary: I feel that with MVC I lose data retrieval efficiency as well as the loss of the ACIDness of my application. Or am I using MVC wrong?
You seem to mix UI and Data access, while you should minimize their dependencies over another. MVC is actually a pretty broad pattern which describes how application interacts with user. Both your questions are related to data access.
1) MVC is the way you organize UI. So, model is a piece of information you want to make user interact with. Note, business objects are not priority here. If there is a case when use loads a Person class along with several properties from Business, so be it: your second Person rendition is a perfect model for this case. And so on - each use case requires a different model and you should create different model for different scenarios.
If you think it's easier for you to call a function to calculate the number - fine. Remember, you are not bound to business objects here.
With more 'object'-oriented approach we usually solve this reference problem in two ways:
first is lazy loading, with is out-of-the-box feature for modern O/RMs. So you load a person and after a first call to Person.Business, latter is loaded automatically.
second is that you create a special kind UI, which is aware of your data access specifics and either has only fields you use, or requests additional data in an async manner from a client.
2) Again, MVC doesn't handles concurrency, and it shouldn't handle it and shouldn't even bother. It's a concern of data access layer. And there are also several ways to deal with concurrency, major of them are optimistic and pessimistic locks. (With the first one you allow different users to make conflicting changes and try to resolve conflicts when they occur. The second way prevents conflicts by locking updates completely). Again, O/RMs deal with it usually; or you can use your own implementation, but it should be still data access, not MVC part.

Data Modeling - modeling an Append-only list in NDB

I'm trying to make a general purpose data structure. Essentially, it will be an append-only list of updates that clients can subscribe to. Clients can also send updates.
I'm curious for suggestions on how to implement this. I could have a ndb.Model, 'Update' that contains the data and an index, or I could use a StructuredProperty with Repeated=true on the main Entity. I could also just store a list of keys somehow and then the actual update data in a not-strongly-linked structure.
I'm not sure how the repeated properties work - does appending to the list of them (via the Python API) have to rewrite them all?
I'm also worried abut consistency. Since multiple clients might be sending updates, I don't want them to overwrite eachother and lose an update or somehow end up with two updates with the same index.
The problem is that you've a maximum total size for each model in the datastore.
So any single model that accumulates updates (storing the data directly or via collecting keys) will eventually run out of space (not sure how the limit applies with regard to structured properties however).
Why not have a model "update", as you say, and a simple version would be to have each provided update create and save a new model. If you track the save date as a field in the model you can sort them by time when you query for them (presumably there is an upper limit anyway at some level).
Also that way you don't have to worry about simultaneous client updates overwriting each other, the data-store will worry about that for you. And you don't need to worry about what "index" they've been assigned, it's done automatically.
As that might be costly for datastore reads, I'm sure you could implement a version that used repeated properties in a single, moving to a new model after N keys are stored but then you'd have to wrap it in a transaction to be sure mutiple updates don't clash and so on.
You can also cache the query generating the results and invalidate it only when a new update is saved. Look at NDB also as it provides some automatic caching (not for a query however).

Resources