mirror of
https://github.com/nasa/openmct.git
synced 2025-05-17 07:53:15 +00:00
Update description of imperative plugins
This commit is contained in:
parent
4579b4fabc
commit
c99b6df9fc
@ -10,87 +10,155 @@ Developers will want to use bundles/plugins to (in rough order
|
|||||||
of occurrence):
|
of occurrence):
|
||||||
|
|
||||||
1. Add new extension instances.
|
1. Add new extension instances.
|
||||||
2. Add new service implementations.
|
2. Use existing services
|
||||||
3. Decorate service implementations.
|
3. Add new service implementations.
|
||||||
4. Add new types of services.
|
4. Decorate service implementations.
|
||||||
5. Add new extension categories.
|
5. Decorate extension instances.
|
||||||
|
6. Add new types of services.
|
||||||
|
7. Add new extension categories.
|
||||||
|
|
||||||
Notably, bullets 4 and 5 above are currently handled implicitly,
|
Notably, bullets 4 and 5 above are currently handled implicitly,
|
||||||
which has been cited as a source of confusion.
|
which has been cited as a source of confusion.
|
||||||
|
|
||||||
## Interfaces
|
## Interfaces
|
||||||
|
|
||||||
```javascript
|
Two base classes may be used to satisfy these use cases:
|
||||||
|
|
||||||
/**
|
* The `CompositeServiceFactory` provides composite service instances.
|
||||||
* Something that can be installed in a running instance of MCT.
|
Decorators may be added; the approach used for compositing may be
|
||||||
* @interface Installable
|
modified; and individual services may be registered to support compositing.
|
||||||
*/
|
* The `ExtensionRegistry` allows for the simpler case where what is desired
|
||||||
|
is an array of all instances of some kind of thing within the system.
|
||||||
|
|
||||||
/**
|
Note that additional developer use cases may be supported by using the
|
||||||
* Install this plugin in an instance of MCT.
|
more general-purpose `Registry`
|
||||||
* @method Installable#install
|
|
||||||
* @param mct the instance of MCT in which to install
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
```nomnoml
|
||||||
* A bundle is a set of related features that can
|
[Function.<T, V>]
|
||||||
* be installed in MCT.
|
|
||||||
* @class
|
|
||||||
* @implements {Installable}
|
|
||||||
* @param {Metadata} metadata metadata about this bundle
|
|
||||||
*/
|
|
||||||
function Bundle(metadata) {
|
|
||||||
this.metadata = metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bundle.prototype.service
|
[Factory.<T, V>
|
||||||
Bundle.prototype.install = function (mct) {};
|
|
|
||||||
|
- factoryFn : Function.<T, V>
|
||||||
|
|
|
||||||
|
+ decorate(decoratorFn : Function.<T, T>, options? : RegistrationOptions)
|
||||||
|
]-:>[Function.<T, V>]
|
||||||
|
|
||||||
/**
|
[RegistrationOptions |
|
||||||
* Data about a given entity within the system.
|
+ priority : number or string
|
||||||
* @typedef Metadata
|
|
||||||
* @property {string} name the human-readable name of the entity
|
|
||||||
* @property {string} key the machine-readable identifier for the entity
|
|
||||||
* @property {string} description a human-readable summary of the entity
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
[Dependency<T> |
|
|
||||||
get() : T
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[Registry<T> |
|
[Registry.<T, V>
|
||||||
register(
|
|
|
||||||
dependencies : Dependency[],
|
- compositorFn : Function.<V, Array.<T>>
|
||||||
factory : Function<T>
|
|
|
||||||
)
|
+ register(item : T, options? : RegistrationOptions)
|
||||||
]
|
+ composite(compositorFn : Function.<V, Array.<T>>, options? : RegistrationOptions)
|
||||||
|
]-:>[Factory.<V, Void>]
|
||||||
|
[Factory.<V, Void>]-:>[Factory.<T, V>]
|
||||||
|
|
||||||
[ExtensionRegistry<T> |
|
[ExtensionRegistry.<T>]-:>[Registry.<T, Array.<T>>]
|
||||||
]
|
[Registry.<T, Array.<T>>]-:>[Registry.<T, V>]
|
||||||
|
|
||||||
[ExtensionRegistry]
|
|
||||||
|
|
||||||
|
[CompositeServiceFactory.<T>]-:>[Registry.<T, T>]
|
||||||
|
[Registry.<T, T>]-:>[Registry.<T, V>]
|
||||||
```
|
```
|
||||||
|
|
||||||
Creating a bundle then looks like:
|
## Examples
|
||||||
|
|
||||||
```javascript
|
### 1. Add new extension instances.
|
||||||
define([
|
|
||||||
'mct',
|
```js
|
||||||
'./SomeExtension',
|
// Instance-style registration
|
||||||
'./SomeService'
|
mct.types.register(new mct.Type({
|
||||||
], function (mct, SomeExtension, SomeService) {
|
key: "timeline",
|
||||||
var plugin = new mct.Bundle({
|
name: "Timeline",
|
||||||
key: 'myBundle',
|
description: "A container for activities ordered in time."
|
||||||
name: "My bundle",
|
|
||||||
description: "A bundle that I made."
|
|
||||||
});
|
|
||||||
|
|
||||||
plugin.extension
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Factory-style registration
|
||||||
|
mct.actions.register(function (domainObject) {
|
||||||
|
return new RemoveAction(domainObject);
|
||||||
|
}, { priority: 200 });
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 2. Use existing services
|
||||||
|
|
||||||
|
```js
|
||||||
|
mct.actions.register(function (domainObject) {
|
||||||
|
var dialogService = mct.ui.dialogServiceFactory();
|
||||||
|
return new PropertiesAction(dialogService, domainObject);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Add new service implementations
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Instance-style registration
|
||||||
|
mct.persistenceServiceFactory.register(new LocalPersistenceService());
|
||||||
|
|
||||||
|
// Factory-style registration
|
||||||
|
mct.persistenceServiceFactory.register(function () {
|
||||||
|
var $http = angular.injector(['ng']).get('$http');
|
||||||
|
return new LocalPersistenceService($http);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Decorate service implementations
|
||||||
|
|
||||||
|
```js
|
||||||
|
mct.modelServiceFactory.decorate(function (modelService) {
|
||||||
|
return new CachingModelDecorator(modelService);
|
||||||
|
}, { priority: 100 });
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Decorate extension instances
|
||||||
|
|
||||||
|
```js
|
||||||
|
mct.capabilities.decorate(function (capabilities) {
|
||||||
|
return capabilities.map(decorateIfApplicable);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
This use case is not well-supported by these API changes. The most
|
||||||
|
common case for decoration is capabilities, which are under reconsideration;
|
||||||
|
should consider handling decoration of capabilities in a different way.
|
||||||
|
|
||||||
|
### 6. Add new types of services
|
||||||
|
|
||||||
|
```js
|
||||||
|
myModule.myServiceFactory = new mct.CompositeServiceFactory();
|
||||||
|
|
||||||
|
// In cases where a custom composition strategy is desired
|
||||||
|
myModule.myServiceFactory.composite(function (services) {
|
||||||
|
return new MyServiceCompositor(services);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Add new extension categories.
|
||||||
|
|
||||||
|
```js
|
||||||
|
myModule.hamburgers = new mct.ExtensionRegistry();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Evaluation
|
||||||
|
|
||||||
|
### Benefits
|
||||||
|
|
||||||
|
* Encourages separation of registration from declaration (individual
|
||||||
|
components are decoupled from the manner in which they are added
|
||||||
|
to the architecture.)
|
||||||
|
* Minimizes "magic." Dependencies are acquired, managed, and exposed
|
||||||
|
using plain-old-JavaScript without any dependency injector present
|
||||||
|
to obfuscate what is happening.
|
||||||
|
* Offers comparable expressive power to existing APIs; can still
|
||||||
|
extend the behavior of platform components in a variety of ways.
|
||||||
|
* Does not force or limit formalisms to use;
|
||||||
|
|
||||||
|
### Detriments
|
||||||
|
|
||||||
|
* Does not encourage separation of dependency acquisition from
|
||||||
|
declaration; that is, it would be quite natural using this API
|
||||||
|
to acquire references to services during the constructor call
|
||||||
|
to an extension or service. But, passing these in as constructor
|
||||||
|
arguments is preferred (to separate implementation from architecture.)
|
||||||
|
* Adds (negligible?) boilerplate relative to declarative syntax.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user