Find It! App – Success at SUN ‘n FUN

The Find It! mobile app for SUN ‘n FUN 2016 #SNF2016 was a big success with over 3000 downloads and great ratings and reviews. FindIt! received 4.7 stars in the Google Play Store and a perfect 5.0 stars in the Apple App Store…

Client Code Structure, Part 1: Model Files

Having good code structure is important to making any project successful.  In order to learn good code structure you first need to know what code structure means.  To me, it means both how you split different pieces of functionality into different files as well as how you organize the code within your files themselves.

Code structure is not something that you can usually find good examples of.  This is because unless the point of the example is to demonstrate good code structure it is usually more effective to get to the point of the functionality instead.  The example code from AngularJS is usually short and has a very limited scope making it a poor candidate for an example of code structure.  Pretty much all functionality in the examples within Angular’s documentation takes place within the controller file and this is how we originally structured our code.


angular.module('ModuleName').controller('ControllerName', 
   [ ...injected dependencies...
      function( ...injected dependencies... ){
         ...Do Stuff...
      }
   ]
);

This structure started off fine, until we needed to share properties across controllers. The solution was actually pretty simple to handle this. We simply created a SharedProperties object and injected it into each controller which needed it. We could even add SharedProperties to scope and any changes to it anywhere would show up in the view in which is was bound.

angular.module('ModuleName').controller('ControllerName', 
   [ '$scope', 'SharedProperties', ...other injected dependencies...
      function( $scope, SharedProperties, ...other injected dependencies... ){
         $scope.SharedProperties = SharedProperties;
         ...Do Stuff...
      }
   ]
);

This worked fine for a while, but as our need for adding shared properties grew, so did our SharedProperties file. Eventually, the file looked like this:

angular.module('Derby.services').service('sharedProperties', [function () {
    return {
        selectedDivisionId: 0,
        divisions: [],
        selectedDivision: null,
        raceYears: [],
        selectedRaceYear: null,
        RaceYearId: 2012,
        RaceYear: 2012,
        isUserLoggedIn: false,
        isUserAdmin: false,
        loggedInUser: null,
        collapseResources: false,
        sharedResourcesURL: "",
        imagePath: "/Derby/Apps/Shared/Assets/Images/",
        attemptingLogin: false,
        collapseChampionshipRound: false,
        drivers: {},
        divisionHeatCache: {},
        isUserLoggedInViaFacebook: false,
        facebookAccessToken: null,
        facebookUser: null,
        selectedHeat: null
    };
}]);

A loose collection of properties thrown together because we couldn’t find a better place to put them. Property files this large makes properties difficult to find, and therefore difficult to debug.

Even though the SharedProperties technique was being abused and was becoming unwieldy, that didn’t mean it was all bad. In fact, it reminded me of a similar technique used in ActionScript. The only difference was that we would create multiple files and each would hold only properties relevant to a single concept. These are known as “Model” files. This way we could inject only the properties we need and not worry about the rest. This methodology is maintainable, much cleaner, and easy to debug.

divisionModule.factory('DivisionModel',
  [
    function () {
      return {
        divisions: [],
        selectedDivision: null,
        manageDivisionInUrl: true

      }
    }
  ]
);

This file is injected and used in the same manner as SharedProperties, just only as needed.

 Next -> Client Code Structure, Part 2: Controller Files

Client Code Structure, Part 2: Controller Files

After separating shared properties into their own Model files, the next thing I ran into was that our controller files were getting large and unwieldy. This was especially the case for our main app.js file. I realized that this was because it contained a loose collection of methods thrown together because we couldn’t find a better place to put them (Sound Familiar?) I thought, “Wouldn’t it be nice if we could conceptually group these methods and separate them into different files just like we did with the models?”

It turns out you can! As I built this file I noticed that it reminded me of a controller file. Then I thought, “Wait, don’t we already have a controller?” It was at this point that I realized that what Angular calls a “Controller” is actually a “ViewModel” and what I was creating was a standard “Controller.” With this in mind, I kept view-specific methods in the ViewModel and created a controller class for non view-specific methods.

divisionModule.factory('DivisionController',
    ['DivisionModel', 'DivisionService',
        function (DivisionModel, DivisionService) {

            function getDivisionsResultHandler(result) {
                //Apply the result
            }

            function getDivisions() {
               DivisionService.query(queryParams, getDivisionsResultHandler);
            }

            getDivisions();

            return{
               getDivisions: getDivisions
            }
        }
    ]
);

I then injected these controller files into the relevant ViewModels (Angular Controllers) and began to invoke their methods directly. Something about this did not seem right, however. Controllers are not supposed to be invoked directly. Instead, they should communicate by registering and dispatching events. Angular has events, but since my controllers were not attached to a view they did not have a $scope and therefore would not propagate events. It was at that point I realized that I could inject the Angular $rootScope and dispatch and listen for events from there.

I went back to my ActionScript roots again and created a controller class as such:

divisionModule.factory('DivisionController',
    ['$rootScope', 'DivisionModel', 'DivisionService',
        function ($rootScope, DivisionModel, DivisionService) {

            function divisionSelectedHandler(event, division) {
                DivisionModel.selectedDivision = division;
            }
            $rootScope.$on('divisionSelected', divisionSelectedHandler);

            function getDivisionsResultHandler(result) {
                //Apply the result
                DivisionModel.divisions = result;

                $rootScope.$emit('divisionSelected', selectedDivision);
            }

            function getDivisions() {
                DivisionService.query(queryParams, getDivisionsResultHandler);
            }

            getDivisions();
        }
    ]
);

With the controller structured this way, I no longer had to inject it everywhere that I wanted to use it. Now generally it is bad practice to use $rootScope but since it is only being used as a conduit for communication I think it is acceptable.

 Next -> Client Code Structure, Part 3: Organization

Client Code Structure, Part 3: Organization

Now that our code is split into Models and Controllers it is much easier to read, maintain, and debug. I thought that I could take it one step further, however. Once again, I pulled from my old ActionScript standards and split each file into the following sections:

  • Model Files
    • Property Initialization
    • That’s all (You expected more?)
  • ViewModel Files
    • Injectables
    • Inheritance
    • Scope Initialization
    • UI Event Handlers (Handles events from the view)
    • Application Event Handlers (Handles events from $rootScope)
    • General helper functions
    • Code that runs when the view is created
  • Controller Files
    • Injectables
    • Application Event Handlers 
    • Result Handlers
    • Fault Handlers
    • General helper functions
    • Code that runs when the app loads

See the example below:

divisionModule.factory('DivisionController',
    [

        /**************************************
        ***
        *** Injectables
        ***
        **************************************/

        '$rootScope',
        'DivisionModel',
        'DivisionService',

        function ($rootScope, DivisionModel, DivisionService) {

            /*********************************
            ***
            *** Application Event Handlers
            ***
            *********************************/

            function divisionSelectedHandler(event, division) {
                DivisionModel.selectedDivision = division;
            }
            $rootScope.$on('divisionSelected', divisionSelectedHandler);

            /********************************
            ***
            *** Result Handlers
            ***
            ********************************/

            function getDivisionsResultHandler(result) {
                //Apply the result
                DivisionModel.divisions = result;

                $rootScope.$emit('divisionSelected', selectedDivision);
            }

            /********************************
            ***
            *** Fault Handlers
            ***
            ********************************/

            function getDivisionsFaultHandler(fault) {
                //Handle faults
            }

            /******************************
            ***
            *** Helper Methods
            ***
            ******************************/

            function getDivisions(){
                DivisionService.query(queryParams, getDivisionsResultHandler, getDivisionsFaultHandler);
            }

            /******************************
            ***
            *** Code that runs on startup
            ***
            ******************************/

            getDivisions();
        }
    ]
);

Now, if there is a problem in the application somewhere, not only do we know exactly which file to look at, we also know which section of the file to look at.

 Next -> Client File Structure

Client File Structure

Now that we have worked out how we will organize code, the next step is to determine how we will structure the source files.  As inexperienced AngularJS developers, we initially decided that instead of coming up with our own file structure, we should start with examples given to us by other developers.  The problem was that suitable examples were hard to come by.  Most examples dealt with small snippets of code instead of looking at file structure.  The only real example that we could find was the AngularJS seed project.  Below is a list of how this project is structured along with what each folder is expected to hold.  I have only drilled down into the “app” folder because that is the only group I propose to reorganize.

  • app – Application specific files
    • css – Style sheets
    • img – Image files
    • js – Source code
      • controllers – Angular controller files.  One per view (partial)
      • directives – Angular directives
      • filters – Angular utilities for sorting, filtering, and formatting
      • services – Other Angular utility files
      • app.js – The main controller for the application.  Relates directly to the index.html file
    • lib – Appears to be framework files (Angular files), but unclear how this differs from “Scripts”
    • partials – HTML view templates
    • index.html – The main view file
  • config – Configuration
  • logs – Log files
  • scripts – External javascript, not specific to this application
  • test – Unit tests

As you can see, these files are organized by file type and abstract functionality.  This works well for basic projects, but for larger projects we run into a problem.  Each of the folders are so general that many files will fit the description.  This means that you will end up with a mountain of files in each folder which makes it difficult to find anything.  Additionally, it is often difficult to organize these files into subfolders because other than abstract functionality (controllers, services, etc) these files are generally unrelated.  Furthermore, because these files are generally unrelated we rarely want to work on more than one of them at the same time (no one says, “I’m going to work on Controllers today”).

After careful consideration (and several meetings) we decided that our best bet was to group the files by business concept first.  After this, we can create additional file structure hierarchy if warranted.  I am using our RaceTracker app as an example below:

  • apps – Still application specific files
    • RaceTrackerApp – If there is more than one app, add this level of Hierarchy to contain files specific to this app
      • heats – code and templates specific to heats
        • directives – directives related to heats in the RaceTracker application
          • heatDirective1
          • heatDirective2
          • …etc
        • HeatController.js – Generic Controller file for heats for the RaceTracker application
        • HeatModel.js – Model file for heats for the RaceTracker application
        • heats.tpl.html – View template (partial) for heats in the RaceTracker app
        • HeatVMController – Controller file tied directly to the heats.tpl.html view
      • drivers – code and templates specific to drivers
        • directives  – Directives related to drivers in the RaceTracker app
        • DriverList – files related to the driver list view
          • DriverListVMController
          • driverList.tpl.html
        • DriverDetails – files related to the driver details view
          • DriverDetailsVMController
          • driverDetails.tpl.html
        • DriverModel
        • DriverController
      • security – code related to security specific to the RaceTracker app
        • SecurityModel
        • SecurityController
      • assets – Non-code related files
        • images – ’nuff said
          • logos
          • icons
          • backgrounds
          • …etc
        • style – Style sheets
          • css – compiled or unchanging css files
          • less – These get compiled into css
        • font – Font files
        • xml – Non-configuration related files for use in the app
        • …etc
      • app.js – Main application file for this app.  Should only contain code related to startup
    • shared – If there is more than one app, files shared between them go here
      • assets – Non-code related files
      • directives – Generic directives
        • directive1 – Folder for the first directive.  Any others will be structured the same way
          • directive1.html – Template for the first directive
          • directive1.js – Code for the first directive
      • security – Security related code shared between apps
        • SecuritySharedModel
        • SecuritySharedController
      • services – Remote data calls
        • services.js – All service call definitions go here.  We have not found a good reason to split them out at this time
      • utilities – General utility files
        • utility1.js
        • utility2.js
  • RaceTracker – This separation exists only to make the URL that the user sees smaller and less confusing
    • index.html – Main application view.  Relates to the app.js file in the corresponding application folder (in this case RaceTrackerApp)
    • config.js – Javascript configuration for this app
  • config – Configuration
  • logs – Log files
  • scripts – External javascript, not specific to this application
  • test – Unit tests

That is kind of a lot to take in at once, but the concept is simple;  Separate the files by business concept first.  Developers generally work on one business concept at a time and this file structure helps facilitate this by keeping the files that they will be looking at in the same location.  For example, if you are working on the Heats screen, you would not need to look very far to find the HeatModel, HeatController, heat view(heats.tpl.html), and view model (HeatVMController ) because they are all in the same folder.

 Next -> Client Code Standards

Client Side Code Structure and Standards – Prologue

AngularJS is a wonderful JavaScript framework which allows developers to quickly create dynamic websites while keeping a maintainable code base. It is not without its quirks, however. The fact that Angular has gained so much traction despite these quirks is a testament to just how amazing of a framework it is.

The quirks that I am referring to can generally be separated into three categories:

  • Documentation
  • Terminology
  • Standards

As you continue reading, bear in mind that these have been my experiences with AngularJS and your experiences may differ.  Also, some of the issues that I describe may now be resolved but were not at the time that this was written.

Documentation

The official documentation on AngularJS is pretty terrible if it exists at all.  Often times many options are available for a specific piece of functionality (api, directive, service, etc) but only a subset are explained leaving the developer to figure out the rest themselves or ask the community.  Also, there is usually only one example per piece of functionality.

Don’t get me wrong, I understand that framework architects are not necessarily good writers and I would rather them focus more on the framework itself than the documentation.  Additionally, whenever a deficiency or inconsistency is found in the documentation and brought up in a public forum, the developers are quick to address it.

Terminology

One of the most confusing things about AngularJS when getting started is getting used to the terminology.  It’s not that it is wrong, it’s just not the standards that are used in practice by many developers.  Below is a list of terms used in Angular along with what I believe their reasoning was and the names that I would normally refer to them as:

  • Angular Scope => View Specific Model – This one is not too bad.  I think they were trying to kill two birds with one stone here.  They were trying to create a view specific model for binding as well as a private scope to handle encapsulation (Something JavaScript does not do well on its own).  The Angular team combined both concepts into one here.
  • Angular Controller => View Model – I have found that often times people misunderstand the term “View Model”.  A View model is a piece of code that models the view and facilitates communication between the view and other parts of an application.  It includes properties that are bound to the view and handlers for UI events that occur on the view.  Additionally, it is created when a view is created and destroyed when the view is destroyed.  It is basically about half controller and half model.  Sound familiar?  This describes the Angular Controller perfectly.
  • Angular Factory => Controller – When I think “Factory” I think about multiple objects being created at a time and then later destroyed.  Angular “Factories” basically create a singleton object used to handle a single piece of functionality.  This object never goes away.  Depending upon implementation, these act a lot like standard Controller classes and nothing like what I would expect from a factory.
  • Angular Resource => Service – In my mind, a resource is any external item which is pulled into the code.  Generally, when I hear “resource” I think external files such as images, templates, etc.  In Angular, it is a way to access data via a REST service.  While this loosely fits the definition of a Resource it wouldn’t be the first name I would come up with.

Once you make the mental connection between the Angular terminology and the standard terminology it makes things a lot easier to understand.  For developers new to Angular, having the terminology mapping above will help with the learning curve significantly.

Standards

Since AngularJS is so new, I’m sure they are still working out their standards.  Standards can be broken into file structure, code structure, and code standards.  The only real example of official standards that I can find for Angular is the seed project.  While it works well for basic projects, when your project grows it quickly can get out of hand.  This is where we are going to make most of our progress.

 Next -> Client Code Structure, Part 1 – Organization

AngularJS – SharedDataServices & Refresh Buttons

The use of Shared Data Service in AngularJS allows us to quickly save off information received from server so it can be re-used later, thus limiting the number of hits we need to make. This is especially useful in mobile applications where we have to be conscious of our bandwidth usage.

One of the problems these services have is that they are very tightly coupled to the state of the application, and thus an enemy of the refresh button. In most mobile applications the refresh button isn’t available so we can avoid this issue. However, in Hybrid applications we need to manage our state a little more carefully in case the user is visiting from a desktop or mobile browser.

Let’s assume the following example is one from a Customer Detail Page. This page assumes that The Customer Info is stored in our Shared Data Service, but needs to be smart enough to react if it isn’t present. To do this we can prepare for failure by passing the ID of the customer that is in sharedData in the hash.

AngularJS – Polling for data

Polling for data in AngularJS can be accomplished quickly using the $timeout function. You pass two parameters to the $timeout instance; The first being the method to call, the second being the delay (in milliseconds).

$timeout($scope.getSomeData, 200);

Combining this with the counter enables you to quickly wire-up a repeated call for data over a specified timeframe.

$scope.keepPolling = function () {
    if ($scope.isPolling) {
        if ($scope.pollCount > 0) {
            $scope.pollCount--;
            $timeout($scope.getSomeData, 200);
        } else {
            $scope.stopPolling();
        }
    }
};

A full example can be seen in the following Gist

AngularJS: Communicating between Scopes

One of the many features of the AngularJS JavaScript framework is scope.  Scope is a way to encapsulate data relevant to a particular piece of functionality and keep it separate from functionality not directly related to it.  While this separation is desirable, from it rises the need to communication and pass data between scopes.

From what I can tell, there are six ways to communicate between scopes in AngularJS:

  1. Global Variables
  2. Parent/Child direct communication
  3. Cookies
  4. Shared Properties Services
  5. Binding
  6. Events

Global Variables

Using global variables is a very simple way to pass data between scopes.  Use of global variables is generally perceived to be a bad idea, however, because these variables can easily, and accidentally, be overwritten.  Additionally, this practice leads to spaghetti code.

Parent/Child or Sibling Communication

Direct communication between parent and child scopes or sibling scopes is also a possibility but this is usually a bad idea as well.  For one, communication in this manner causes tight coupling.  Additionally, the mechanism for communication between scopes in this manner is clunky.  Child scopes are implemented as linked lists.  This means that each parent has a link to the first and last child scope, and those child scopes have a link to their next sibling and previous sibling.  While there could be certain situations where this kind of communication is desirable, generally there is a better way.

Cookies

Use of cookies works well but should generally be used for their intended purpose which is to persist data locally.  If cookies are abused, you run into the same problem as global variables.  Also, cookies only store string data so attempting to communicate any non-string data would have the overhead of serialization.

Shared Properties Services

Shared properties services are a good way to share and cache data between scopes.  These are objects that are injected into controllers and directives using mechanisms provided by AngularJS which are intended to contain data common to each.  While communication can be achieved in this manner using watchers on a specified shared property, generally this is most useful for caching purposes.

To define a shared properties serivce:


angular.module('Derby.services').service('sharedProperties', [function () {
    return {
        selectedDivisionId: 0,
        //...Define other default shared properties here
    };
}]);

To use a shared properties service, inject it into a controller or directive and use it as an object:


angular.module('RaceTrackerApp.heats', []).controller('HeatsController', ['$scope', 'sharedProperties',
    function ($scope, sharedProperties) {
        //You must add sharedProperties to $scope in order to watch it
        $scope.sharedProperties = sharedProperties;

        //Watch the selectedDivisionId for changes
        $scope.$watch('sharedProperties.selectedDivisionId', 
            //This function will be executed when selectedDivisionId changes 
            //from anywhere
            function(newValue,oldValue){
                //Do something
            }
        );

Binding

Binding in AngularJS is a built-in way to easily pass data between parent and child scopes through HTML.  To facilitate communication, you can add a watcher on a bound variable.  When this variable changes, the watcher will fire allowing you to take some additional action.  The downside to binding is that it is difficult to achieve outside of HTML and therefore if the two scopes in which you want to communicate are not connected via HTML then binding should probably not be used.

To use binding, define a variable in your parent scope as such:


angular.module('RaceTrackerApp.heats', []).controller('HeatsController', ['$scope',
    function ($scope) {
        $scope.heats = [];

And use the variable in HTML as such:


<div ng-repeat="heat in heats">

Events

The final method of communicating between scopes is using events.  There are two kinds of events in AngularJS:

  • Broadcast – Event bubbles downward to all decentant scopes
  • Emit – Events bubble upwards to all ancestor scopes

Besides the fact that each event type bubbles in a different direction, these both work the same.  Each can pass in additional payload data.  Also, each can be watched for using $on.

To dispatch an event:


//heatCardClicked is the event name and heatDriverYear is the payload
$scope.$emit('heatCardClicked', heatDriverYear);

$broadcast works in the same way but bubbles in a different direction. To watch for an event:


//Watches for the heatCardClicked event.  Expects a heatDriverYear payload
$scope.$on('heatCardClicked', 
    function(event, heatDriverYear){
        //Do stuff after the heat card is clicked
    }
);

HTTP Posting of data in AngularJS

Posting HTTP data within the Angular framework requires the use of the $http angular service.  The reUrgency 2.0 programming practices have us interacting with server-side data through the use of RESTful services.  This allows us at reUrgency to utilize the $resource service within the Angular framework.  The $resource service is a wrapper around $http service which makes it easier and more efficient to consume RESTful services.

The $resource service requires the file angular-resource.js.  This service must first be loaded within your application.

Once the $resource service has been loaded it has the following usage pattern.

The Angular module can then be setup with multiple factory patterns that return $resource services. Below is an example of one such factory within the Derby app.

By giving the service a name, in this case DivisionService, the service can be referenced and used anywhere within your Angular application, or even across Angular applications as is being done within the Derby project.

The above example is creating a $resource service. The new service, as previously mentioned, is called DivisionService and it also has a new action called “update” which is mapped to the “PUT” HTTP verb.

This blog entry is about the posting of data. Below is a code snippet of another one of our Derby $resource services. This one is called AssignLaneService.

The Angular $resource service supports the main HTTP verbs/methods of GET, POST, and DELETE. Why the PUT verb was neglected is anybody’s guess. As you can see in the PUT example above, the $resource action of “update” was created and mapped to the HTTP verb “PUT”. Angular gives you the default actions listed below.

So if a developer wanted to post data using the AssignLaneService above, they would call the “save” action on that service.

Below is an example of one more $resource service within the Derby application and it is called RandomizeHeatService. The RandomizeHeatService service and the AssignLaneService will be the focus of this blog entry going forward.

These two services, RandomizeHeatService and AssignLaneService , randomly assign drivers to a heat and assign a driver to a lane withing a heat. They both take some input, make an insert into the database (along with some other functionality), and return the appropriate object. When I originally created these two services, I was using HTTP GETs to perform this transferring of data. HTTP GET, however, should only be utilized when requesting data, not when modifying data. Using HTTP GET to modify data does not follow the REST standard. To modify data within the REST environment, POST or PUT should be used. It is debatable whether in my usage I should be using a PUT or a POST. I settled on using POSTs for the two services above.

When POSTing data within Angular using the $resource service, the $resource service will post your data as an object. I ran into this problem with the RandomizeHeatService. The server-side WebApi controller only requires the ID (which is an integer) of the selected heat to do its magic. However, I could not just pass that integer ID because Angular would take that integer and wrap it inside an object. So on the server-side I had to create a custom class with only one property. This custom class is shown below.

By the way, this custom class was created within the Model layer as an entity (but this “entity” is not allowed to be added to the database as a table). It seems like overkill to create a class just so we can pass a single integer, but it appears that is what is required by Angular.

The AssignLaneService has several parameters that need to be passed to the server. It made much more sense to create a class in this instance. The custom class used to pass data to the server within the AssignLaneService is shown below.

You might ask why I didn’t use an existing entity as my input parameter and that would be a valid question. However, the nature of our database structure and the data actually inputted by the end user (namely the driver number) do not exist within a single entity. For this reason, the class above was created within the Model layer to handle the inputted data. The server-side code handles all of the relationships between the various entities.

With the two input classes created for our WebApi controllers, the actual function signatures for the server-side C# code are shown below.

Note the “HttpPost” decoration on both methods. That will tell the WebApi controller that both of these methods are POST methods. Normally, you can just use the default methods of “Put” and “Post” within a WebApi controller, but we created custom post methods for each WebApi controller because neither method strictly posted the entire entity defined by its WebApi controller.

This causes the URL for the REST service to include the respective method name as shown at the beginning of this blog post for the RandomizeHeatService and AssignLaneService services.

Originally, I was not passing back to the client an HttpResponseMessage. Doing that did not follow the practices of REST. When data is posted to the server, the client expects back an HttpResponseMessage. Below is the server-side C# code that creates the HttpResponseMessage return object. Please note, that according to the REST standard, within the return header the location of the newly created resource should be included.

In order to utilize either REST service provided by the server, the client can take advantage of the Angular services RandomizeHeatService and AssignLaneService created from before. An example using the AssignLaneService is shown below.

As you can see from the above JavaScript, an object was created with properties that match our custom server-side entity. These properties are then assigned values and passed to the server via the “save” action of the AssignLaneService (the “save” action by default being a POST).

Lastly, the “save” action expects two function handlers to be provided. One for a successfully returned status code (in the case of a POST, a 201 code) and another to handle error status codes. These functions can either be inline anonymous functions or references to functions. The example above uses inline anonymous functions.

Hopefully, reading this blog post will give you a better understanding of how to POST data using Angular.