I know that you might be tired of reading/hearing about it, and there is enough material on it out there. Still, there are many inconsistencies and misconceptions that might make you fuzzy. So I’ll show you what I see as being the basics and give you good references. If it makes you curious enough, soon I’ll be posting some samples.

Concept

Erick Evans, on his book about DDD, raises an interesting point about the object’s life cycle and reconstituting stored objects when writing about factories:

At some point, most objects get stored in databases or transmitted through a network, and few current database technologies retain the object character of their contents. Most transmission methods flatten an object into an even more limited presentation. Therefore, retrieval requires a potentially complex process of reassembling the parts into a live object.
Eric Evans

He is explaining the importance of factories (as ORMs) to recreate objects as they were before being persisted to the database. He argues that there is a great responsibility for these objects when they reconstitute the previous state of a disposed object as they once were.

Although his idea of object’s life cycle could be considered already flatten on an event-driven perspective. So we could say Most structural data models flatten objects into an even more limited presentation. Due to understanding it better, we should discuss what it means. Consider reading Martin Fowlersarticle about the subject, where he explains his view about event source (ES):

The core idea of event sourcing is that whenever we make a change to the state of a system, we record that state change as an event, and we can confidently rebuild the system state by reprocessing the events at any time in the future. The event store becomes the principal source of truth, and the system state is purely derived from it. For programmers, the best example of this is a version control system. The log of all the commits is the event store and the working copy of the source tree is the system state.
Martin Fowler

In addition to Erick`s view, ES expands the immutability, only covered by Value Objects on DDD, to whole application state, like a shadow. We only append facts to the repository. In spite of changing and deleting objects, we create new events that, when applied, remove or change them from the current state.

Aplication

As good as it sounds, of course, you might not be already pumped to use it. I’ve just described what it is, not why. Why should you care? After all, if you wanna fix something without nails, a hammer is useless.

I’ve questioned myself that years ago. To answer I had to associate with other concepts first, like distributed computing, DDD, functional programming. Now, I have a view of my own, and I hope to help to build yours.

One of its characteristics is traceability/auditability. Natively, you got the ability to trace all domain changes and easily understand how the application is behaving. Even more, you could easily add user information and audite user changes.

Another important feature it provides is an easy reconciliation. So, when things go south between distributed systems, one can simply ask for what happened to others on a period then process all lost messages.

For these reasons, ES should solve many problems like conflict management and desynchronization on microservice applications that shares business flows and IoT/embedded systems that might work off-line.

There is plenty of real-world applications that would leverage this pattern, like:

  • Shipment tracker
  • IoT systems in general
  • Version control systems
  • Banking transactions

Conclusion

To conclude the pros/cons, I will let Greg Young, who has made the concept popular, anwser that:

Pros

Single Event Centric Model
Simplified/Better Testing
Conflict Management

Cons

Harder to sell to an organization
Less known tools/technologies (though you can implement the Event Store in a RDBMS which kind of mitigates this)
Very difficult to migrate a legacy app to
Greg Young

Next steps

I’ve been working with C# for a while now, so I will be posting some sample soon. But keep in mind that, as Vaught Venom wrote in his book Implementing Domain Driven Design, “ES is inherently functional in nature”, and its use on this paradigm would “potentially lead to more concise code that performs optimally”.

Last week I was looking a way to find out the city from a latitude and longitude. So here is what I learned.

Circumstances

Actualy I and my team triped over this issue, because we are using the venues from the Foursquare API, that doesn’t always provide this informations, and when it does may be roungh. So I strugle in some insatisfary solutions, between those I’ve tested Geonames Onpenstreemap and Mapbpx API. Finaly it led me to the beta service of Opencage, that uses the Towfishes to resolve the geocode reverse.

I’m currently using the Mapbox map to display the Foursquare venues, and the Geoname api to auto complete cities names on a search form. It shouldn’t be hard at all, if it isn’t the fact we can’t use the Google api, because its license agreement obligate us to use from its own map.

Developing acess to the APIs

The ideal scenario would use the Geoname API, because it’s free service, we are already using, so the city aliases would be similar to the searched venues input.

As I’ve already experienced previously, it results don’t follow a strict pattern, but tried it again to be sure.

As an alternative I’ve chosen to test the Mapbox api, that we already have an account, and the Openstreetmap, that doesn’t require any account.

In oder to develop test the APIs, I’ve coded an Angular Webapp using a template from Yeoman.

Implementation

Then I develop a service that would use all those APIs.

To configure the service I’ve added constant to the angular module as follow.

reverseGeocodeModule.constant('GeoAPIConstants', {
    mapBoxId: 'xxxxxx',
    geonameId: 'xxxxxx',
    openCage: 'xxxxxx'
  });

When I developed the services, I used these constants to identify the environment configurations, so I don’t need to peek on every file to change my access accounts.

Let me show the services.

Mapbox

The Mapbox WEB API has this reverse geocode call.

reverseGeocodeModule.service('MapboxService', [ '$http','GeoAPIConstants',
  function($http,GeoAPIConstants){
    var self = this;
    var urls = {};
    urls.geocode = "http://api.tiles.mapbox.com/v3/{0}/geocode/{1},{2}.json";
    self.FindCityReverseGeocode = function(lng, lat){
      var q = $http.get(urls.geocode.format(GeoAPIConstants.mapBoxId,lng,lat));
        return q.then(function(r){
                    return self.extractCityFromGeocodeJSONResult(r.data);
        });
      };
    self.extractCityFromGeocodeJSONResult = function(result){
      if(self.isResultEmpty(result))
        return null;
      return self.searchInMatrixForCity(result);
    };
    self.isResultEmpty = function(result){
      return !result.results || result.results.length === 0;
    }
    self.searchInMatrixForCity = function(result){
      for(var i = 0; i < result.results.length; i++){
        for(var j = 0; j < result.results.length; j++){
          if(result.results[i][j].type == 'city')
            return result.results[i][j];
        }
      }
      return null;
    }
  }]);

Openstreetmap

reverseGeocodeModule.service('OpenstreetmapService', [ '$http',
  function($http){
    var self = this;
    var urls = {};
    urls.geocode = "http://nominatim.openstreetmap.org/reverse?format=json&lat={1}&lon={0}";
    self.FindCityReverseGeocode = function(lng, lat){
            return $http.get(urls.geocode.format(lng,lat));
    };
  }]);

Geonames

reverseGeocodeModule.service('GeonamesService', [ '$http','GeoAPIConstants',
  function($http,GeoAPIConstants){
    var self = this;
    var urls = {};
    urls.reverseGeocode = "http://ws.geonames.org/findNearbyPlaceNameJSON?lat={1}&lng={0}&style=full&username={2}";

    self.FindCityReverseGeocode = function(lng, lat){
            var q = $http.get(urls.reverseGeocode.format(lng,lat,GeoAPIConstants.geonameId));
            return q.then(function(result){
                var listResults = result.data.geonames;
                for(var i = 0; i < listResults.length; i++){
                    if(0<=self.findFeatureClassIndexFor(listResults[i]))
                      return listResults[i];
                }
            });
    };
    self.findFeatureClassIndexFor = function(geolocation){
      var featureClassNameList = geolocation.fclName.split(',');
      return featureClassNameList.indexOf("city");
    };
  }]);

Solution elected

Opencage service

reverseGeocodeModule.service('OpenCageService', [ '$http','GeoAPIConstants',
  function($http,GeoAPIConstants){
    var self = this;
    var urls = {};
    urls.geocode = "https://api.opencagedata.com/geocode/v1/json?q={1},{0}&pretty=1&key={2}";
    self.FindCityGeoCodeReverse = function(lng, lat){
      if(lng>0)
        lng='+'+lng;
      if(lat>0)
        lat='+'+lat;
      var q = $http.get(urls.geocode.format(lng,lat,GeoAPIConstants.openCage));
        return q.then(function(r){
                    return r.data.results[0].components;
        });
      };
  }]);

Next experiments

The chosen API is running in beta version, so considered it risky. In order to mitigate it, the next step would be try the Twofishes solution, which opencage uses, to evaluate it as an alternative.

In this jump start I will show how to create a Angular directive using Yeoman.

But before the good part, let me briefly introduce to you Yeoman, or can’t handle yourself just skip to the good part.

What’a hell?

You may not know about the existence of Yeoman, as I didn’t. So in that case you are asking yourself “What the F$%# is this?”. Yeoman is scaffolding tool that helps developers to start up their projects, especially the web kind. It generates boilerplate code, including bower and npm package references and task runner scripts like grunt and gulp.

And? Why should I care about it?

Actually, this is pretty neat, because you can easily set up a solution with a whole structure, without having to copy code from other projects or write the same jibber jabber.

Copy ain't funny

Therefore, it increases your productivity and, if use it the right way, software quality, by adding and configure tools that you would may leave behind, because they “delay” your “progress”.

It has already set of generators, that cover a good variety of solutions. Each one requires some usual tasks for its purpose, like automated tests, build, watch (livereload), and in common projects dependencies, as AngularJS, Bootstrap.

In order to cover these needs, it may generate bower and npm package references and Grunt or Gult files for running tasks.

#LetsGetDownToIt

We need some stuff fist:

  • Install NPM, nodejs package manager
  • And them Yeoman itself, running the following command:
npm install -g yo

Now we are good to go! We need to download the angular directives generator for Yeoman.

You can find generators by searching in npm by packages with the prefix “generator”, like that:

npm search generator WhaterverYouLike

In this case we will need the angular directive, so we search like this:

npm search generator directive

With the package name in hand we install it.

npm install generator-angular-directive -g

The npm packages with “generator-“ prefix stands for yo templates. To run the recently added generator, we just need loose the prefix and pass it as argument to Yeomann. Before this ensure that you are in the project folder.

mkdir ng-yomanDirective
cd ng-yomanDirective
yo angular-directive

Now that the magic happens! The Yeoman will ask some setting to generate in a more convenient way the project.

This template will ask you the name you wish to give for your new directive and your github name.

And them It will create a solution with: * A configuration to build, run test and run server for live demo; * Automated test configuration with karma and jasmine; * Travis configuration for continuous integration.

These are the things you need to just start developing.

With the solution set run the following lines to install all dependencies:

npm install -g gulp
npm install -g bower
npm install
bower install

For run the live reload demo run:

gulp serve

And to develop using TDD, looking forward to maintain your bar green, run:

gulp test