diff --git a/src/main/scala/org/rosi_project/model_sync/generator/CLIGenerator.scala b/src/main/scala/org/rosi_project/model_sync/generator/CLIGenerator.scala
new file mode 100644
index 0000000000000000000000000000000000000000..9f6af4d784e94a44459d35eb17e5c33159c54a02
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/CLIGenerator.scala
@@ -0,0 +1,50 @@
+package org.rosi_project.model_sync.generator
+
+import java.{io => jio}
+
+import scopt.OptionParser
+
+/** Main entry into the application. It is intended to run as a console application and should be
+  * called like the following: `generator [-o DIR] [-c] ECORE` with the following options:
+  *
+  *  - `-o | --outdir DIR` will write the generated `model.jar` to the directory `DIR`
+  *  - `-c | --cleanup` will remove the generated `.scala` files and only keep the `.class` in the
+  *   generated `.jar` file
+  *  - `ECORE` should specify the ecore (XML) files which contains the model to create the scala
+  *   files for
+  *
+  * @author Rico Bergmann
+  */
+object CLIGenerator extends App {
+
+  val parser = new OptionParser[GeneratorConfig](programName="modelgen") {
+    head("modelgen", "0.1")
+
+    arg[jio.File]("ecore").required().action( (ef, conf) =>
+      conf.copy(source = ef.getAbsolutePath)
+    ).text("The ecore (XML) file of the model")
+
+    opt[jio.File]('o', "outdir").optional().action( (dir, conf) =>
+      conf.copy(outDir =  dir)
+    ).text("The directory to place the generated model in (current dir by default)")
+
+    opt[jio.File]('w', "workdir").optional().action( (dir, conf) =>
+      conf.copy(workDir = dir)
+    ).text("The directory to place the generated .scala files in (temp dir by default)")
+
+    opt[jio.File]('m', "model").optional().action( (mj, conf) =>
+      conf.copy(modelFile = mj.getAbsolutePath)
+    ).text("The description of the model's components (mapped to the name of the ecore with .sync.json extension by default)")
+
+    opt[Unit]('c', "cleanup").optional().action( (_, conf) =>
+      conf.copy(cleanUp = true)
+    ).text("Remove the generated .scala files and only keep the compiled .class files")
+  }
+
+  parser.parse(args, GeneratorConfig()) match {
+    case Some(config) =>
+      new Generator(config).run()
+    case None =>
+  }
+
+}
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/EcoreLoader.scala b/src/main/scala/org/rosi_project/model_sync/generator/EcoreLoader.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6bd33b84fa74494b769718936aa11b759e4c5bea
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/EcoreLoader.scala
@@ -0,0 +1,29 @@
+package org.rosi_project.model_sync.generator
+
+import org.eclipse.emf.ecore.{EObject, EPackage}
+import scroll.internal.ecore.ECoreImporter
+
+/** Simple service to load an ECORE model from a file.
+  *
+  * @author Rico Bergmann
+  */
+class EcoreLoader extends ECoreImporter {
+
+  /** Fetches an ecore model from XML.
+    *
+    * @param path where to find the model
+    * @return the model described by the XML
+    */
+  def loadEcore(path: String = "assets/ttc17.ecore"): EPackage = {
+    this.path = path
+    val res = loadModel()
+    res.getContents.toArray(new Array[EObject](0)).toList.find(_.isInstanceOf[EPackage]).map((p: EObject) => p.asInstanceOf[EPackage]).orNull
+  }
+
+}
+
+/** Exception to indicate that the model images may not be copied into the JAR.
+  *
+  * @param cause the causing exception
+  */
+class EcoreLoadException(cause: Exception) extends RuntimeException(cause)
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala b/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
index acf4fd9eec7adfc4923adca5bd88bd402ecee93b..69c91044992b22cb5d4733834f2136c4360e7409 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
@@ -2,137 +2,73 @@ package org.rosi_project.model_sync.generator
 
 import net.liftweb.json._
 import org.eclipse.emf.ecore._
-import org.eclipse.emf.ecore.resource.Resource
 import org.rosi_project.model_sync.generator.conversion.SModelGenerator
-import org.rosi_project.model_sync.generator.io.{ClassWritingException, ModelImagePreparationException, SModelFSWriter}
-import org.rosi_project.model_sync.generator.sync.{GetterSetterGeneratingVisitor, SyncEnhancingVisitor}
-import scopt.OptionParser
-import scroll.internal.ecore.ECoreImporter
-
-import scala.reflect.io.{Directory, File}
-import java.{io => jio}
-
-import org.rosi_project.model_sync.generator.acr_model.SModel
 import org.rosi_project.model_sync.generator.env.{CompilationException, JarPackaginException}
+import org.rosi_project.model_sync.generator.io.{ClassWritingException, ModelImagePreparationException, SModelFSWriter}
 
 import scala.io.Source
+import scala.reflect.io.File
 
-/** Main entry into the application. It is intended to run as a console application and should be
-  * called like the following: `generator [-o DIR] [-c] ECORE` with the following options:
+/** The `Generator` runs the whole workflow of generating a JAR of compiled Scala source files
+  * based on an ECORE file of some sync model.
   *
-  *  - `-o | --outdir DIR` will write the generated `model.jar` to the directory `DIR`
-  *  - `-c | --cleanup` will remove the generated `.scala` files and only keep the `.class` in the
-  *   generated `.jar` file
-  *  - `ECORE` should specify the ecore (XML) files which contains the model to create the scala
-  *   files for
+  * @param config the configuration that tells the generator where to locate the necessary files.
   *
   * @author Rico Bergmann
   */
