You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue describes the awkwardness one encounters when two instances of the same type need to be shared across plugins using the service mechanism. (This awkwardness also applies if one must advertise multiple services of the same type even if those services are to be used by the same plugin that advertises them.)
This issue serves to present the problem. This may motivate an alternative design for one plugin to share resources with another plugin.
Suppose now we'd like to have two Lorenz instances in the application, then one could define two ServiceOffer with different factories, with the same protocol, e.g.:
The two service instances may have slightly different behaviours, and those differences are important where they are used.
Ambiguity when obtaining a service from get_service
With that, existing usage of application.get_service(Lorenz) would obtain the instance from some_factory_1 assuming the fact that Python dictionary are ordered and assuming the service offers are contributed in the order of [lorenz_service_offer_1, lorenz_service_offer_2]. If the two offers are contributed by separate plugins, then the order depends on the ordering of the plugins too. #407 is related here
Existing ways to obtain the second service is fragile or not possible
To obtain the second one, one will need to use get_services with some additional filtering, e.g.:
The usage of get_services + query may not be possible if the filtering logic depends on information that cannot be retrospectively obtained, i.e. one simply can't provide a query.
The usage of eval is also fragile. It is too easy for the query to be broken for trivial reasons (e.g. attribute name is changed) and the filter finds no match.
It is hard to maintain these queries: It requires consumers of a service to know a lot about the internal details of the service.
Workaround is also awkward
Suppose we cannot compose a query for get_services or we want to avoid the fragility mentioned above, then one way to workaround this would be to create a subclass of the service, e.g.:
class Lozent1(acme.lorenz.lorenz.Lorenz):
pass
class Lozent2(acme.lorenz.lorenz.Lorenz):
pass
This issue describes the awkwardness one encounters when two instances of the same type need to be shared across plugins using the service mechanism. (This awkwardness also applies if one must advertise multiple services of the same type even if those services are to be used by the same plugin that advertises them.)
This issue serves to present the problem. This may motivate an alternative design for one plugin to share resources with another plugin.
Starting from this example:
envisage/examples/legacy/plugins/workbench/Lorenz/acme/lorenz/lorenz_plugin.py
Lines 29 to 40 in 28f7958
Suppose now we'd like to have two
Lorenz
instances in the application, then one could define twoServiceOffer
with different factories, with the same protocol, e.g.:The two service instances may have slightly different behaviours, and those differences are important where they are used.
Ambiguity when obtaining a service from
get_service
With that, existing usage of
application.get_service(Lorenz)
would obtain the instance fromsome_factory_1
assuming the fact that Python dictionary are ordered and assuming the service offers are contributed in the order of[lorenz_service_offer_1, lorenz_service_offer_2]
. If the two offers are contributed by separate plugins, then the order depends on the ordering of the plugins too.#407 is related here
Existing ways to obtain the second service is fragile or not possible
To obtain the second one, one will need to use
get_services
with some additional filtering, e.g.:envisage/envisage/tests/test_service_registry.py
Line 291 in d62af08
That logic depends on
eval
, here:envisage/envisage/service_registry.py
Line 215 in d62af08
get_services
+query
may not be possible if the filtering logic depends on information that cannot be retrospectively obtained, i.e. one simply can't provide a query.eval
is also fragile. It is too easy for the query to be broken for trivial reasons (e.g. attribute name is changed) and the filter finds no match.Workaround is also awkward
Suppose we cannot compose a
query
forget_services
or we want to avoid the fragility mentioned above, then one way to workaround this would be to create a subclass of the service, e.g.:And then advertise the services:
Part of this is imposed by the fact that protocol must be either a type or a string that can be used for importing a type.
The text was updated successfully, but these errors were encountered: