diff --git a/force_bdss/api.py b/force_bdss/api.py
index 4e3950b362f872d38fb0eb91439e4b12cd89f5e4..2f83fe343b866b990f49767dd514866e2097eca0 100644
--- a/force_bdss/api.py
+++ b/force_bdss/api.py
@@ -1,5 +1,5 @@
 from .base_extension_plugin import BaseExtensionPlugin  # noqa
-from .ids import factory_id, mco_parameter_id  # noqa
+from .ids import plugin_id  # noqa
 
 from .core.data_value import DataValue  # noqa
 from .core.workflow import Workflow  # noqa
diff --git a/force_bdss/base_extension_plugin.py b/force_bdss/base_extension_plugin.py
index f4ee680f6f51dadf8fc238a8485c56a8a2fd453d..1f1a0c1d5940bd03d115cb81e70fcb4d5c159c7c 100644
--- a/force_bdss/base_extension_plugin.py
+++ b/force_bdss/base_extension_plugin.py
@@ -28,11 +28,7 @@ class BaseExtensionPlugin(Plugin):
     in your plugin, and reimplement the methods as from example::
 
         class MyPlugin(BaseExtensionPlugin):
-            def get_producer(self):
-                return "enthought"
-
-            def get_identifier(self):
-                return "myplugin"
+            id = plugin_id("enthought", "plugin_name", 0)
 
             def get_factory_classes(self):
                 return [
@@ -86,26 +82,8 @@ class BaseExtensionPlugin(Plugin):
     _logger = Instance(logging.Logger)
 
     def __init__(self, *args, **kwargs):
-        broken = False
-        error = ""
-
-        if "id" not in kwargs:
-            try:
-                id_ = plugin_id(self.get_producer(), self.get_identifier())
-            except Exception as e:
-                self._logger.exception(e)
-                error = traceback.format_exc()
-                broken = True
-            else:
-                kwargs["id"] = id_
-
         super(BaseExtensionPlugin, self).__init__(*args, **kwargs)
 
-        if broken:
-            self.broken = True
-            self.error = error
-            return
-
         try:
             self.factory_classes = self.get_factory_classes()
             self.mco_factories[:] = [
@@ -133,25 +111,6 @@ class BaseExtensionPlugin(Plugin):
             self.notification_listener_factories[:] = []
             self.ui_hooks_factories[:] = []
 
-    def get_producer(self):
-        """Must be reimplemented to return a string with the name of the
-        company producing this plugin. Examples are "enthought", "itwm" etc.
-        """
-
-        raise NotImplementedError(
-            "get_producer was not implemented in plugin {}".format(
-                self.__class__))
-
-    def get_identifier(self):
-        """Must return a string with the name of the plugin the producer
-        is releasing. The name must be unique and is responsibility of
-        the producer to guarantee this name is not conflicting with
-        another already existing plugin
-        """
-        raise NotImplementedError(
-            "get_identifier was not implemented in plugin {}".format(
-                self.__class__))
-
     def get_factory_classes(self):
         """Must return a list of factory classes that this plugin exports.
         """
diff --git a/force_bdss/data_sources/base_data_source_factory.py b/force_bdss/data_sources/base_data_source_factory.py
index 7452c493c456a1fe00c6a0a435a065911fc88c05..698cdb5755730ad719895a3b2767c2790aa31f3b 100644
--- a/force_bdss/data_sources/base_data_source_factory.py
+++ b/force_bdss/data_sources/base_data_source_factory.py
@@ -1,10 +1,11 @@
 import logging
-from traits.api import ABCHasStrictTraits, provides, String, Instance, Type
+from traits.api import ABCHasStrictTraits, provides, Str, Instance, Type
 from envisage.plugin import Plugin
 
 from force_bdss.data_sources.base_data_source import BaseDataSource
 from force_bdss.data_sources.base_data_source_model import BaseDataSourceModel
 from force_bdss.data_sources.i_data_source_factory import IDataSourceFactory
+from force_bdss.ids import factory_id
 
 log = logging.getLogger(__name__)
 
@@ -13,15 +14,30 @@ log = logging.getLogger(__name__)
 class BaseDataSourceFactory(ABCHasStrictTraits):
     """Base class for DataSource factories. Reimplement this class to
     create your own DataSource.
+
+    You must reimplement the following methods as from example::
+
+        class MyDataSourceFactory(BaseDataSourceFactory)
+            def get_data_source_class(self):
+                return MyDataSource
+
+            def get_data_source_model(self):
+                return MyDataSourceModel
+
+            def get_name(self):
+                return "My data source"
+
+            def get_identifier(self):
+                return "my_data_source"
     """
     # NOTE: changes to this class must be ported also to the IDataSourceFactory
 
     #: Unique identifier that identifies the factory uniquely in the
     #: universe of factories. Create one with the function factory_id()
-    id = String()
+    id = Str()
 
     #: A human readable name of the factory. Spaces allowed
-    name = String()
+    name = Str()
 
     #: The data source to be instantiated. Define this to your DataSource
     data_source_class = Type(BaseDataSource)
@@ -39,6 +55,43 @@ class BaseDataSourceFactory(ABCHasStrictTraits):
         self.plugin = plugin
         super(BaseDataSourceFactory, self).__init__(*args, **kwargs)
 
+        self.data_source_class = self.get_data_source_class()
+        self.model_class = self.get_model_class()
+        self.name = self.get_name()
+        identifier = self.get_identifier()
+        self.id = factory_id(self.plugin.id, identifier)
+
+    def get_data_source_class(self):
+        """Must be reimplemented to return the DataSource class.
+        """
+        raise NotImplementedError(
+            "get_data_source_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_model_class(self):
+        """Must be reimplemented to return the DataSourceModel class.
+        """
+        raise NotImplementedError(
+            "get_model_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_name(self):
+        """Must be reimplemented to return a user-visible name of the
+        data source.
+        """
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_identifier(self):
+        """Must be reimplemented to return a unique string identifying
+        the factory. The provider is responsible to guarantee this identifier
+        to be unique across the plugin data sources.
+        """
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
     def create_data_source(self):
         """Factory method.
         Must return the factory-specific BaseDataSource instance.
diff --git a/force_bdss/ids.py b/force_bdss/ids.py
index c62d52b1de49cc0fb1eba50774f89dcebe84f9fb..f4bf5e3938745c984a0f68a2da00a60d7f5e9ad5 100644
--- a/force_bdss/ids.py
+++ b/force_bdss/ids.py
@@ -17,57 +17,69 @@ class ExtensionPointID:
     UI_HOOKS_FACTORIES = 'force.bdss.ui_hooks.factories'
 
 
-def factory_id(producer, identifier):
+def factory_id(plugin_id, identifier):
     """Creates an id for the factory.
 
     Parameters
     ----------
-    producer: str
-        the company or research institute unique identifier (e.g. "enthought")
+    plugin_id: str
+        the id of the plugin that contains this factory
     identifier: str
-        A unique identifier for the factory. The producer has authority and
+        A unique identifier for the factory. The identifier should be unique
         control over the uniqueness of this identifier.
 
     Returns
     -------
     str: an identifier to be used in the factory.
     """
-    return _string_id(producer, "factory", identifier)
+    return _string_id(plugin_id, "factory", identifier)
 
 
-def mco_parameter_id(producer, mco_identifier, parameter_identifier):
+def mco_parameter_id(mco_factory_id, parameter_identifier):
     """Creates an ID for an MCO parameter, so that it can be identified
     uniquely."""
-    return _string_id(producer,
-                      "factory",
-                      mco_identifier,
-                      "parameter",
-                      parameter_identifier)
+    return _string_id(mco_factory_id, "parameter", parameter_identifier)
 
 
-def plugin_id(producer, identifier):
+def plugin_id(producer, identifier, version):
     """Creates an ID for the plugins. These must be defined, otherwise
     the envisage system will complain (but not break)
+
+    Parameters
+    ----------
+    producer: str
+        A unique string identifying the producer (company/research institute)
+        of the plugin (e.g. "enthought", "itwm")
+    identifier: str
+        A string identifying the plugin. It must be unique within the context
+        of the producer, who is responsible to guarantee that plugin names
+        are unique
+    version: int
+        A version number for the plugin.
     """
-    return _string_id(producer, "plugin", identifier)
+    if not isinstance(version, int) or version < 0:
+        raise ValueError("version must be a non negative integer")
+
+    return _string_id("force",
+                      "bdss",
+                      producer,
+                      "plugin",
+                      identifier,
+                      "v{}".format(version))
 
 
 def _string_id(*args):
-    """Creates an id for a generic entity.
+    """Creates an id for a generic entity, by concatenating the given args
+    with dots.
 
     Parameters
     ----------
-    entity_namespace: str
-        A namespace for the entity we want to address (e.g. "factory")
-    producer: str
-        the company or research institute unique identifier (e.g. "enthought")
-    identifier: str
-        A unique identifier for the factory. The producer has authority and
-        control over the uniqueness of this identifier.
+    *args: str
+        The strings to concatenate
 
     Returns
     -------
-    str: an identifier to be used in the factory.
+    str: an identifier to be used.
     """
     def is_valid(entry):
         return (
@@ -79,4 +91,4 @@ def _string_id(*args):
         raise ValueError("One or more of the specified parameters was "
                          "invalid: {}".format(str(args)))
 
-    return ".".join(["force", "bdss"]+list(args))
+    return ".".join(list(args))
diff --git a/force_bdss/mco/base_mco_factory.py b/force_bdss/mco/base_mco_factory.py
index 281351e4bce8fec47f840226e72062148f987fff..44ebde99c8ddec5df0a7c07262e905add3dfdd26 100644
--- a/force_bdss/mco/base_mco_factory.py
+++ b/force_bdss/mco/base_mco_factory.py
@@ -1,7 +1,8 @@
 import logging
-from traits.api import ABCHasStrictTraits, String, provides, Instance, Type
+from traits.api import ABCHasStrictTraits, Str, provides, Instance, Type
 from envisage.plugin import Plugin
 
+from force_bdss.ids import factory_id
 from force_bdss.mco.base_mco import BaseMCO
 from force_bdss.mco.base_mco_communicator import BaseMCOCommunicator
 from force_bdss.mco.base_mco_model import BaseMCOModel
@@ -18,10 +19,10 @@ class BaseMCOFactory(ABCHasStrictTraits):
     # in the IMultiCriteriaOptimizerFactory interface class.
 
     #: A unique ID produced with the factory_id() routine.
-    id = String()
+    id = Str()
 
     #: A user friendly name of the factory. Spaces allowed.
-    name = String()
+    name = Str()
 
     #: The optimizer class to instantiate. Define this to your MCO class.
     optimizer_class = Type(BaseMCO)
@@ -39,6 +40,38 @@ class BaseMCOFactory(ABCHasStrictTraits):
         self.plugin = plugin
         super(BaseMCOFactory, self).__init__(*args, **kwargs)
 
+        self.name = self.get_name()
+        self.optimizer_class = self.get_optimizer_class()
+        self.model_class = self.get_model_class()
+        self.communicator_class = self.get_communicator_class()
+        identifier = self.get_identifier()
+        self.id = factory_id(self.plugin.id, identifier)
+
+    def get_optimizer_class(self):
+        raise NotImplementedError(
+            "get_optimizer_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_model_class(self):
+        raise NotImplementedError(
+            "get_model_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_communicator_class(self):
+        raise NotImplementedError(
+            "get_communicator_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_identifier(self):
+        raise NotImplementedError(
+            "get_identifier was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_name(self):
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
     def create_optimizer(self):
         """Factory method.
         Creates the optimizer with the given application
diff --git a/force_bdss/mco/parameters/base_mco_parameter_factory.py b/force_bdss/mco/parameters/base_mco_parameter_factory.py
index cd8751b456eb41d04b6748f6b3f6b8001a061e97..c6c16f9e5234990508f3284d337928f3be34f8e7 100644
--- a/force_bdss/mco/parameters/base_mco_parameter_factory.py
+++ b/force_bdss/mco/parameters/base_mco_parameter_factory.py
@@ -1,4 +1,6 @@
-from traits.api import HasStrictTraits, String, Type, Instance
+from traits.api import HasStrictTraits, Str, Type, Instance
+
+from force_bdss.ids import mco_parameter_id
 
 
 class BaseMCOParameterFactory(HasStrictTraits):
@@ -14,23 +16,49 @@ class BaseMCOParameterFactory(HasStrictTraits):
     mco_factory = Instance('force_bdss.mco.base_mco_factory.BaseMCOFactory')
 
     #: A unique string identifying the parameter
-    id = String()
+    id = Str()
 
     #: A user friendly name (for the UI)
-    name = String("Undefined parameter")
+    name = Str("Undefined parameter")
 
     #: A long description of the parameter
-    description = String("Undefined parameter")
+    description = Str("Undefined parameter")
 
     # The model class to instantiate when create_model is called.
     model_class = Type(
         "force_bdss.mco.parameters.base_mco_parameter.BaseMCOParameter"
     )
 
+    def get_identifier(self):
+        raise NotImplementedError(
+            "get_identifier was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_name(self):
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_description(self):
+        raise NotImplementedError(
+            "get_description was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_model_class(self):
+        raise NotImplementedError(
+            "get_model_class was not implemented in factory {}".format(
+                self.__class__))
+
     def __init__(self, mco_factory, *args, **kwargs):
         self.mco_factory = mco_factory
         super(BaseMCOParameterFactory, self).__init__(*args, **kwargs)
 
+        self.name = self.get_name()
+        self.description = self.get_description()
+        self.model_class = self.get_model_class()
+        identifier = self.get_identifier()
+        self.id = mco_parameter_id(self.mco_factory.id, identifier)
+
     def create_model(self, data_values=None):
         """Creates the instance of the model class and returns it.
         You should not reimplement this, as the default is generally ok.
diff --git a/force_bdss/notification_listeners/base_notification_listener_factory.py b/force_bdss/notification_listeners/base_notification_listener_factory.py
index f892d9c6bddb79e5ff1cd9a205704dec37a32d16..7e7d30b1f4e14015f30efe6c1a12b161d9abada6 100644
--- a/force_bdss/notification_listeners/base_notification_listener_factory.py
+++ b/force_bdss/notification_listeners/base_notification_listener_factory.py
@@ -1,9 +1,10 @@
 import logging
 from traits.api import (
-    ABCHasStrictTraits, Instance, String, provides, Type, Bool
+    HasStrictTraits, Instance, Str, provides, Type, Bool
 )
 from envisage.plugin import Plugin
 
+from force_bdss.ids import factory_id
 from force_bdss.notification_listeners.base_notification_listener import \
     BaseNotificationListener
 from force_bdss.notification_listeners.base_notification_listener_model \
@@ -15,16 +16,16 @@ log = logging.getLogger(__name__)
 
 
 @provides(INotificationListenerFactory)
-class BaseNotificationListenerFactory(ABCHasStrictTraits):
+class BaseNotificationListenerFactory(HasStrictTraits):
     """Base class for notification listeners.
     Notification listeners are extensions that receive event notifications
     from the MCO and perform an associated action.
     """
     #: identifier of the factory
-    id = String()
+    id = Str()
 
     #: Name of the factory. User friendly for UI
-    name = String()
+    name = Str()
 
     #: If the factor should be visible in the UI. Set to false to make it
     #: invisible. This is normally useful for notification systems that are
@@ -53,6 +54,32 @@ class BaseNotificationListenerFactory(ABCHasStrictTraits):
         self.plugin = plugin
         super(BaseNotificationListenerFactory, self).__init__(*args, **kwargs)
 
+        self.listener_class = self.get_listener_class()
+        self.model_class = self.get_model_class()
+        self.name = self.get_name()
+        identifier = self.get_identifier()
+        self.id = factory_id(self.plugin.id, identifier)
+
+    def get_listener_class(self):
+        raise NotImplementedError(
+            "get_listener_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_model_class(self):
+        raise NotImplementedError(
+            "get_model_class was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_identifier(self):
+        raise NotImplementedError(
+            "get_identifier was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_name(self):
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
     def create_listener(self):
         """
         Creates an instance of the listener.
diff --git a/force_bdss/ui_hooks/base_ui_hooks_factory.py b/force_bdss/ui_hooks/base_ui_hooks_factory.py
index adb07b991bfc4bb4dce22172b5e05db963f652a9..111a8588943da107d75c8591971967de83be8c50 100644
--- a/force_bdss/ui_hooks/base_ui_hooks_factory.py
+++ b/force_bdss/ui_hooks/base_ui_hooks_factory.py
@@ -2,6 +2,7 @@ import logging
 from traits.api import ABCHasStrictTraits, Instance, String, provides, Type
 from envisage.plugin import Plugin
 
+from force_bdss.ids import factory_id
 from force_bdss.ui_hooks.base_ui_hooks_manager import BaseUIHooksManager
 from .i_ui_hooks_factory import IUIHooksFactory
 
@@ -38,6 +39,27 @@ class BaseUIHooksFactory(ABCHasStrictTraits):
         self.plugin = plugin
         super(BaseUIHooksFactory, self).__init__(*args, **kwargs)
 
+        self.ui_hooks_manager_class = self.get_ui_hooks_manager_class()
+        self.name = self.get_name()
+        identifier = self.get_identifier()
+        self.id = factory_id(self.plugin.id, identifier)
+
+    def get_ui_hooks_manager_class(self):
+        raise NotImplementedError(
+            "get_ui_hooks_manager_class was not implemented "
+            "in factory {}".format(
+                self.__class__))
+
+    def get_name(self):
+        raise NotImplementedError(
+            "get_name was not implemented in factory {}".format(
+                self.__class__))
+
+    def get_identifier(self):
+        raise NotImplementedError(
+            "get_identifier was not implemented in factory {}".format(
+                self.__class__))
+
     def create_ui_hooks_manager(self):
         """Creates an instance of the hook manager.
         The hooks manager contains a set of methods that are applicable in