diff --git a/.coveragerc b/.coveragerc
index baa10de454893675aeedc6275e2c6725b0b84966..69c1dcd3f1ca5068733a54fdb231bab80170169d 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -23,3 +23,6 @@ exclude_lines =
 
     # Don't complain about import statements
     import
+
+    # Don't complain about abstract class declarations and placeholders
+    pass
diff --git a/src/datastore.py b/src/datastore.py
index 4c71e67facd48abe4f5e9097615a362944376498..b106c767dab5ee937c4df288995c60ae16d35b1d 100644
--- a/src/datastore.py
+++ b/src/datastore.py
@@ -2,17 +2,21 @@ __author__ = 'Lukas Leufen'
 __date__ = '2019-11-22'
 
 
-from typing import Any
+from typing import Any, List
 from abc import ABC
 
 
 class NameNotFoundInDataStore(Exception):
-
+    """
+    Exception that get raised if given name is not found in the entire data store.
+    """
     pass
 
 
 class NameNotFoundInScope(Exception):
-
+    """
+    Exception that get raised if given name is not found in the provided scope, but can be found in other scopes.
+    """
     pass
 
 
@@ -28,21 +32,72 @@ class AbstractDataStore(ABC):
         self._store = {}
 
     def put(self, name: str, obj: Any, scope: str) -> None:
+        """
+        Abstract method to add an object to the data store
+        :param name: Name of object to store
+        :param obj: The object itself to be stored
+        :param scope: the scope / context of the object, under that the object is valid
+        """
         pass
 
     def get(self, name: str, scope: str) -> None:
+        """
+        Abstract method to get an object from the data store
+        :param name: Name to look for
+        :param scope: scope to search the name for
+        :return: the stored object
+        """
+        pass
+
+    def search_name(self, name: str) -> None:
+        """
+        Abstract method to search for all occurrences of given `name` in the entire data store.
+        :param name: Name to look for
+        :return: search result
+        """
         pass
 
 
 class DataStoreByVariable(AbstractDataStore):
 
-    def put(self, name, obj, scope):
+    """
+    Data store for all settings for the experiment workflow to save experiment parameters for the proceeding modules
+    and predefine parameters loaded during the experiment setup phase. The data store is hierarchically structured, so
+    that global settings can be overwritten by local adjustments.
+
+    This implementation stores data as
+    <variable1>
+        <scope1>: value
+        <scope2>: value
+    <variable2>
+        <scope1>: value
+        <scope3>: value
+    """
+
+    def put(self, name: str, obj: Any, scope: str) -> None:
+        """
+        Store an object `obj` with given `name` under `scope`. In the current implementation, existing entries are
+        overwritten.
+        :param name: Name of object to store
+        :param obj: The object itself to be stored
+        :param scope: the scope / context of the object, under that the object is valid
+        """
         # open new variable related store with `name` as key if not existing
         if name not in self._store.keys():
             self._store[name] = {}
         self._store[name][scope] = obj
 
-    def get(self, name, scope, depth=None):
+    def get(self, name: str, scope: str, depth: int = None) -> Any:
+        """
+        Retrieve an object with `name` from `scope`. If no object can be found in the exact scope, take an iterative
+        look on the levels above. Raises a NameNotFoundInDataStore error, if no object with given name can be found in
+        the entire data store. Raises a NameNotFoundInScope error, if the object is in the data store but not in the
+        given scope and its levels above (could be either included in another scope or a more detailed sub-scope).
+        :param name: Name to look for
+        :param scope: scope to search the name for
+        :param depth: counter to check, if all roots of the scope have been visited to trigger an error.
+        :return: the stored object
+        """
         if depth is None:
             depth = scope.count(".")
         if depth >= 0:
@@ -57,18 +112,54 @@ class DataStoreByVariable(AbstractDataStore):
             else:
                 raise NameNotFoundInDataStore(f"Couldn't find {name} in data store")
 
-    def search_name(self, name):
+    def search_name(self, name: str) -> List[str]:
+        """
+        Search for all occurrences of given `name` in the entire data store.
+        :param name: Name to look for
+        :return: list with all scopes and sub-scopes containing an object stored as `name`
+        """
         return sorted(self._store[name])
 
 
 class DataStoreByScope(AbstractDataStore):
 
-    def put(self, name, obj, scope):
+    """
+    Data store for all settings for the experiment workflow to save experiment parameters for the proceeding modules
+    and predefine parameters loaded during the experiment setup phase. The data store is hierarchically structured, so
+    that global settings can be overwritten by local adjustments.
+
+    This implementation stores data as
+    <scope1>
+        <variable1>: value
+        <variable2>: value
+    <scope2>
+        <variable1>: value
+        <variable3>: value
+    """
+
+    def put(self, name: str, obj: Any, scope: str) -> None:
+        """
+        Store an object `obj` with given `name` under `scope`. In the current implementation, existing entries are
+        overwritten.
+        :param name: Name of object to store
+        :param obj: The object itself to be stored
+        :param scope: the scope / context of the object, under that the object is valid
+        """
         if scope not in self._store.keys():
             self._store[scope] = {}
         self._store[scope][name] = obj
 
-    def get(self, name, scope, depth=None):
+    def get(self, name: str, scope: str, depth: int = None) -> Any:
+        """
+        Retrieve an object with `name` from `scope`. If no object can be found in the exact scope, take an iterative
+        look on the levels above. Raises a NameNotFoundInDataStore error, if no object with given name can be found in
+        the entire data store. Raises a NameNotFoundInScope error, if the object is in the data store but not in the
+        given scope and its levels above (could be either included in another scope or a more detailed sub-scope).
+        :param name: Name to look for
+        :param scope: scope to search the name for
+        :param depth: counter to check, if all roots of the scope have been visited to trigger an error.
+        :return: the stored object
+        """
         if depth is None:
             depth = scope.count(".")
         if depth >= 0:
@@ -84,9 +175,16 @@ class DataStoreByScope(AbstractDataStore):
                 raise NameNotFoundInScope(f"Couldn't find {name} in scope {scope}. {name} is only defined in "
                                           f"{occurrences}")
 
-    def search_name(self, name):
+    def search_name(self, name: str) -> List[str]:
+        """
+        Search for all occurrences of given `name` in the entire data store.
+        :param name: Name to look for
+        :return: list with all scopes and sub-scopes containing an object stored as `name`
+        """
         keys = []
         for (key, val) in self._store.items():
             if name in val.keys():
                 keys.append(key)
         return sorted(keys)
+
+