-
Notifications
You must be signed in to change notification settings - Fork 37
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
Conversation
packages/frint/src/App.ts
Outdated
@@ -183,6 +199,10 @@ export class App { | |||
return this.getOption('name'); | |||
} | |||
|
|||
public getMethods() { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep :)
There was a problem hiding this comment.
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 🙂
There was a problem hiding this comment.
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 Report
@@ Coverage Diff @@
## master #431 +/- ##
==========================================
+ Coverage 97.75% 97.76% +<.01%
==========================================
Files 112 112
Lines 4366 4380 +14
==========================================
+ Hits 4268 4282 +14
Misses 98 98
Continue to review full report at Codecov.
|
7c5720b
to
89c54e9
Compare
packages/frint/src/App.ts
Outdated
const method = this.options.methods[methodName]; | ||
|
||
if (typeof method === 'function') { | ||
this[methodName] = method.bind(this); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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')
}
}
})
There was a problem hiding this comment.
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 🤔
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :/
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
Great stuff, @rbardini! 💖 |
56478a8
to
63aaa6f
Compare
63aaa6f
to
21c4214
Compare
What's done
methods
(Object
) property toAppOptions
, which has its properties added to the app'sthis
object.app.getMethods
method which returns the app'smethods
object.Why
Allow access to public methods directly from the app instance, besides the
options
property.Closes #426.