Improving Angular experience with some convention magic
Disclaimer: I’m a line of business app developer - not a Web site developer. My view on things is colored by my experience with building large enterprise applications that has larger teams of of developers working together and needs to keep velocity and code quality at a very high standard through years of development.
I’ve been on a short assignment with a client and they wanted to establish ways for them to work with their Web development. They’re a .net shop with little experience in Web - only thick client technologies like WPF. They had very few requirements, but they wanted to go for things that are fairly established and had a guy that had done some AngularJS. For me it was the first time I did Angular in any structured way - previously I’ve just dabbled with it, basically with the intention of supporting it for Bifrost. The first thing that struck me with Angular is the explicitness of just about everything and how everything needs to be configured with code. Obviously, I’m not going to claim to be an expert in Angular, and I’d love to be corrected if I’m wrong. But from my little experience I started itching, and I had to scratch the itch.
Routes and conventions
In Angular, with the Angular Route extension, routing is one of the things you can do. A fairly simple and consistent API. One typically ends with a pattern as follows:
[code type=”javascript”] var application = angular.module(“MyApp”, [””, “ngRoute”]); application.config([“$routeProvider”], function($routeProvider) { $routeProvider.when(“/some/route”, { templateUrl: “/some/path/to/view.html”, controller: “MyController” }); }); application.controller(“MyController”, function() { /* Put your controller code here … */ }); ```
On one side one tells what to do when a route occurs - pointing it to a view and a controller that represents it. Then we need to configure the controller by its name and then point it to a function that represents the controller. My claim is that looking at your app, you either have formalized a pattern or you have a pattern by accident for how these things are put together. This is a great time to formalize it by creating something that represents it and can automate it as a convention.
For instance, you probably will see that for most parts of your app there is a relationship between the routes and where things are placed on disk. In my experience, routing is more often than not something the end users really don’t care about. I do have a feeling that we put too much thought and effort into something like this, while the end users will just copy / paste / click links and don’t care how they look. With this in mind and if there is more in reality a correlation between routes and disk location, we can automate this whole thing.
Directives Another aspect of Angular that is really useful are the directives, but again as with routes and controllers, one has to set this up very explicitly. This is something that could easily be automated. For instance, you could have a folder in your frontend project called Directives and every folder within it represents a directive by the folder name, within this a directive could then be represented by View.html for the view a Controller.js for the controller and a Link.js for the link part.
Proxy generation FTW Something we’ve had great success with from our Bifrost development is proxy generation. With backend code written in a different language than the frontend, its just great to augment the frontend with code generated to make the transition between the two less painful. But regardless of the divine of having 2 languages in your system, generating code for automation can really be a lifesaver. With a fixed convention, developers on your team gets less options. You might be arguing that is a bad thing, but I argue its a very good thing. If you’re the only one on your team or you’re two guys - you can probably cope with full flexibility. But applying a regime makes it easier to do things right - or according to the regime, at least. And that should be a good thing. Another benefit of defining regimes is that in some cases when automating things and generating code you get the opportunity for doing cross cutting concerns. With a regime in place for routing for instance and pointing it by convention to a controller that matches the view, you could inject a man in the middle controller that could do a lot of interesting cross cutting concerns, for instance logging, error handling, security or other more domain specific concerns.
Code please We are going to build support for Angular into Bifrost, and with it we will provide configurable conventions for routing and directives.
As part doing a Visual Studio 2015 Deep Dive for Microsoft recently I created a sample for Visual Studio 2015 showing off how to do all this, but now just using JavaScript and the new Grunt and NodeJS support coming with Visual Studio 2015. You can find the entire sample that uses SignalR, Karma, Jasmine over at GitHub here.