Refactor Settings update

@Jonahss settings changes touched off a 31 message exchange of chunky emails between Jonathan and me.  He helped me better understand Jonah's changes within the context of Node.  There were two major results from that discussion:

1. I see now that Jonah did all the right things; and,
2. I believe that my concerns can be resolved by refining Jonah's approach rather than supplanting it.

As I worked through the code with jlipp's help, the refactoring I did looked more and more like Jonah's solution.  However, I've been able to simplify things in several ways:

1. I encapsulated all the settings-related logic in the DeviceSettings object. This allowed me to remove the repetitive references to "get/updateSettings" from the various devices.
2. Encapsulation also helped me make updating settings more straightforward.  There's no need to worry about when to use `settings.update` vs `settings._settings`. There's only `settings.set` (well, there is a non-obvious way using `get`, but I won't get into that). 
3. In roughly the same amount of code that Jonah had written for DeviceSettings, I was able to provide the same functionality without using the EventEmitting class or Q or any other library.  The code I have works very similarly to EventEmitter, but it's less abstract, provides the functionality we need and nothing more, and requires a lot less code in aggregate.

Take a gander and let me know.  I'm hoping it's an "everybody is happy" solution. 
That's a good point.  If there are going to be multple listeners, we can 1)
add a `subscribe` event and then keep a list of subscribed listeners; or 2)
go with EventEmitter.  `subscribe` definitely looks a lot like `on` except
that it's be for updates only.

I'm really not opposed to event emitter, just trying to keep it simple.  I
looked through the EE code and understand how it works now, so I can live
with it.  If you feel strongly about it, let's keep it.

On Fri, Sep 12, 2014 at 5:16 PM, Jonah <notifications@github.com> wrote:

> In lib/devices/android/android.js:
>
> > @@ -72,14 +72,14 @@ Android.prototype.init = function () {
> >    , ['GET', new RegExp('^/wd/hub/session/[^/]+/appium')]
> >    ];
> >
> > -  // listen for changes to ignoreUnimportantViews
> > -  this.settings.on("update", function (update) {
> > -    if (update.key === "ignoreUnimportantViews") {
> > -      this.setCompressedLayoutHierarchy(update.value, update.callback);
> > +  // listen for changes to the settings object
> > +  this.settings.onPropertyChanged = function (propName, value, cb) {
>
> Setting settings.onPropertyChanged = [some function] doesn't allow for
> more than one part of the code to register a function to be called when the
> settings change.
>
> In our current implementation, only the Android Device listens to update
> events. But imagine we also have a setting called bombasticLogging which
> when true causes appium to do way more logging. The appium server itself
> would listen to a change on that setting, while the Android Device will
> still listen for compressLayoutHierarchy setting changes.
>
> A common pattern for allowing the registration of multiple callbacks would
> be to change is like so:
> this.settings.onPropertyChange([some function]) and every time it's
> called, the function passed in is added to a list of callbacks which all
> get called.
>
> Here's an example of when I made this exact mistake >.0
> axemclion/grunt-saucelabs#148
> <https://github.com/axemclion/grunt-saucelabs/issues/148>
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/appium/appium/pull/3630/files#r17503201>.
>