Skip to content

Provide Background on ObjectState #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
TylerBrock opened this issue Dec 18, 2015 · 2 comments
Closed

Provide Background on ObjectState #127

TylerBrock opened this issue Dec 18, 2015 · 2 comments

Comments

@TylerBrock
Copy link
Contributor

Hey everyone, I know there is a lot going on and it is the holidays so I apologize in advance if this is a nuisance but I'd like some background on the global object state being maintained JS SDK. I'm not quite sure how to describe this issue except to phrase it as an honest question.

Can someone describe why the JS SDK implemented the functionality this way?

I appreciate but don't fully comprehend the efforts of trying to keep objects up to date for the user. It seems like global state for a NodeJS application in any capacity is a bad idea. In fact, global user state is part of what triggered the previous re-write of the Parse JS SDK.

Clearly, if an object is read, changed locally but modified somewhere else before saving it, you will smash over the first change when you go to persist the object. However, there has to be a more elegant way to do this.

If that is the reason this part of the SDK exists it might it be better to keep a version # or something that is provided with the update to ensure that you only update the object if the version in the DB still matches that of the object you want to modify (if greater then fail).

As implemented, this produces very surprising behavior such as what is observed by myself and others in #91 and #111. Perhaps some additional background would help us understand why the bookkeeping in and around ObjectState is needed.

@andrewimm
Copy link
Contributor

Ultimately, it's because the JS SDK is designed as a client-first SDK. The use cases we see are almost all from a web app, and this architecture allows developers to build apps that stay in sync. It also opens us up to doing things like offline storage, similar to the other SDKs (which, in fact, implemented this type of behavior first).
It also dramatically simplifies a number of corner cases you may not think of off the top of your head, but which we need to support -- things like handling changes / saves while another save is already in progress. Stacking these in a central location makes it easier to manage them.
Another reason: Object-oriented programming is not necessarily the way developers will want to manage Parse Objects in the future. Having the true "contents" of an object stored separately from a ParseObject instance allows for easier unit testing today, and will allow us to implement other interfaces (like the more functional operations of Parse+React) down the line. I'm already working on experimental libraries to do this.
Automatically updating local objects when new data comes from the server; inflating pointers when you have the current object in memory; maintaining synchronicity across UIs without implementing a Flux architecture; there are many benefits to this type of shared-object-data structure.

As this is designed for client applications, it's also not ideal for node ones. It is for this reason that node applications, by default, do not have "single instance" mode enabled, because as you point out, global state is generally a bad idea. Instead, they currently use the same backing mechanism, but do not share data between Parse Object instances. Otherwise, it would be difficult to implement a beforeSave type interaction (no way to see the old state and the new state simultaneously).
In the short term, the solution to memory leaks is to avoid using the standard global store in node apps, and instead store them in a way that they are attached to the object (either directly as a property, or more likely in a weakmap). FWIW, the global storage isn't really what's causing your pointer issue, since objects do not share instances in Node. In both 1.5 and 1.6, in your code sample, brand === savedBrand === updatedBrand... it has absolutely nothing to do with global objects; in fact, quite the opposite, it's allocating fresh new instances of Item when the response comes back.

We don't take architectural decisions lightly. We decided that a global storage structure would unify the architectures of the 4 major SDKs and make development much easier for us (Parse engineers) and end developers by reducing bugs and weird edge cases.

@andrewimm
Copy link
Contributor

Archiving this as a discussion issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants