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

frint: Expose class methods on the app instance level #431

Merged
merged 6 commits into from
Jul 13, 2018

Conversation

rbardini
Copy link
Member

What's done

  • Add optional methods (Object) property to AppOptions, which has its properties added to the app's this object.
  • Add app.getMethods method which returns the app's methods object.

Why

Allow access to public methods directly from the app instance, besides the options property.

Closes #426.

@@ -183,6 +199,10 @@ export class App {
return this.getOption('name');
}

public getMethods() {
Copy link
Member

Choose a reason for hiding this comment

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

is this new method necessary?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so if for some reason we change the way we save and get those methods, we don't need to change the implementation. Exposing this clear api we avoid future maintainability problems. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

I am trying to convince myself to keep this, but not yet there :D

at the moment, it is returning the original methods option that is passed to the App's constructor. those functions are not bound to the app instance, and cannot be called directly either. so don't know how they can be useful right away.

Copy link
Contributor

Choose a reason for hiding this comment

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

I got your point, i thought it was about the way we are exposing this but i agree now that maybe we don't need this method.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe it would be useful for someone who wants to retrieve a list of the public methods exposed by a given app. But yes, not having the methods bound to the app instance makes the return value less useful—and it's accessible via app.getOption('methods') anyway.

Copy link
Member

Choose a reason for hiding this comment

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

yep :)

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll remove it for now to avoid confusion. We can write a proposal later on if necessary 🙂

Copy link
Contributor

Choose a reason for hiding this comment

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

But i don't know, i think we are doing some magic here, seems like a bad smell to me, we now are binding those methods and changing the scope, so we are exposing app instance inside each function, is that the desired behavior?

What do you guys think?

const FooApp = createApp({
  name: 'Foo',
  methods: { // specify what methods this app exposes
    bar() {
      this.methods = {}; // exposing app variable
      console.log('bar')
    }
  }
})

@codecov
Copy link

codecov bot commented Jul 12, 2018

Codecov Report

Merging #431 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #431      +/-   ##
==========================================
+ Coverage   97.75%   97.76%   +<.01%     
==========================================
  Files         112      112              
  Lines        4366     4380      +14     
==========================================
+ Hits         4268     4282      +14     
  Misses         98       98
Impacted Files Coverage Δ
packages/frint/src/App.spec.ts 100% <100%> (ø) ⬆️
packages/frint/src/App.ts 99.37% <100%> (+0.02%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update abb7964...21c4214. Read the comment docs.

const method = this.options.methods[methodName];

if (typeof method === 'function') {
this[methodName] = method.bind(this);
Copy link
Member

Choose a reason for hiding this comment

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

it will be useful if we check if there is already an existing method with the same name first.

if it exists, we throw an Error.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, will do 🙂

throw new Error(`Cannot overwrite app's \`${methodName}\` property or method with options method.`);
}

this[methodName] = method.bind(this);
Copy link
Contributor

@noisae noisae Jul 12, 2018

Choose a reason for hiding this comment

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

I don't know, i think we are doing some magic here, seems like a bad smell to me, we now are binding those methods and changing the scope, so we are exposing app instance inside each function, is that the desired behaviour?

What do you guys think?

const FooApp = createApp({
  name: 'Foo',
  methods: { // specify what methods this app exposes
    bar() {
      this.methods = {}; // exposing app variable
      console.log('bar')
    }
  }
})

Copy link
Member Author

Choose a reason for hiding this comment

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

That's an interesting point, and I can see how this may give a lot of freedom to break things. On the other hand, if the framework doesn't automatically bind the methods, the developer could still do and have the same privileges, so I'm not sure if this is a big problem 🤔

Copy link
Contributor

@noisae noisae Jul 12, 2018

Choose a reason for hiding this comment

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

But there is another problem here too, if we need to create new methods on this class, and someone is using that name, when we update frintjs, this application is going to break too. We are also breaking the Open Close principle here i think.

Copy link
Member

Choose a reason for hiding this comment

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

regarding open/close:

  • we are open to others extending the API with further methods.
  • but if we throw errors whenever there is a conflicting method name, we are closed.

Copy link
Contributor

Choose a reason for hiding this comment

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

We are really open to modification on this case.
But the thing is, imagine that i create a method called getMethods on my application, and then we do the same on App. Now when i update my frint package my application is going to break.

I think this is not a good thing :/

Copy link
Member Author

Choose a reason for hiding this comment

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

One possible drawback I foresee is that, once this is merged, any new properties or methods added to the App class would require a major release, since they can potentially clash with injected methods. Should we worry about this, or is the App API stable enough for this to not be an issue?

Copy link
Member

Choose a reason for hiding this comment

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

we haven't added any new methods for months, if not years to the App class.

@fahad19
Copy link
Member

fahad19 commented Jul 12, 2018

Great stuff, @rbardini! 💖

@rbardini rbardini merged commit 0a89cc1 into master Jul 13, 2018
@rbardini rbardini deleted the expose-class-methods branch July 13, 2018 09:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants