Skip to content

Introducing UserDataReader/UserDataWriter #1177

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

Merged
merged 6 commits into from
Jan 31, 2020

Conversation

schmidt-sebastian
Copy link
Contributor

This renames UserDataConverter to UserDataReader and refactors out the Java type conversion in DocumentSnapshot to UserDataWriter.

Note: This is against master.

Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM, though I'm not a huge fan of the mocking changes. I've included an idea that could simplify the writer implementation and possibly avoid the mocking changes, so start there before investing too much in addressing the other comments; they might be irrelevant.

@@ -33,7 +33,7 @@

public static FieldValue wrap(Object value) {
DatabaseId databaseId = DatabaseId.forProject("project");
UserDataConverter dataConverter = new UserDataConverter(databaseId);
UserDataReader dataConverter = new UserDataReader(databaseId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the local to dataReader?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I had caught all of these, but this PR went through a lot of iterations. Fixed now.

* Install mocks for `FirebaseFirestore.getFirestoreSettings()` and
* `FirebaseFirestore.getUserDataWriter()`, which are used in DocumentSnapshot tests.
*/
public static void installDocumentSnapshotMocks(FirebaseFirestore firestore) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of centralization of mocking creation makes me uneasy. It seems like we're using the wrong tool for the job. If TestUtil.firestore() returned a real instance of Firestore these tests wouldn't have to mock anything to get what's otherwise default behavior of the instance.

Also, the function of this particular class is to expose as public methods things that are otherwise access protected in the public API. A way to allow mocking of package private methods would be just to contralize the Mockito.when call like this:

  public static OngoingStubbing<UserDataReader> getUserDataWriter(FirebaseFirestore firestore) {
    return Mockito.when(firestore.getUserDataWriter());
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

installDocumentSnapshotMocks() is not needed in our codebase to bypass access restrictions, but it was in the Kotlin tests since they live in a subpackage.

Either way, I reverted this change as I removed the getUserDataWriter() instance method on FirebaseFirestore.

private Map<String, Object> convertObject(
ObjectValue objectValue, UserDataWriterOptions options) {
Object result = userDataWriter.convertValue(objectValue, options);
hardAssert(result instanceof Map, "Documens should be decoded into Maps");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Documens/Documents/

result.add(convertValue(v, options));
}
return result;
private Map<String, Object> convertObject(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it could reasonably just be a part of the UserDataWriter API, making it more self-contained as to how to use it safely.

Indeed there's already a convertObject method there; why not just use that and avoid asserting/casting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea behind this was to only expose a single method in UserDataWriter. I don't feel strongly and made convertObject package private.

private final FirebaseFirestore firestore;

/** Holds settings that define field value deserialization options. */
static class UserDataWriterOptions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea if this is a good idea, but what do you think of making these things properties of the UserDataWriter itself?

We already have to allocate a UserDataWriterOptions object so it's not like we're avoiding heap allocations with the current scheme. Meanwhile it would save us having to pass the options up and down every call.

This would allow you to remove the getUserDataWriter method on FirebaseFirestore and the associated mocking weirdness.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version of the PR that I showed you yesterday (that addressed both UserDataConversion and CanonicalIds) actually did just that. It was needed because I did not want to expose options in the canonical ID API. I scrapped this since I didn't want to create the extra object. You are correct though that I am still creating an extra object - and we will likely not be able to get rid of it since timestampsInSnapshots will have to stay around even when we drop in from Settings, as DocumentSnapshot.getDate() relies on it.

I reverted the parts of the last edit that removed the constructor params for serverTimestampBehavior and timestampsInSnapshotsEnabled.

@wilhuff wilhuff assigned schmidt-sebastian and unassigned wilhuff Jan 30, 2020
Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@wilhuff wilhuff assigned schmidt-sebastian and unassigned wilhuff Jan 31, 2020
@schmidt-sebastian schmidt-sebastian merged commit 1548002 into master Jan 31, 2020
@schmidt-sebastian schmidt-sebastian deleted the mrschmidt/readerwriteronmaster branch February 7, 2020 00:22
@firebase firebase locked and limited conversation to collaborators Mar 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants