Skip to content
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

Refactored Firebase library #42

Merged
merged 19 commits into from
Jan 29, 2016
Merged

Conversation

ed7coyne
Copy link
Collaborator

As discussed in issue #41

Refactored to provide result and not depend on class state for error reporting, conform to Google C++ style.

Also broke FirebaseEventStream out from Firebase. When this is connected I believe any other calls (push,fetch,etc..) to the class would break it. For that reason it really seems like this should be its own focused class. Or you need large comments explaining this gotcha.

@ed7coyne
Copy link
Collaborator Author

Also should note this is based on the other pull request so ignore that one here and only accept this one when that one is in.

@proppy
Copy link
Collaborator

proppy commented Jan 13, 2016

Also broke FirebaseEventStream out from Firebase. When this is connected I believe any other calls (push,fetch,etc..) to the class would break it. For that reason it really seems like this should be its own focused class. Or you need large comments explaining this gotcha.

If we make sendRequest call _http.stop() that should allow the user to do a post() and then resume stream().

As I commented on #41: I'm not sure we should make it easy for the user to do multiple thing at a time with the same client. If they want to do streaming and post update they could create multiple instance of the Firebase object, if they want to reuse the same object they have to call stream() again if they want to resume streaming

The idea was that stream() was at the same level than other HTTP methods like post(), get() etc but long running: #43 try to make it more obvious by decoupling "getting the result" from "making the request".

Ideally I like to converge in a direction where there the only difference between get() and stream() is that you can call read() or data() multiple time after stream()

// handle error.
if (fbase.error()) {
// add a new entry.
FirebaseResultWithMessage push = fbase.push("/logs", "{\".sv\": \"timestamp\"}");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is that a different type: FirebaseResultWithMessage? I don't see it declared in Firebase.h

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yup, I had it then decided it wasn't worth the complexity to maintain two types. I liked that it was explicit in what returned a body and what didn't.
I will fix it.

@ed7coyne
Copy link
Collaborator Author

I did a major change over to a different paradigm. Let me know what you think of this one. This pushes more of the logic into the returned object a FirebaseCall. This allows the optional rawResponse() call or the library to not read the response if the user is not interested in it. It reuses the http object for all calls except the streaming one.

I still kept the streaming impl pretty separate but accessable through the main Firebase interface. It just feels really disjoint to me. It holds the http object for a while, the others are all immediate. It allows multiple reads, it has events.

I am off until next week so we can discuss more then, just wanted to post this up. I am not sure the streaming example works for me either.

void loop() {
if (fbase.error()) {
void loop() {
static FirebaseEventStream stream = fbase.stream("/bitcoin");
Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't realize this would force the user to store a static, I think we should find a way that keep the state in the Firebase object so that the user don't have to worry about the lifetime of the result object.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ya I am still playing with that but it would have to be either a static like this and use return value optimization to allow this to be constructed or to switch over to returning a unique_ptr which is a little ugly but would work like we want.

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we could move this as a global?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Give it a shot, I thought something was preventing that from working. I think it was you can't construct the event stream until setup() is called which won't happen if you directly initialize the global.
It isn't really a copyable object with the HTTP connection so you can't create a global then copy this value in.
I think we either need to make it a movable object which is probably the cleanest for the client, or return a unique_ptr<> to the object on the heap. This way is the most standard for c++ but maybe not arduino and looks ungly.

@proppy
Copy link
Collaborator

proppy commented Jan 20, 2016

I did a major change over to a different paradigm. Let me know what you think of this one. This pushes more of the logic into the returned object a FirebaseCall. This allows the optional rawResponse() call or the library to not read the response if the user is not interested in it. It reuses the http object for all calls except the streaming one.

Made a few more comments, I like the separation of the logic but I'd like to find a way not to push the FirebaseCall type and its lifetype to the user.

I still kept the streaming impl pretty separate but accessable through the main Firebase interface. It just feels really disjoint to me. It holds the http object for a while, the others are all immediate. It allows multiple reads, it has events.

I feel like the streaming impl is a call that can yield multiple result, all the other methods also hold the http object in a way since they don't re-inialize the connection between each call.

@proppy
Copy link
Collaborator

proppy commented Jan 20, 2016

I feel we should hold on the refactoring until we merge #43: json will likely warrant returning JsonObject or a FirebaseResult wrapper and affect the way we split "making the request", "checking for errors" and "consuming result".

@ed7coyne @aliafshar does that sound OK with you?

@ed7coyne
Copy link
Collaborator Author

Updated to reflect changes decided in #41


class FirebaseGetResult : public FirebaseResult {
public:
static FirebaseGetResult FromError(const String& error_message) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

does this need to be public? it seems it is only being used by the client impl.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could make them private and make them friend classes. This way allows clients to create tests easily though. I don't feel strongly either way.

// True if no error.
operator bool() const;

bool isError() const;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should keep the separate FirebaseError type, with a message() method, etc, and have API method specifics result types compose the generic error and the method specific result.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds good.

@proppy
Copy link
Collaborator

proppy commented Jan 28, 2016

Just some nits, I'd be happy to send a PR addressing them.

return url;
}

class FirebaseCall {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we should rename that into HTTPRequest since there is not much specific to firebase in this helper (basically just the port and the fingerprint).

firebase: refactor the refactoring
@proppy
Copy link
Collaborator

proppy commented Jan 28, 2016

Let's merge this once we fix the streaming sample.

FirebaseCall::FirebaseCall(const String& host, const String& auth,
const char* method, const String& path,
const String& data, HTTPClient* http) {
if (!http) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should probably reuse the client for now (even for stream) and do that in a separate PR (that might be the cause of the crash we see with the stream sample)

proppy added a commit that referenced this pull request Jan 29, 2016
Refactored Firebase library
@proppy proppy merged commit 96f7d8e into FirebaseExtended:master Jan 29, 2016
@proppy proppy mentioned this pull request Feb 1, 2016
@ed7coyne ed7coyne deleted the refactor branch April 8, 2016 18:18
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

Successfully merging this pull request may close these issues.

2 participants