> On Sep 10, 2017, at 13:09, Elvis Stansvik <[email protected]> wrote:
> 
> Right, the two-phase plugin initialization and object pool is quite
> well described in the docs:
> 
>    https://doc-snapshots.qt.io/qtcreator-extending/plugin-lifecycle.html
> 
> I think my question was a little vague, sorry about that.
> 
> Consider an example: Some functionality "foo" is to be added to the
> core plugin, and a plugin Bar written to implement that functionality.
> 
> Approach 1:
> 
> - Add an interface IFoo to the core plugin.
> - Bar implements IFoo and add an instance of its implementation to the
> pool in its initialize().
> - The core plugin get the object from the pool (in its
> extensionsInitialized()), and make use of it.
> 
> Approach 2:
> 
> - Add a singleton Foo to the core plugin.
> - Bar carries out its work using direct calls on Foo::instance().
> 
> I was just wondering if the second approach is ever used, or if the
> mechanism set up by the object pool + two-phase initialization is
> always used. If approach 2 is used, I was interested in what the
> deciding factor is between the two approaches.

Many good things have already been said, I’m late :)

Basically there is also

Approach 3:

- Add an interface IFoo to the core plugin
- Add a static method for registering instances of IFoo to core plugin 
- Bar implements IFoo and registers an instance of its implementation via the 
method above
- The core plugin gets the object(s) that have been registered through the 
static method (in its extensionsInitialized or later)

Approach 1 works when there should not be a hard runtime dependency between the 
plugins (at compile time the interface header is needed). For making this work 
without a link dependency, the interface must use Q_DECLARE_INTERFACE. I think 
the only place where it actually used this way is with CodePaster::Service, to 
avoid a runtime dependency between CodePaster and DiffEditor plugins. 
Historically we used that a lot also when there actually already was a hard 
runtime dependency between the plugins, which is problematic because of the 
performance issue that André hinted at.

In Approach 2 we actually moved towards using mostly classes with static 
methods, only using the instance() when we actually need an instance (e.g. for 
connecting to signals). It works well when a hard runtime dependency is ok and 
Bar is the driving force for the work to be done. I would say that we do this a 
lot, e.g. ActionManager, EditorManager, …, but I don’t know if you meant that 
kind of interaction ;)

Approach 3 works well if a hard runtime dependency between the plugins is ok. 
We still experiment with ways for avoiding the monotonous work of adding 
add/registerXXX, remove/unregisterXXX, methods for managing the list of 
implementations. One experiment is Utils::ObjectPool. One could add a public 
static instance of that to the core plugin in your example, and then call 
Core::foos.addObject(myIFooImpl) from Bar plugin.

I’d also prefer having fewer hard runtime dependencies, but it is a struggle… 
Qt helps a bit, but it is still not nice.
There is the Q_DECLARE_INTERFACE/Q_INTERFACES combo + object pool, there is 
invokeMethod + object pool, and the other thing that we also use is custom 
QObject properties (e.g. CodePaster looks for a custom property “plainText” in 
the current IEditor, as a fallback for finding pasteable text).

Br, Eike

_______________________________________________
Qt-creator mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/qt-creator

Reply via email to