diff --git a/lib/highlight-selected.js b/lib/highlight-selected.js
index ecb49df..0585f50 100644
--- a/lib/highlight-selected.js
+++ b/lib/highlight-selected.js
@@ -1,5 +1,7 @@
 const { CompositeDisposable } = require('atom');
 const HighlightedAreaView = require('./highlighted-area-view');
+const ScrollMarkersService = require('./scroll-markers/scroll-markers-service');
+const StatusBarService = require('./status-bar/status-bar-service');
 
 module.exports = {
   config: {
@@ -79,14 +81,21 @@ module.exports = {
   },
 
   deactivate() {
-    if (this.areaView != null) {
+    if (this.areaView) {
       this.areaView.destroy();
     }
     this.areaView = null;
-    if (this.subscriptions != null) {
+    if (this.subscriptions) {
       this.subscriptions.dispose();
     }
     this.subscriptions = null;
+    if (this.scrollMarkersService) {
+      this.scrollMarkersService.destroy();
+    }
+    this.scrollMarkersService = null;
+    if (this.statusBarService) {
+      this.statusBarService = null;
+    }
   },
 
   provideHighlightSelectedV1Deprecated() {
@@ -98,7 +107,7 @@ module.exports = {
   },
 
   consumeStatusBar(statusBar) {
-    return this.areaView.setStatusBar(statusBar);
+    this.statusBarService = new StatusBarService(statusBar, this.areaView);
   },
 
   toggle() {
@@ -113,6 +122,6 @@ module.exports = {
   },
 
   consumeScrollMarker(scrollMarkerAPI) {
-    return this.areaView.setScrollMarker(scrollMarkerAPI);
+    this.scrollMarkersService = new ScrollMarkersService(this.areaView, scrollMarkerAPI);
   }
 };
diff --git a/lib/highlighted-area-view.js b/lib/highlighted-area-view.js
index 7570fa4..ec7712a 100644
--- a/lib/highlighted-area-view.js
+++ b/lib/highlighted-area-view.js
@@ -1,6 +1,7 @@
-const { Range, CompositeDisposable, Emitter } = require('atom');
-const StatusBarView = require('./status-bar-view');
-const escapeRegExp = require('./escape-reg-exp');
+const { CompositeDisposable, Emitter } = require('atom');
+const escapeRegExp = require('./utils/escape-reg-exp');
+const getNonWordCharacters = require('./utils/non-word-characters');
+const isWordSelected = require('./utils/is-word-selected');
 
 class EarlyTerminationSignal extends Error {}
 
@@ -51,81 +52,9 @@ module.exports = class HighlightedAreaView {
     return outcome;
   }
 
-  static getNonWordCharacters(editor, point) {
-    const scopeDescriptor = editor.scopeDescriptorForBufferPosition(point);
-    const nonWordCharacters = atom.config.get('editor.nonWordCharacters', {
-      scope: scopeDescriptor
-    });
-
-    return nonWordCharacters;
-  }
-
-  static ensureScrollViewInstalled() {
-    if (!atom.inSpecMode()) {
-      /* eslint-disable */
-      require('atom-package-deps').install('highlight-selected', true);
-      /* eslint-enable */
-    }
-  }
-
-  static isWordSelected(selection) {
-    if (selection.getBufferRange().isSingleLine()) {
-      const selectionRange = selection.getBufferRange();
-      const lineRange = HighlightedAreaView.getActiveEditor().bufferRangeForBufferRow(
-        selectionRange.start.row
-      );
-      const nonWordCharacterToTheLeft =
-        selectionRange.start.isEqual(lineRange.start) ||
-        HighlightedAreaView.isNonWordCharacterToTheLeft(selection);
-      const nonWordCharacterToTheRight =
-        selectionRange.end.isEqual(lineRange.end) ||
-        HighlightedAreaView.isNonWordCharacterToTheRight(selection);
-
-      return nonWordCharacterToTheLeft && nonWordCharacterToTheRight;
-    }
-    return false;
-  }
-
-  static isNonWord(editor, range) {
-    const nonWordCharacters = HighlightedAreaView.getNonWordCharacters(editor, range.start);
-    const text = editor.getTextInBufferRange(range);
-    return new RegExp(`[ \t${escapeRegExp(nonWordCharacters)}]`).test(text);
-  }
-
-  static isNonWordCharacterToTheLeft(selection) {
-    const selectionStart = selection.getBufferRange().start;
-    const range = Range.fromPointWithDelta(selectionStart, 0, -1);
-    return HighlightedAreaView.isNonWord(HighlightedAreaView.getActiveEditor(), range);
-  }
-
-  static isNonWordCharacterToTheRight(selection) {
-    const selectionEnd = selection.getBufferRange().end;
-    const range = Range.fromPointWithDelta(selectionEnd, 0, 1);
-    return HighlightedAreaView.isNonWord(HighlightedAreaView.getActiveEditor(), range);
-  }
-
   constructor() {
-    this.destroy = this.destroy.bind(this);
-    this.onDidAddMarker = this.onDidAddMarker.bind(this);
-    this.onDidAddSelectedMarker = this.onDidAddSelectedMarker.bind(this);
-    this.onDidAddMarkerForEditor = this.onDidAddMarkerForEditor.bind(this);
-    this.onDidAddSelectedMarkerForEditor = this.onDidAddSelectedMarkerForEditor.bind(this);
-    this.onDidRemoveAllMarkers = this.onDidRemoveAllMarkers.bind(this);
-    this.disable = this.disable.bind(this);
-    this.enable = this.enable.bind(this);
-    this.setStatusBar = this.setStatusBar.bind(this);
     this.debouncedHandleSelection = this.debouncedHandleSelection.bind(this);
-    this.handleSelection = this.handleSelection.bind(this);
-    this.removeAllMarkers = this.removeAllMarkers.bind(this);
-    this.removeMarkers = this.removeMarkers.bind(this);
-    this.setupStatusBar = this.setupStatusBar.bind(this);
-    this.removeStatusBar = this.removeStatusBar.bind(this);
-    this.listenForStatusBarChange = this.listenForStatusBarChange.bind(this);
-    this.selectAll = this.selectAll.bind(this);
-    this.setScrollMarker = this.setScrollMarker.bind(this);
-    this.setupMarkerLayers = this.setupMarkerLayers.bind(this);
-    this.setScrollMarkerView = this.setScrollMarkerView.bind(this);
-    this.destroyScrollMarkers = this.destroyScrollMarkers.bind(this);
+
     this.emitter = new Emitter();
     this.editorToMarkerLayerMap = {};
     this.markerLayers = [];
@@ -135,7 +64,6 @@ module.exports = class HighlightedAreaView {
     this.editorSubscriptions.add(
       atom.workspace.observeTextEditors(editor => {
         this.setupMarkerLayers(editor);
-        return this.setScrollMarkerView(editor);
       })
     );
 
@@ -147,7 +75,6 @@ module.exports = class HighlightedAreaView {
         const editor = item.item;
         this.removeMarkers(editor.id);
         delete this.editorToMarkerLayerMap[editor.id];
-        this.destroyScrollMarkers(editor);
       })
     );
 
@@ -158,39 +85,17 @@ module.exports = class HighlightedAreaView {
       return this.subscribeToActiveTextEditor();
     });
     this.subscribeToActiveTextEditor();
-    this.listenForStatusBarChange();
-
-    this.enableScrollViewObserveSubscription = atom.config.observe(
-      'highlight-selected.showResultsOnScrollBar',
-      enabled => {
-        if (enabled) {
-          HighlightedAreaView.ensureScrollViewInstalled();
-          return atom.workspace.getTextEditors().forEach(this.setScrollMarkerView);
-        }
-        return atom.workspace.getTextEditors().forEach(this.destroyScrollMarkers);
-      }
-    );
   }
 
   destroy() {
     clearTimeout(this.handleSelectionTimeout);
     this.activeItemSubscription.dispose();
-    if (this.selectionSubscription != null) {
+    if (this.selectionSubscription) {
       this.selectionSubscription.dispose();
     }
-    if (this.enableScrollViewObserveSubscription != null) {
-      this.enableScrollViewObserveSubscription.dispose();
-    }
-    if (this.editorSubscriptions != null) {
+    if (this.editorSubscriptions) {
       this.editorSubscriptions.dispose();
     }
-    if (this.statusBarView != null) {
-      this.statusBarView.removeElement();
-    }
-    if (this.statusBarTile != null) {
-      this.statusBarTile.destroy();
-    }
-    this.statusBarTile = null;
   }
 
   onDidAddMarker(callback) {
@@ -213,6 +118,10 @@ module.exports = class HighlightedAreaView {
     this.emitter.on('did-add-selected-marker-for-editor', callback);
   }
 
+  onDidFinishAddingMarkers(callback) {
+    this.emitter.on('did-finish-adding-markers', callback);
+  }
+
   onDidRemoveAllMarkers(callback) {
     this.emitter.on('did-remove-marker-layer', callback);
   }
@@ -227,11 +136,6 @@ module.exports = class HighlightedAreaView {
     return this.debouncedHandleSelection();
   }
 
-  setStatusBar(statusBar) {
-    this.statusBar = statusBar;
-    return this.setupStatusBar();
-  }
-
   debouncedHandleSelection() {
     clearTimeout(this.handleSelectionTimeout);
     this.handleSelectionTimeout = setTimeout(() => {
@@ -247,7 +151,7 @@ module.exports = class HighlightedAreaView {
   }
 
   subscribeToActiveTextEditor() {
-    if (this.selectionSubscription != null) {
+    if (this.selectionSubscription) {
       this.selectionSubscription.dispose();
     }
 
@@ -301,11 +205,11 @@ module.exports = class HighlightedAreaView {
     let regexSearch = escapeRegExp(text);
 
     if (atom.config.get('highlight-selected.onlyHighlightWholeWords')) {
-      if (!HighlightedAreaView.isWordSelected(lastSelection)) {
+      if (!isWordSelected(editor, lastSelection)) {
         return;
       }
       const selectionStart = lastSelection.getBufferRange().start;
-      const nonWordCharacters = HighlightedAreaView.getNonWordCharacters(editor, selectionStart);
+      const nonWordCharacters = getNonWordCharacters(editor, selectionStart);
       const allowedCharactersToSelect = atom.config.get(
         'highlight-selected.allowedCharactersToSelect'
       );
@@ -340,22 +244,20 @@ module.exports = class HighlightedAreaView {
       this.highlightSelectionInEditor(editor, regexSearch, regexFlags);
     }
 
-    if (this.statusBarElement) {
-      this.statusBarElement.updateCount(this.resultCount);
-    }
+    this.emitter.emit('did-finish-adding-markers');
   }
 
   highlightSelectionInEditor(editor, regexSearch, regexFlags, originalEditor) {
-    if (editor == null) {
+    if (!editor) {
       return;
     }
     const maximumHighlights = atom.config.get('highlight-selected.maximumHighlights');
-    if (!(this.resultCount < maximumHighlights)) {
+    if (this.resultCount > maximumHighlights) {
       return;
     }
 
     const markerLayers = this.editorToMarkerLayerMap[editor.id];
-    if (markerLayers == null) {
+    if (!markerLayers) {
       return;
     }
     const markerLayer = markerLayers.visibleMarkerLayer;
@@ -385,7 +287,7 @@ module.exports = class HighlightedAreaView {
           });
         }
 
-        if (newResult == null) {
+        if (!newResult) {
           return;
         }
         this.resultCount += 1;
@@ -425,11 +327,13 @@ module.exports = class HighlightedAreaView {
   }
 
   removeAllMarkers() {
-    return Object.keys(this.editorToMarkerLayerMap).forEach(this.removeMarkers);
+    return Object.keys(this.editorToMarkerLayerMap).forEach(editorId =>
+      this.removeMarkers(editorId)
+    );
   }
 
   removeMarkers(editorId) {
-    if (this.editorToMarkerLayerMap[editorId] == null) {
+    if (!this.editorToMarkerLayerMap[editorId]) {
       return;
     }
 
@@ -439,51 +343,14 @@ module.exports = class HighlightedAreaView {
     markerLayer.clear();
     selectedMarkerLayer.clear();
 
-    if (this.statusBarElement != null) {
-      this.statusBarElement.updateCount(0);
-    }
-
+    this.resultCount = 0;
     this.emitter.emit('did-remove-marker-layer');
   }
 
-  setupStatusBar() {
-    if (this.statusBarElement != null) {
-      return;
-    }
-    if (!atom.config.get('highlight-selected.showInStatusBar')) {
-      return;
-    }
-    this.statusBarElement = new StatusBarView();
-    this.statusBarTile = this.statusBar.addLeftTile({
-      item: this.statusBarElement.getElement(),
-      priority: 100
-    });
-  }
-
-  removeStatusBar() {
-    if (this.statusBarElement == null) {
-      return;
-    }
-    if (this.statusBarTile != null) {
-      this.statusBarTile.destroy();
-    }
-    this.statusBarTile = null;
-    this.statusBarElement = null;
-  }
-
-  listenForStatusBarChange() {
-    return atom.config.onDidChange('highlight-selected.showInStatusBar', changed => {
-      if (changed.newValue) {
-        return this.setupStatusBar();
-      }
-      return this.removeStatusBar();
-    });
-  }
-
   selectAll() {
     const editor = HighlightedAreaView.getActiveEditor();
     const markerLayers = this.editorToMarkerLayerMap[editor.id];
-    if (markerLayers == null) {
+    if (!markerLayers) {
       return;
     }
     const ranges = [];
@@ -498,18 +365,10 @@ module.exports = class HighlightedAreaView {
     }
   }
 
-  setScrollMarker(scrollMarkerAPI) {
-    this.scrollMarker = scrollMarkerAPI;
-    if (atom.config.get('highlight-selected.showResultsOnScrollBar')) {
-      HighlightedAreaView.ensureScrollViewInstalled();
-      atom.workspace.getTextEditors().forEach(this.setScrollMarkerView);
-    }
-  }
-
   setupMarkerLayers(editor) {
     let markerLayer;
     let markerLayerForHiddenMarkers;
-    if (this.editorToMarkerLayerMap[editor.id] != null) {
+    if (this.editorToMarkerLayerMap[editor.id]) {
       markerLayer = this.editorToMarkerLayerMap[editor.id].visibleMarkerLayer;
       markerLayerForHiddenMarkers = this.editorToMarkerLayerMap[editor.id].selectedMarkerLayer;
     }
@@ -520,32 +379,4 @@ module.exports = class HighlightedAreaView {
       selectedMarkerLayer: markerLayerForHiddenMarkers
     };
   }
-
-  setScrollMarkerView(editor) {
-    if (!atom.config.get('highlight-selected.showResultsOnScrollBar')) {
-      return;
-    }
-    if (this.scrollMarker == null) {
-      return;
-    }
-
-    const scrollMarkerView = this.scrollMarker.scrollMarkerViewForEditor(editor);
-
-    const markerLayer = this.editorToMarkerLayerMap[editor.id].visibleMarkerLayer;
-    const { selectedMarkerLayer } = this.editorToMarkerLayerMap[editor.id];
-
-    scrollMarkerView.getLayer('highlight-selected-marker-layer').syncToMarkerLayer(markerLayer);
-    scrollMarkerView
-      .getLayer('highlight-selected-selected-marker-layer')
-      .syncToMarkerLayer(selectedMarkerLayer);
-  }
-
-  destroyScrollMarkers(editor) {
-    if (this.scrollMarker == null) {
-      return;
-    }
-
-    const scrollMarkerView = this.scrollMarker.scrollMarkerViewForEditor(editor);
-    scrollMarkerView.destroy();
-  }
 };
diff --git a/lib/scroll-markers/scroll-markers-service.js b/lib/scroll-markers/scroll-markers-service.js
new file mode 100644
index 0000000..671205f
--- /dev/null
+++ b/lib/scroll-markers/scroll-markers-service.js
@@ -0,0 +1,90 @@
+const { CompositeDisposable } = require('atom');
+
+module.exports = class ScrollMarkersService {
+  static ensureScrollViewInstalled() {
+    if (!atom.inSpecMode()) {
+      /* eslint-disable */
+      require('atom-package-deps').install('highlight-selected', true);
+      /* eslint-enable */
+    }
+  }
+
+  constructor(areaView, scrollMarkerAPI) {
+    this.areaView = areaView;
+    this.scrollMarkerAPI = scrollMarkerAPI;
+
+    if (atom.config.get('highlight-selected.showResultsOnScrollBar')) {
+      ScrollMarkersService.ensureScrollViewInstalled();
+      atom.workspace.getTextEditors().forEach(editor => this.setScrollMarkerView(editor));
+    }
+
+    this.setupEditorSubscriptions();
+    this.setupConfigObserver();
+  }
+
+  destroy() {
+    this.editorSubscriptions.dispose();
+    this.enableScrollViewObserveSubscription.dispose();
+  }
+
+  setupEditorSubscriptions() {
+    this.editorSubscriptions = new CompositeDisposable();
+    this.editorSubscriptions.add(
+      atom.workspace.observeTextEditors(editor => {
+        this.setScrollMarkerView(editor);
+      })
+    );
+
+    this.editorSubscriptions.add(
+      atom.workspace.onWillDestroyPaneItem(item => {
+        if (item.item.constructor.name !== 'TextEditor') {
+          return;
+        }
+        const editor = item.item;
+        this.destroyScrollMarkers(editor);
+      })
+    );
+  }
+
+  setupConfigObserver() {
+    this.enableScrollViewObserveSubscription = atom.config.observe(
+      'highlight-selected.showResultsOnScrollBar',
+      enabled => {
+        if (enabled) {
+          ScrollMarkersService.ensureScrollViewInstalled();
+          atom.workspace.getTextEditors().forEach(editor => this.setScrollMarkerView(editor));
+        } else {
+          atom.workspace.getTextEditors().forEach(editor => this.destroyScrollMarkers(editor));
+        }
+      }
+    );
+  }
+
+  setScrollMarkerView(editor) {
+    if (!atom.config.get('highlight-selected.showResultsOnScrollBar')) {
+      return;
+    }
+    if (!this.scrollMarkerAPI) {
+      return;
+    }
+
+    const scrollMarkerView = this.scrollMarkerAPI.scrollMarkerViewForEditor(editor);
+
+    const markerLayer = this.areaView.editorToMarkerLayerMap[editor.id].visibleMarkerLayer;
+    const { selectedMarkerLayer } = this.areaView.editorToMarkerLayerMap[editor.id];
+
+    scrollMarkerView.getLayer('highlight-selected-marker-layer').syncToMarkerLayer(markerLayer);
+    scrollMarkerView
+      .getLayer('highlight-selected-selected-marker-layer')
+      .syncToMarkerLayer(selectedMarkerLayer);
+  }
+
+  destroyScrollMarkers(editor) {
+    if (!this.scrollMarkerAPI) {
+      return;
+    }
+
+    const scrollMarkerView = this.scrollMarkerAPI.scrollMarkerViewForEditor(editor);
+    scrollMarkerView.destroy();
+  }
+};
diff --git a/lib/status-bar/status-bar-service.js b/lib/status-bar/status-bar-service.js
new file mode 100644
index 0000000..b5e2d0f
--- /dev/null
+++ b/lib/status-bar/status-bar-service.js
@@ -0,0 +1,69 @@
+const StatusBarView = require('./status-bar-view');
+
+module.exports = class StatusBarService {
+  constructor(statusBar, areaView) {
+    this.statusBar = statusBar;
+    this.areaView = areaView;
+
+    this.updateCount = this.updateCount.bind(this);
+
+    this.listenForStatusBarConfigChange();
+    this.setupListeners();
+
+    this.setupStatusBarView();
+  }
+
+  destroy() {
+    this.removeStatusBarView();
+    if (this.selectionSubscription) {
+      this.selectionSubscription.dispose();
+    }
+  }
+
+  listenForStatusBarConfigChange() {
+    return atom.config.onDidChange('highlight-selected.showInStatusBar', changed => {
+      if (changed.newValue) {
+        return this.setupStatusBarView();
+      }
+      return this.removeStatusBarView();
+    });
+  }
+
+  setupListeners() {
+    this.areaView.onDidFinishAddingMarkers(this.updateCount);
+    this.areaView.onDidRemoveAllMarkers(this.updateCount);
+  }
+
+  setupStatusBarView() {
+    if (this.statusBarElement) {
+      return;
+    }
+    if (!atom.config.get('highlight-selected.showInStatusBar')) {
+      return;
+    }
+    this.statusBarElement = new StatusBarView();
+    this.statusBarTile = this.statusBar.addLeftTile({
+      item: this.statusBarElement.getElement(),
+      priority: 100
+    });
+  }
+
+  removeStatusBarView() {
+    if (!this.statusBarElement) {
+      return;
+    }
+    this.statusBarElement.removeElement();
+    if (this.statusBarTile) {
+      this.statusBarTile.destroy();
+    }
+    this.statusBarTile = null;
+    this.statusBarElement = null;
+  }
+
+  updateCount() {
+    if (!this.statusBarElement) {
+      return;
+    }
+    this.statusBarElement.updateCount(this.areaView.resultCount);
+  }
+};
diff --git a/lib/status-bar-view.js b/lib/status-bar/status-bar-view.js
similarity index 100%
rename from lib/status-bar-view.js
rename to lib/status-bar/status-bar-view.js
diff --git a/lib/escape-reg-exp.js b/lib/utils/escape-reg-exp.js
similarity index 100%
rename from lib/escape-reg-exp.js
rename to lib/utils/escape-reg-exp.js
diff --git a/lib/utils/is-word-selected.js b/lib/utils/is-word-selected.js
new file mode 100644
index 0000000..59c64c0
--- /dev/null
+++ b/lib/utils/is-word-selected.js
@@ -0,0 +1,36 @@
+const { Range } = require('atom');
+const escapeRegExp = require('./escape-reg-exp');
+const getNonWordCharacters = require('./non-word-characters');
+
+function isNonWord(editor, range) {
+  const nonWordCharacters = getNonWordCharacters(editor, range.start);
+  const text = editor.getTextInBufferRange(range);
+  return new RegExp(`[ \t${escapeRegExp(nonWordCharacters)}]`).test(text);
+}
+
+function isNonWordCharacterToTheLeft(editor, selection) {
+  const selectionStart = selection.getBufferRange().start;
+  const range = Range.fromPointWithDelta(selectionStart, 0, -1);
+  return isNonWord(editor, range);
+}
+
+function isNonWordCharacterToTheRight(editor, selection) {
+  const selectionEnd = selection.getBufferRange().end;
+  const range = Range.fromPointWithDelta(selectionEnd, 0, 1);
+  return isNonWord(editor, range);
+}
+
+module.exports = function isWordSelected(editor, selection) {
+  if (selection.getBufferRange().isSingleLine()) {
+    const selectionRange = selection.getBufferRange();
+    const lineRange = editor.bufferRangeForBufferRow(selectionRange.start.row);
+    const nonWordCharacterToTheLeft =
+      selectionRange.start.isEqual(lineRange.start) ||
+      isNonWordCharacterToTheLeft(editor, selection);
+    const nonWordCharacterToTheRight =
+      selectionRange.end.isEqual(lineRange.end) || isNonWordCharacterToTheRight(editor, selection);
+
+    return nonWordCharacterToTheLeft && nonWordCharacterToTheRight;
+  }
+  return false;
+};
diff --git a/lib/utils/non-word-characters.js b/lib/utils/non-word-characters.js
new file mode 100644
index 0000000..b9258d9
--- /dev/null
+++ b/lib/utils/non-word-characters.js
@@ -0,0 +1,8 @@
+module.exports = function getNonWordCharacters(editor, point) {
+  const scopeDescriptor = editor.scopeDescriptorForBufferPosition(point);
+  const nonWordCharacters = atom.config.get('editor.nonWordCharacters', {
+    scope: scopeDescriptor
+  });
+
+  return nonWordCharacters;
+};