-
Notifications
You must be signed in to change notification settings - Fork 731
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
Final instances vs Incomplete instances vs Update-in-place #589
Comments
A thought I had today. So: GHLabel label = getLabel(myLabelName);
// two network calls, each returning a new instance
label = label.updateName("New Name").updateColor(newColor);
// one network call, returns new instance
label = label.update().name("New Name").color(newColor).apply();
// one network call, updates in place? Maybe not.
// I'd really rather have instances be effectively final so their hashCode and equality are stable.
// Set the state of the connection to update in place.
// This changes all instances created with this connection to update in place.
github.updateInPlace(true);
label = github.getRepository(myRepoName).getLabel(myLabelName);
label.update().name("New Name").color(newColor).apply(); |
Current design for the So: GHLabel label = getLabel(myLabelName);
// two network calls, each returning a new instance
label = label.set().name("New Name");
label = label.set().color(newColor);
// one network call, returns new instance
label = label.update().name("New Name").color(newColor).done(); Possible designs to handle "update in place"Firstly, in all cases, the enum UpdateInPlace {
// Lets objects and operations decide for themselves if they will update in place
// NOTE: `hashCode()` and `equals()` are not guaranteed stable with this setting enabled
// Individual classes classes or instances can override this.
ALLOWED,
// throw if update in place is attempted.
// NOTE: `populate()` should still succeed.
// `refresh()` does not update current instance, returns a new instance.
// QUESTION: Should get `hashCode()` and `equals()` automatically call `populate()` to ensure they are stable?
NEVER,
// always update in place
// NOTE: `hashCode()` and `equals()` are not guaranteed stable with this setting enabled
// `refresh()` updates current instance and returns it (but return can be ignored.
ALWAYS
}
GitHub gitHub = new GitHubBuilder().updateInPlace(UpdateInPlace.ALWAYS).build(); There are then several ways individual classes and instances can choose to update in place or not. For the Add
|
#495 and #496 raise an interesting point. Also #584.
This project currently tends to treat instances of data objects as "final" - you request an Issue and the instance you requested never changes after that. That instance is a stable snapshot and can be used as a key in a HashSet or Map without fear of it changing.
We also have action and update methods on these objects. In general, these methods update the state of the server-side object the instance is based on, but do not change the data in the instance. You call
close()
ordelete()
or one of theset*
methods and a request is sent to change the object on the server, but the data in the local instance doesn't update to match. This is consistent with the "final instances" model but has some problems. There's no batching of updates (each action is another query) and since the local instance is out of date, updates can end up overwriting each other as in #495. The only current workaround is send another request to get a fresh instance for each update. 😱The
Builder/Updater
pattern added to some objects addresses this by batching updates together and then returning a new instance matching those updates. This solves the problem of stale data but results in verboseitem.update().title('New Title').update()
syntax for single field changes. It does partially unblock update-in-place asitem = item.update().title('New Title').update()
.Finally, some objects can be incomplete when first created - either due to their source (partial information provided as part of creating another object) or due to the target only updating on request (pull request mergability is only updated after the first time PR is queried after a new commit is pushed). For these cases, we currently update in place. Do we want to force users to get new instances instead?
There's no one right way to do this, but we should look at how to make this behavior consistent across all objects.
A couple random thought s off hand about this:
set*
method naming is misleading - best practice in my understanding is to makeget*
andset*
methods local and lightweight. Alternative would be to haveupdate*
methods that actually send updates to the server.GitHub
object to create objects in those state. Rather than having updaters for objects, users would get a mutable instance. Possible states for data objects: immutable, immediate mutable, batch mutable. Not sure how the incomplete objects figure into this yet.The text was updated successfully, but these errors were encountered: