-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Plugins and middleware approach #213
Comments
I like the idea. This is a very powerful technique, and (partly thanks to JavaScript) would allow contributors to make almost any kind of modulation, without having to alter the core. |
This is a very exciting idea for many reasons I won't detail because reading is boring! I do have a question. Should there be some kind of feedback/awareness of Matter.js of who changes what? To follow your examples, something that would say:
(I know this could be done using various strategies, I am asking if it should be) |
@Aralun yeah there should be a way of tracking changes made by plugins, particularly for debugging or for making special cases. I've started an implementation, it's looking good. I'm currently trying to decide whether I should go for a flat or recursive plugin dependency structure. At first most plugins will likely have no other plugin dependencies, but I like to think forward. It would be cool to build small plugins that build on each other. A flat dependency structure would mean that all plugins must be installed on the |
If someone builds a plugin to, say, detect collisions of a specific body or some kind of render engine or multi-client synchronizations or whatever, people will want to build upon them (use-case: a video game...) But isn't this already possible with npm packages and maybe some ES6 magic? Do you actually need to do anything in that matter, or just provide some guidelines as to how to make a plugin pluginable? |
I see what you mean, let me clarify for everyone how I'm defining plugins vs just modules as the terms overlap: Modules alone are intentionally generic, they don't normally extend existing modules directly. They tend to create new functionality but expect the user to implement it into their application directly (e.g. must use new constructors, add event hooks or update things manually on every tick). They may not be compatible with each other and there are limitations on what can be achieved because implementations are often hidden. Plugins are also modules but they are much more specialised for a particular application. They are designed to fit in to (or modify) an existing pipeline, in a way that remains highly compatible and composable with other plugins (both forwards and backwards). They should require very little work to use. So to implement plugins requires some sort of special work from the host framework to accommodate closer integration and flexibility than you could get with modules alone. I guess a good example of what I'm trying to describe would be the concept of middleware in web frameworks, for example express middleware. Does that make sense? The closest thing the OOP world has to plugins would maybe be mixins (or multiple inheritence) and dependency injection. But these concepts alone aren't really for creating chains of actions like we want. You'd have to combine them with events unless your APIs are already based on streaming. Promises are a neat idea here but they are designed for asynchronous operations. I did a quick look for examples of mixins in JS and came across an article titled Mixins Are Dead. Long Live Composition. It advocates an approach related to what I'm considering:
As for any ES6 magic with regards to composition, there are Proxies which would be a possible way to patch things but they are way more heavyweight than needed. |
It turns out that the Redux project provides a great article on how their middleware is implemented. It's similar to what I've been playing with. They also take it a step further than monkey patching but it ends up being less easy to understand and requires the patched function to implement the pipeline (I think). The approach I'm working on allows anything to be patched. They also have a requirement for async, which matter.js generally doesn't (but it would be nice). |
@antirez just posted his ideas about a module system for redis. In particular he mentions about maintaining back compatibility while at the same time allowing access to core internals. This seems like an ideal scenario, but I'm not sure how it can be pulled off easily for most libraries. He suggests that plugins specify a target version and that a compatibility layer handles changes. This seems pretty reasonable, although may prove tricky in some cases depending on the nature of the changes. |
Just an update on this, I'm very close to having finalised the plugins implementation and it will be published in a branch soon! |
The plugins branch is now pushed! Check it out! Take a look at the code for Matter.Plugin to see the implementation. There are also two new wiki pages on Using plugins and Creating plugins that go in to detail on the approach and the design of the plugin system. Here are three simple plugins you can try: You can see them in action by running the attractors example. I'd appreciate it if you guys got back to me with your thoughts! |
Any idea when this will be merged into the stable version? I am currently unable to build the release myself. Really interested! Great job 👍 |
This has now been merged into master and I've updated the edge build which now includes |
The plugin system is now available in release A plugin boilerplate will be released soon to make it easier to get started! |
It's been a pretty huge task to get this done how I wanted, but now these plugins are now fully packaged! Also check out the matter-plugin-boilerplate. I'm going to close this thread for now, any issues with plugins should be opened in a new issue (on the appropriate repo). If anyone still would generally like to discuss the approach some more, feel free to post here. Thank you everyone for your input! |
I'm investigating patterns for a plugin / extension approach for matter.js. Ultimately I'd like to maintain a collection of small module packages named
matter-*
that follow a common pattern (e.g. like the grunt / gulp ecosystem) rather than a monolithic library.This should hopefully:
Some goals for a plugin approach are:
To start we can say that plugins should be:
One of the more difficult concerns for plugins is the need to extend existing methods like
Engine.update
orBody.create
with new features. To do this plugins will need to hook these module methods so they can apply their own operations at the right moment. We could use events for this, but this requires definitions of lots of new events and there is little control over order of execution.My proposal is that plugins can patch any module method through function composition.
It could work like this:
MyPlugin.js
App.js
I realise that monkey-patching like this might make some people wince. But it's extremely powerful.
It's also optional! As it's entirely possible to use plugins defined like this without using
Matter.use
(obviously takes more work on the user's part). Documentation of plugins might be a little tricky...Candidates for plugins so far:
If anybody has any comments, ideas or examples of other good approaches I'd be interested to hear.
Edit: Looks like Vue.js is using a very similar approach.
The text was updated successfully, but these errors were encountered: