diff --git a/src/adapter/postgres.ts b/src/adapter/postgres.ts
index 3cb982a34432c97eff6eeb0bfc39b0540e69b9cb..b796d142cd79411dcb5e08c201ff9f9e9f08d7a6 100644
--- a/src/adapter/postgres.ts
+++ b/src/adapter/postgres.ts
@@ -18,9 +18,9 @@
  * along with blend.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-import { View } from "../core/view";
 import { Adapter } from "../core/adapter";
-import { AggregationType } from "../common/aggregationType";
+import { AggregationType } from "../common/types";
+import { View } from "../core/view";
 
 interface ParsedView {
     query: string;
diff --git a/src/common/aggregationType.ts b/src/common/types.ts
similarity index 100%
rename from src/common/aggregationType.ts
rename to src/common/types.ts
diff --git a/src/core/dimension.ts b/src/core/dimension.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f0b27898fb363ef38594430e61afe40f52dd182f
--- /dev/null
+++ b/src/core/dimension.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blend.
+ *
+ * blend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blend.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+export interface DimensionOptions {
+    name: string;
+}
+
+export class Dimension {
+    public readonly name: string;
+
+    constructor(options: DimensionOptions) {
+        this.name = options.name;
+    }
+}
diff --git a/src/core/engine.spec.ts b/src/core/engine.spec.ts
index 94c6456d49dcd78de71b7ccb263f076bb3abcfdc..e59087d68e28acba644f3363a99d7615e274a0ee 100644
--- a/src/core/engine.spec.ts
+++ b/src/core/engine.spec.ts
@@ -21,78 +21,88 @@
 import { expect } from "chai";
 
 import { Engine } from "./engine";
+import { Metric } from "./metric";
+import { Dimension } from "./dimension";
 import { View } from "./view";
 import { ViewOptions } from "./view";
 import { Query } from "../common/query";
-import { AggregationType } from "../common/aggregationType";
+import { AggregationType } from "../common/types";
 
 describe("engine class", () => {
-    let query: Query = {
-        metrics: [],
-        dimensions: []
-    };
+    const engine = new Engine();
 
-    let views: View[] = [];
+    const met1 = new Metric({ name: "met:1", aggregation: AggregationType.SUM });
+    const met2 = new Metric({ name: "met:2", aggregation: AggregationType.AVG });
+    const met3 = new Metric({ name: "met:3", aggregation: AggregationType.AVG });
+    const met4 = new Metric({ name: "met:4", aggregation: AggregationType.SUM });
+    const met5 = new Metric({ name: "met:5", aggregation: AggregationType.SUM });
+    const met6 = new Metric({ name: "met:6", aggregation: AggregationType.AVG });
+    const met7 = new Metric({ name: "met:7", aggregation: AggregationType.COUNT });
+    const met8 = new Metric({ name: "met:8", aggregation: AggregationType.COUNT });
+    const met9 = new Metric({ name: "met:9", aggregation: AggregationType.SUM });
+    const met10 = new Metric({ name: "met:10", aggregation: AggregationType.COUNT });
 
-    let viewBuilder: Query[] = [
-        { metrics: ["met:1", "met:2", "met:3"], dimensions: ["dim:1", "dim:2"]},
-        { metrics: ["met:1", "met:3", "met:5"], dimensions: ["dim:1", "dim:2"]},
-        { metrics: ["met:3", "met:4", "met:7"], dimensions: ["dim:4", "dim:5"]},
-        { metrics: ["met:6", "met:7"], dimensions: ["dim:3", "dim:4", "dim:5", "dim:6"]},
-        { metrics: ["met:8", "met:2", "met:3"], dimensions: ["dim:1", "dim:2", "dim:7"]},
-        { metrics: ["met:1", "met:2", "met:3"], dimensions: ["dim:1", "dim:2"]},
-        { metrics: ["met:2", "met:4"], dimensions: ["dim:1", "dim:2"]},
-        { metrics: ["met:8"], dimensions: ["dim:8", "dim:9", "dim:10"]},
-        { metrics: ["met:9"], dimensions: ["dim:8", "dim:9", "dim:10"]},
-        { metrics: ["met:10"], dimensions: ["dim:8", "dim:9", "dim:10"]}
-    ];
+    const dim1 = new Dimension({ name: "dim:0" });
+    const dim2 = new Dimension({ name: "dim:1" });
+    const dim3 = new Dimension({ name: "dim:2" });
+    const dim4 = new Dimension({ name: "dim:3" });
+    const dim5 = new Dimension({ name: "dim:4" });
+    const dim6 = new Dimension({ name: "dim:5" });
+    const dim7 = new Dimension({ name: "dim:6" });
+    const dim8 = new Dimension({ name: "dim:7" });
+    const dim9 = new Dimension({ name: "dim:8" });
+    const dim10 = new Dimension({ name: "dim:9" });
 
-    let iterable: [string, AggregationType][] = [
-        ["met:1", AggregationType.SUM],
-        ["met:2", AggregationType.AVG],
-        ["met:3", AggregationType.AVG],
-        ["met:4", AggregationType.SUM],
-        ["met:5", AggregationType.SUM],
-        ["met:6", AggregationType.AVG],
-        ["met:7", AggregationType.COUNT],
-        ["met:8", AggregationType.COUNT],
-        ["met:9", AggregationType.SUM],
-        ["met:10", AggregationType.COUNT],
-    ];
+    engine.addMetric(met1);
+    engine.addMetric(met2);
+    engine.addMetric(met3);
+    engine.addMetric(met4);
+    engine.addMetric(met5);
+    engine.addMetric(met6);
+    engine.addMetric(met7);
+    engine.addMetric(met8);
+    engine.addMetric(met9);
+    engine.addMetric(met10);
 
-    let map: Map<string, AggregationType> = new Map(iterable);
+    engine.addDimension(dim1);
+    engine.addDimension(dim2);
+    engine.addDimension(dim3);
+    engine.addDimension(dim4);
+    engine.addDimension(dim5);
+    engine.addDimension(dim6);
+    engine.addDimension(dim7);
+    engine.addDimension(dim8);
+    engine.addDimension(dim9);
+    engine.addDimension(dim10);
 
-    for (let i: number = 0; i < 10; ++ i) {
-        query.metrics.push("met:" + (i + 1));
-        query.dimensions.push("dim:" + (i + 1));
-        let options: ViewOptions = {
-            metrics: viewBuilder[i].metrics,
-            dimensions: viewBuilder[i].dimensions,
-            materialized: true,
-            aggregationMap: map,
-            childViews: []
-        };
-        views.push(new View (options));
-    }
+    let views: View[] = [
+        new View({ metrics: [met1, met2, met3], dimensions: [dim1, dim2]}),
+        new View({ metrics: [met1, met3, met5], dimensions: [dim1, dim2]}),
+        new View({ metrics: [met3, met4, met7], dimensions: [dim4, dim5]}),
+        new View({ metrics: [met6, met7], dimensions: [dim3, dim4, dim5, dim6]}),
+        new View({ metrics: [met8, met2, met3], dimensions: [dim1, dim2, dim7]}),
+        new View({ metrics: [met1, met2, met3], dimensions: [dim1, dim2]}),
+        new View({ metrics: [met2, met4], dimensions: [dim1, dim2]}),
+        new View({ metrics: [met8], dimensions: [dim8, dim9, dim10]}),
+        new View({ metrics: [met9], dimensions: [dim8, dim9, dim10]}),
+        new View({ metrics: [met10], dimensions: [dim8, dim9, dim10]})
+    ];
 
     views.push(new View({
-        metrics: ["met:1", "met:2", "met:3", "met:4", "met:5"],
-        dimensions: ["dim:1", "dim:2"],
+        metrics: [met1, met2, met3, met4, met5],
+        dimensions: [dim1, dim2],
         materialized: false,
-        aggregationMap: map,
         childViews: [views[0], views[6]]
     }));
 
     views.push(new View({
-        metrics: ["met:8", "met:9", "met:10"],
-        dimensions: ["dim:8", "dim:9", "dim:10"],
+        metrics: [met8, met9, met10],
+        dimensions: [dim8, dim9, dim10],
         materialized: false,
-        aggregationMap: map,
         childViews: [views[7], views[8], views[9]]
     }));
 
     it("should be create a fill that cover the query and has 4 children", () => {
-        let engine: Engine = new Engine (views);
         let optimalView = engine.query(query);
         expect(optimalView).to.be.an("object");
         expect(optimalView).to.have.property("metrics");
@@ -116,7 +126,6 @@ describe("engine class", () => {
         }
     });
     it("should throw an exception, query with non-existent metric", () => {
-        let engine: Engine = new Engine (views);
         let error: boolean = false;
         try {
             engine.query({metrics: ["met:11"], dimensions: ["dim:1"]});
@@ -130,7 +139,6 @@ describe("engine class", () => {
     });
 
     it("should throw an exception, query with non-existent dimension", () => {
-        let engine: Engine = new Engine (views);
         let error: boolean = false;
         try {
             engine.query({metrics: ["met:1"], dimensions: ["dim:11"]});
diff --git a/src/core/engine.ts b/src/core/engine.ts
index a4e4a5fd3084e094e06397a30c4595448eadb121..a7b3bf06f1dc1072e5fd90967af12b49665359aa 100644
--- a/src/core/engine.ts
+++ b/src/core/engine.ts
@@ -18,28 +18,74 @@
  * along with blend.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-import { Query } from "../common/query";
+import { Dimension } from "./dimension";
+import { Metric } from "./metric";
 import { View } from "./view";
-import { AggregationType } from "../common/aggregationType";
+import { AggregationType } from "../common/types";
+import { Query } from "../common/query";
 
 export class Engine {
-    private views: View[];
+    private views: View[] = [];
+    private metrics: Metric[] = [];
+    private dimensions: Dimension[] = [];
+
+    constructor () { }
+
+    public getViews() {
+        return this.views;
+    }
+
+    public addView(view: View) {
+        this.views.push(view);
+        return view;
+    }
+
+    public addMetric(metric: Metric) {
+        this.metrics.push(metric);
+        return metric;
+    }
+
+    public getMetricByName(name: string) {
+        let result = this.metrics.find(metric => metric.name === name);
+
+        if (!result) {
+            throw new Error('The metric named ' + name + ' was not found');
+        }
 
-    constructor (v: View[]) {
-        this.views = v;
+        return result;
+    }
+
+    public addDimension(dimension: Dimension) {
+        this.dimensions.push(dimension);
+        return dimension;
+    }
+
+    public getDimensionByName(name: string) {
+        let result = this.dimensions.find(dimension => dimension.name === name);
+
+        if (!result) {
+            throw new Error('The dimension named ' + name + ' was not found');
+        }
+
+        return result;
+    }
+
+    public query (q: Query) {
+        return this.selectOptimalView(q);
     }
 
-    public query (q: Query) { return this.selectOptimalView(q); }
-    public insert (data: any) { /*to Implement*/ }
     private selectOptimalView (q: Query) {
         let objective = q.metrics.concat(q.dimensions);
         let optimalViews: View[] = [];
-        let activeViews = this.views;
+        let activeViews = this.getViews();
 
-        // Run this block until all metrics and dimmensions are covered
+        // run this block until all metrics and dimmensions are covered
         while (objective.length  > 0) {
             let bestView: View;
             let shortestDistance = objective.length + 1;
+
+            // remove views from the activeViews if they don't intersect
+            // with the objective
             activeViews = activeViews.filter((view: View) => {
                 let cover = view.metrics.concat(view.dimensions);
                 let intersection = cover.filter((item: string) => {
@@ -62,23 +108,28 @@ export class Engine {
             });
 
             if (shortestDistance  === objective.length + 1) {
-                throw new Error ("Engine views cannot cover the query");
+                throw new Error("Engine views cannot cover the query");
             }
 
             optimalViews.push(bestView);
 
-            //remove metrics and dimensions corevered by the bestView
+            // remove metrics and dimensions corvered by the bestView from the
+            // objective (i.e. the object is already met for those metrics/dimensions)
             objective = objective.filter((item: string) => {
                 let cover = bestView.dimensions.concat(bestView.metrics);
                 return cover.indexOf(item) === -1;
             });
         }
 
+        
         if (optimalViews.length === 1) {
+            // if there is a single view that covers the query, we just return it
             return optimalViews.pop();
         }
-
         else {
+            // if more than one view is necessary to cover the query,
+            // we need to compose them into a new singular virtual view
+
             let map = new Map();
             optimalViews.forEach((view: View) => {
                 view.aggregationMap.forEach((value: AggregationType, key: string) => {
@@ -95,7 +146,7 @@ export class Engine {
             };
 
             let view = new View(options);
-            this.views.push(view);
+            this.addView(view);
             return view;
         }
     }
diff --git a/src/core/metric.ts b/src/core/metric.ts
new file mode 100644
index 0000000000000000000000000000000000000000..adbabeaf3f577ce51c6824709ed7279877b351d6
--- /dev/null
+++ b/src/core/metric.ts
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blend.
+ *
+ * blend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * blend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with blend.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { AggregationType } from "../common/types";
+
+export interface MetricOptions {
+    name: string;
+    aggregation: AggregationType;
+}
+
+export class Metric {
+    public readonly name: string;
+    public readonly aggregation: AggregationType;
+
+    constructor(options: MetricOptions) {
+        this.name = options.name;
+        this.aggregation = options.aggregation;
+    }
+}
diff --git a/src/core/view.ts b/src/core/view.ts
index 34716d22cdeb719e509f1d8585d4a1e11004f492..b1f5fb60e511ac548cd3ec852bad6b76e2f0b3cc 100644
--- a/src/core/view.ts
+++ b/src/core/view.ts
@@ -18,40 +18,33 @@
  * along with blend.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+import { Dimension } from "./dimension";
+import { Metric } from "./metric";
 import { Hash } from "../util/hash";
-import { AggregationType } from "../common/aggregationType";
 
 export interface ViewOptions {
-    metrics: string[];
-    dimensions: string[];
-    materialized: boolean;
-    aggregationMap: Map <string, AggregationType>;
-    childViews: View[];
+    metrics: Metric[];
+    dimensions: Dimension[];
+    materialized?: boolean;
+    childViews?: View[];
 }
 
 export class View {
     public readonly id: string;
-    public readonly metrics: string[];
-    public readonly dimensions: string[];
+    public readonly metrics: Metric[];
+    public readonly dimensions: Dimension[];
     public readonly materialized: boolean;
-    public readonly aggregationMap: Map<string, AggregationType>;
-
     public childViews: View[];
 
     constructor (options: ViewOptions) {
         this.metrics = options.metrics;
         this.dimensions = options.dimensions;
-        this.materialized = options.materialized;
-        this.childViews = options.childViews;
-        this.aggregationMap = options.aggregationMap;
-        this.id = Hash.sha1(options.metrics.sort(), options.dimensions.sort());
-    }
-
-    public getAggregatationType(metric: string): AggregationType {
-        if (this.aggregationMap.has(metric)) {
-            return AggregationType.NONE;
-        }
+        this.materialized = options.materialized || true;
+        this.childViews = options.childViews || [];
 
-        return this.aggregationMap.get(metric);
+        // calculate the id of the view based on it's metrics and dimensions
+        let metricsNames = this.metrics.map(metric => metric.name);
+        let dimensionsNames = this.dimensions.map(dimension => dimension.name);
+        this.id = Hash.sha1(metricsNames.concat(dimensionsNames));
     }
 }
diff --git a/src/util/hash.ts b/src/util/hash.ts
index bfe777670811b3f1690b9a2698baa6112d19d8a6..0ca3c606ad88c7d5531fcf525cc80a3129eb31c8 100644
--- a/src/util/hash.ts
+++ b/src/util/hash.ts
@@ -39,7 +39,7 @@ export class Hash {
                 }
             })
             .sort()
-            .map((objStr) => {
+            .forEach((objStr) => {
                 hash.update(objStr);
             });