-object Generator extends App {
-
-  val parser = new OptionParser[GeneratorConfig](programName="modelgen") {
-    head("modelgen", "0.1")
-
-    arg[jio.File]("ecore").required().action( (ef, conf) =>
-      conf.copy(source = ef.getAbsolutePath)
-    ).text("The ecore (XML) file of the model")
-
-    opt[jio.File]('o', "outdir").optional().action( (dir, conf) =>
-      conf.copy(outDir =  dir)
-    ).text("The directory to place the generated model in (current dir by default)")
-
-    opt[jio.File]('w', "workdir").optional().action( (dir, conf) =>
-      conf.copy(workDir = dir)
-    ).text("The directory to place the generated .scala files in (temp dir by default)")
-
-    opt[jio.File]('m', "model").optional().action( (mj, conf) =>
-      conf.copy(modelFile = mj.getAbsolutePath)
-    ).text("The description of the model's components (mapped to the name of the ecore with .sync.json extension by default)")
-
-    opt[Unit]('c', "cleanup").optional().action( (_, conf) =>
-      conf.copy(cleanUp = true)
-    ).text("Remove the generated .scala files and only keep the compiled .class files")
-  }
-
-  try {
-    parser.parse(args, GeneratorConfig()) match {
-      case Some(config) =>
+class Generator(config: GeneratorConfig) {
 
-        val modelJson = Source.fromFile(config.getModelFile).getLines.mkString
-        implicit val jsonFormats: Formats = DefaultFormats
-        val modelCfg = parse(modelJson).extract[ModelConfig]
-
-        var ecoreModel: EPackage = null
-        try {
-          ecoreModel = loadEcore(config.source)
-        }  catch {
-          case e: Exception => throw new EcoreLoadException(e)
-        }
-
-        val sModel = new SModelGenerator convert ecoreModel
-        prepareModel(sModel, modelCfg)
-        // write the model and create the JAR
-        println("... Writing model")
+  /**
+    * Starts the generation.
+    */
+  def run(): Unit = {
+    try {
+      val modelJson = Source.fromFile(config.getModelFile).getLines.mkString
+      implicit val jsonFormats: Formats = DefaultFormats
+      val modelCfg = parse(modelJson).extract[ModelConfig]
+
+      var ecoreModel: EPackage = null
+      try {
+        ecoreModel = new EcoreLoader loadEcore config.source
+      }  catch {
+        case e: Exception => throw new EcoreLoadException(e)
+      }
+
+      val sModel = new SModelGenerator convert ecoreModel
+      new SModelSyncPreparationService prepareModel(sModel, modelCfg)
+      // write the model and create the JAR
+      println("... Writing model")
+
+      if (config.hasWorkDir) {
+        sModel.accept(
+          new SModelFSWriter(
+            outputDir = File(config.outDir).toDirectory,
+            workingDir = File(config.workDir),
+            keepClassFiles = !config.cleanUp,
+            modelCfg = modelCfg,
+            currentDir = config.getModelPath))
+      } else {
+        sModel.accept(
+          new SModelFSWriter(
+            outputDir = File(config.outDir).toDirectory,
+            keepClassFiles = !config.cleanUp,
+            modelCfg = modelCfg,
+            currentDir = config.getModelPath))
+      }
 
-        if (config.hasWorkDir) {
-          sModel.accept(
-            new SModelFSWriter(
-              outputDir = File(config.outDir).toDirectory,
-              workingDir = File(config.workDir),
-              keepClassFiles = !config.cleanUp,
-              modelCfg = modelCfg,
-              currentDir = config.getModelPath))
-        } else {
-          sModel.accept(
-            new SModelFSWriter(
-              outputDir = File(config.outDir).toDirectory,
-              keepClassFiles = !config.cleanUp,
-              modelCfg = modelCfg,
-              currentDir = config.getModelPath))
-        }
-      case None =>
     }
-  }
-  catch {
-    case ele: EcoreLoadException =>
-      println(s"** ERROR ** could not load ecore model: $ele")
-    case mipe: ModelImagePreparationException =>
-      println(s"** ERROR ** could not prepare model images: $mipe")
-    case cwe: ClassWritingException =>
-      println(s"** ERROR ** could not write classes: $cwe")
-    case ce: CompilationException =>
-      println(s"** ERROR ** could not compile classes: $ce")
-    case jpe: JarPackaginException =>
-      println(s"** ERROR ** could not package JAR: $jpe")
-  }
-
-  /** Fetches an ecore model from XML.
-    *
-    * @param path where to find the model
-    * @return the model described by the XML
-    */
-  def loadEcore(path: String = "assets/ttc17.ecore"): EPackage = {
-    val importer = new ECoreImporter {
-      def lm(): Resource = loadModel()
+    catch {
+      case ele: EcoreLoadException =>
+        println(s"** ERROR ** could not load ecore model: $ele")
+      case mipe: ModelImagePreparationException =>
+        println(s"** ERROR ** could not prepare model images: $mipe")
+      case cwe: ClassWritingException =>
+        println(s"** ERROR ** could not write classes: $cwe")
+      case ce: CompilationException =>
+        println(s"** ERROR ** could not compile classes: $ce")
+      case jpe: JarPackaginException =>
+        println(s"** ERROR ** could not package JAR: $jpe")
     }
-    importer.path = path
-    val res = importer.lm()
-    res.getContents.toArray(new Array[EObject](0)).toList.find(_.isInstanceOf[EPackage]).map((p: EObject) => p.asInstanceOf[EPackage]).orNull
-  }
-
-  /** Augments a [[SModel]] with the necessary methods and statements to make it usable in a
-    * synchronization context.
-    *
-    * @param sModel the model to augment
-    */
-  def prepareModel(sModel: SModel, modelCfg: ModelConfig): Unit = {
-    val getterSetterVisitor = new GetterSetterGeneratingVisitor
-    val syncNotificationVisitor = new SyncEnhancingVisitor(modelCfg)
-
-    sModel.accept(getterSetterVisitor)
-    sModel.accept(syncNotificationVisitor)
   }
 
 }
-
-class EcoreLoadException(cause: Exception) extends RuntimeException(cause)
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/SModelSyncPreparationService.scala b/src/main/scala/org/rosi_project/model_sync/generator/SModelSyncPreparationService.scala
new file mode 100644
index 0000000000000000000000000000000000000000..130f2527eae224b7fed30dcf4295e0b1ed7fa876
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/SModelSyncPreparationService.scala
@@ -0,0 +1,26 @@
+package org.rosi_project.model_sync.generator
+
+import org.rosi_project.model_sync.generator.acr_model.SModel
+import org.rosi_project.model_sync.generator.sync.{GetterSetterGeneratingVisitor, SyncEnhancingVisitor}
+
+/** Simple service to perform all the necessary adaptions of an [[SModel]] to make applicable for
+  * synchronization.
+  *
+  * @author Rico Bergmann
+  */
+class SModelSyncPreparationService {
+
+  /** Augments a [[SModel]] with the necessary methods and statements to make it usable in a
+    * synchronization context.
+    *
+    * @param sModel the model to augment
+    */
+  def prepareModel(sModel: SModel, modelCfg: ModelConfig): Unit = {
+    val getterSetterVisitor = new GetterSetterGeneratingVisitor
+    val syncNotificationVisitor = new SyncEnhancingVisitor(modelCfg)
+
+    sModel.accept(getterSetterVisitor)
+    sModel.accept(syncNotificationVisitor)
+  }
+
+}