Matt Briggs

"Not all code needs to be a factory, some of it can just be origami" -why, the lucky stiff

The Rails Value Proposition No Longer Adds Up

| Comments

In 2005, Ruby on Rails was a breath of fresh air, and brought a revolution in how we build applications on the web. It had cutting edge ideas, and real solutions to the problems people were facing at the time. That was 8 years ago. If rails were to launch in todays world, would anyone even notice?

What makes rails amazing

In 2005, most people making (serious) web applications were doing it using Java and struts. Rails changed that, and it did that by being amazing.

  • Convention over configuration. Instead of spending your first weeks building structure, configuring infrastructure, and arguing about how to architect your application, you have a fully functional stack ready to go in seconds.
  • Great HTML generation. Rails has “AJAX” out of the box, without having to build reams of nasty javascript yourself. It also has form helpers, which make HTML make a bit more sense. It uses the philosophy of paving over the rough parts of web technology when it is possible, giving you more understandable and consistent mental models to work with.
  • Rails ships with a test suite built in, and ways to test every layer of the application.
  • Rails lets you quickly generate a scaffolding to give you a functional base to start iterating on in seconds.
  • Rails has plugins for pretty much all problems you will ever run into with web development.
  • Rails uses Ruby, which is a beautiful OO language, FAR more powerful than Java.

This is a pretty impressive list, many of these features were down right revolutionary when they came out. The only serious downside, is that rails is slow as a dog and eats ram like potato chips. But hey, what is more expensive, building new features, or adding server hardware? Adding more servers is a great problem to have, it means you have a lot of clients giving you money who need service. Rails and ruby are Fast Enough.

Node.JS… the first cracks

In 2005, AJAX was a brave new world. “Smartphone” still meant either Blackberry, or Windows Mobile 6. By 2008, things were starting to change. “Normal” people were interacting with online services constantly throughout the day, no matter where they were.

Node arrived with a bang. It had the right capabilities at the right time.

  • Node is simple, and allows you to expose blocking services to the web extremely easily.
  • Node is fast, and non-blocking, allowing you to leverage some of the more interesting features available in modern browsers.
  • Node is written in JavaScript, not as well designed a language as ruby, but faster to build things with than Java, and known well by a large percentage of web developers. JavaScript is asynchronous at its core, and cheap asynchrony is what enables us to build the type of things we are building today.

You could still make an argument for rails, in that it was a very good framework, while node takes more of a routing library approach to building web applications. But even with rails maintaining a lot of relevance, there was quite a big “brain drain” from the rails world to the node world.

Go and Clojure, where we are today.

We are steadily approaching 2015, and the world of web application development is continuing the steady shift that has been happen for the last 7 years. Even though JavaScript allows for fast and easy asynchrony, being limited to the reactor pattern can make certain types of problems quite challenging. JavaScript isn’t the greatest language at building large apps, and things like visibility, tuning, and stability are forcing people to look for alternatives. The folks at the cutting edge of the field are starting to move to alternatives, and are finding them in one of two places — Google’s golang, and Clojure, a lisp dialect for the JVM.

Both of these are incredible languages for many reasons, two key things they have in common is they are both exceptional at asynchronous programming, and they are both very, very fast.

Let’s revisit the value proposition of rails.

  • Convention over Configuration. It turns out the world hasn’t stood still. Smart defaults and sane conventions are the norm in web frameworks today. Java still kind of sucks, but Java 8 with the Play! framework is actually not that far behind the Ruby on Rails experience in developer productivity.
  • The only people still doing HTML generation for a new application nowadays are folks building web “sites” instead of web “apps”. And even there, a good front end developer will be frequently asking for APIs over templated HTML.
  • Testing has taken the world by storm. People don’t talk about if they test, they talk about how they test.
  • Maybe it is just folks I know, but experienced ruby developers tend to wince nowadays when opening a colossal Gemfile in a rails app for the first time. Each gem you add will change rails, sometimes in a quite unexpected way. Not only that, but many are poorly supported, and it is extremely rare to find one with documentation. (beyond a README and method signature stubs)
  • Ruby is no longer in competition with Java. It is in competition with other languages as productive and powerful, if not more so.

And what about our big downside of performance? It turns out performance is extremely, sometimes vitally important for us to build the services we are asked to build today.

What is so good about these other platforms?

It is awesome to be able to build an application that crunches reports, and give visibility into its data on demand. What is better is an application that tells you about things you care about before you even ask. Being able to push messages to your clients is an amazingly powerful thing, and it is available today, on mature, well tested platforms.

The other point is that performance really does matter in web development. A company who spends a fraction of the cost on hardware is going to have higher margins, and be able to buy more / better developers. When rails was so far beyond its competition in terms of productivity, that tradeoff was worth it. Nowadays, rails has serious competition in terms of easy of use and productivity, and that tradeoff is very hard to still justify.

It no longer adds up.

Rails is not a terrible framework, but its time has passed. There are a lot of folks with a heavy rails investment, it probably doesn’t make sense to move off of the platform for them, and they are the ones who will keep the eco-system moving. But for new development, I think rails should no longer be in the running. You are limiting the capabilities and future of your product, and not getting enough in return.

First Impressions: Using Clojure at Work

| Comments

TL;DR: I am a developer with a Java / C# / JavaScript / Rails background, and am building a small piece of infrastructure with Clojure at work. So far it has been a joy, and exceeded expectations.

I feel like I need to set the stage for this blog post. The first Clojure book I read was Stuart Sierra’s excellent Programming Clojure book back in 2009. At that point I had zero professional experience with functional, dynamic, or declarative styles of programming, and Clojure blew my mind. It fit well with how I like to think about programming, and shaped a lot of my ideals about the properties of good code.

Soon after, I left the C#/Java world behind, and worked at a company doing enterprise Ruby on Rails. Clojure helped me understand a lot of what ruby was trying to accomplish. It also paved the way to using emacs, and learning elisp. During this time, I also became a card-carrying member of Rich Hickey’s cult of personality. It is hard not to hero worship the guy, after listening to him talk about how he thinks about big problems, or how he defines simplicity, and advocates its usage. I think most of his talks should be mandatory for people practicing software development, they are just that good.

So this is not from the perspective of a total newcomer to Clojure. This is from the perspective of a developer who has used rails for years, and yearned to be working on the other side of the fence.

“But who wants to deal with all those parenthesis?”

This has been the mantra of the lisp hater for the last 50 years. Lisp doesn’t look like anything else out there, and has huge amount of parens as its primary form of syntax. This property may be off-putting at first, but it turns out that lisp parenthesis are a problem that has been solved pretty much completely. Once you get used to them and the tools which exist to interact with them, eventually you miss them when they are not there in other languages.

Only read the opening parens

There is a reason that people stack up all the closing parens at the end, because they are there for the lisp reader, and for your editor. Lisp strikes an amazing balance between being very terse, and being extremely explicit. Balanced parens are a big part of what allows for that.

Learn how to read code “inside out” at the same time as reading it “outside in”

I found this the biggest hurdle when learning lisp. Logically, code is structured outside in, but it will execute inside out. This is “normal” as programming languages go, what isn’t normal is that idiomatic Clojure is built using nested expressions — a declarative style of programming. Python comprehensions are a similar thing, you need to learn how to read it properly. Before you do that, its foreign gibberish. Afterwards, they become a great, concise way to express common code.

Use something capable of structural editing

Your choice of editor is extremely important here. What you want is something that will allow you to extend / retract the scope of an s-expression, add a new s-expression / merge the current one into its parent (depth editing), enforce paren balancing, allow you to select your current expression easily, split it apart / join it together, etc. If you have these capabilities (structured editing), then all those parens are a joy to work with. If you don’t have them, they will be the chore that they appear to be at first glance.

This may seem to be a pain at first, but proper tooling makes it a more joyful experience to work with parens then without them.

If you are looking for an IDE, cursive seems to be the best bet. If you are using emacs, its paredit or smartparens. If you are using vim, it is paredit.vim.

Using Clojure at work

There is a huge difference using something from a hobbyist point of view, and using it 8+ hours a day. Some of my challenges were

  • logging
  • wrapping my head around “interactive development”
  • common “new platform” issues (basic syntax / idioms that need to be fully grasped)

I am building a fairly simple application which watches the end of a queue, and perform actions on external resources based on the message. It is currently sitting at ~400loc, and is the sort of thing where if it breaks 1000loc it will be way overdue to be broken apart into smaller apps.

It is not that much output for the time I put into it, but it was my first time building something serious on the platform, as well as the first time I worked with AMQP.

Logging

Clojure inherits Java’s insanely complex logging legacy, and understanding what the hell is going on took me easily more then half a day. At first, there was no logging frameworks for Java, so IBM released log4j, which is incredibly powerful, and does pretty much everything you could want from a logging framework. Sun didn’t really like how everyone was using a vital piece of infrastructure like logging from IBM, so they built java.util.Logging, not quite as good, but built into the platform.

Since logging is something that things like libraries need to do quite frequently, this split become quite nightmarish. So people started using a logging abstraction frameworks, the most recent of which is slf4j.

Now, Java interop in Clojure is absolutely fantastic, and it is not uncommon to use Java libraries directly. So Clojure adds another layer to the onion — clojure.tools.logging, which is an abstraction layer over the java abstraction layers…

Long story short: if you are building a new project, what you want is clojure.tools.logging with slf4j and logback. This is the current “recommended stack”, and is incredibly powerful, if quite complex.

Interactive Development

Lisp developers practice something called “interactive development”, where they are constantly interacting with a running instance of their application. If you are a rails developer, you may be saying “no big deal, we have rails console!”. Imagine a console that is always attached to the development instance of your application, not as its own process. Now, imagine your editor could send it commands, like “run all the tests”, or “load changed code” or “reload application configuration”, and it would perform these tasks instantly. Imagine your editor could query the repl very quickly and efficiently for auto-completions and for symbol locations in the codebase. Imaging your editor could ask it for function documentation and method signatures. Imagine that the repl was embedded into your editor, living side by side with your code, always ready to give immediate feedback on the code you wrote or are debugging.

This is interactive development.

Modern IDEs approach this level of quality of life, but only for languages which are friendly to tooling. But they tend to lose a lot of their power, and sometimes downright lie when it comes to dynamic languages.

Interactive Development vs TDD

Clojure folks are known for their disdain of Test Driven Development. TDD comes at a high cost; writing, running, and maintaining a comprehensive test suite can become a substantial portion of the cost of building and maintaining an application. But that test suite gives you a benefit that makes it worthwhile, it allows you close to instant feedback on whether a change did what you thought it was going to do.

Getting that feedback is extremely difficult in Object Oriented languages. The reason for that is that most methods interact with state, so to reliably get feedback on a change, you need to get feedback on that function running against an object with as many variations of state it is likely to have.

By contrast, in clojure you usually have a lot of small functions that take inputs and return outputs, a few functions that perform side effects, and then “abstraction” functions which tie everything together and do something interesting. Because the pieces are much more granular, and state is treated as a dangerous property rather then tied into the most fundamental building blocks of the language, it turns out getting quick feedback on a function is typically incredibly simple.

Here is an example of interactive development of a small function which takes a clojure keyword and turns it into something ruby would expect from a hash key

1
2
3
4
5
6
7
8
user> (message/rubyify-keyword :hi-buddy)
::hi-buddy
:reloading (poops.message poops.message-test poops.core poops.core-test user)
user> (message/rubyify-keyword :hi-buddy)
":hi_buddy"
:reloading (poops.message poops.message-test poops.core poops.core-test user)
user> (message/rubyify-keyword :hi-buddy)
"hi_buddy"

that whole process took in the range of 5-10 seconds, which is FAR less then I would expect if I had test driven it. What I am missing from this is that if I want to test it in the future, I have to repeat what I wrote in the repl. But that is totally fine, this function has no dependancies (which unit tests suck at testing anyways if they live outside the class under test), and it either works or it doesn’t work.

This this is not to say that unit tests have no place in a clojure project, or that test driving code is something which is never useful on the platform — both still have their place. But the properties of the language design coupled with the incredible power you get from interactive development changes the value proposition of using these practices for the majority of code you write.

Unit Testing can still make sense in clojure

So where does unit testing still make sense? It’s very easy — listen to the code! In my opinion, the prime lesson of TDD is never make a change without getting feedback on it, the tighter that feedback cycle the better. If you find it starting to be a pain to get feedback through the REPL, write a test! This is what they are good at, taking the effort away and shrinking that feedback loop.

I am far from an expert, and my view on these things will probably change over time, but these are some examples of situations where the REPL probably wouldn’t cut it.

  • Functions which have a high number code paths without being “coordinators” (who should be end to end tested, not unit tested)
  • Functions which perform a calculation that depends on more then a single property of their arguments. Testing these would require multiple calls for every change, probably better to automate it.
  • Functions that deal with money calculations. I tend to pay attention to this type of code as much as I possibly can, because I am terrified of screwing it up.

This type of code should also be minimized, and isolated if at all possible. The ideal function takes an argument, and returns a value, it is good to keep to that ideal as much as possible.

Interactive Development vs Acceptance Testing

“Acceptance” testing is very different then Unit testing, but clojure has you covered here too. The user namespace is basically there to be decked out with functions and tools to make your life easier. In my case, I was dealing with inputs coming from a RabbitMQ queue, and outputs getting published to different queues.

Rabbit has a great feature that lets you create transient queues which disappear when the connection closes. I use those during development, and have a few helper functions which will test my whole code base.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(defn watch
  []
  (core/watch-for-assets system))

(defn publish-bad-message
  []
  (queue/publish (:print-assets-q system) {:fart "butt"}))

(defn publish-test-message
  ([]
     (publish-test-message 366))

  ([id]
     (queue/publish (:print-assets-q system)
                    {:id 1 :artwork_id id :device_id 2 :product_type "type"})))

Again, getting end to end feedback means typing (watch) followed by (publish-test-message) in my repl.

Unlike unit tests, this is most definitely not a scalable replacement. It will however take you surprisingly far.

Expected “Platform Issues”

Surprisingly, the switch from Object Oriented code to clojure was quite simple for me. You end up with similar separations of code, just the code isn’t attached to the data. So an object with functions maps easily to a namespace with functions which operate on similar (or the same) data-structures.

Most of my time dealing issues with working on clojure came down to not being comfortable with basic syntax and idioms. For example, there is no implicit do in a catch expression, anything after the first expression is treated as finally. Or slurp and spit only work with text, not binary data. You kind of expect this sort of thing going in, I feel in a few more weeks I wouldnt be hitting those roadblocks.

Using Langohr for RabbitMQ probably added some time, since it doesn’t try to hide AMQP behind layers of sugar. But at this point I feel pretty comfortable in my understanding of what is going on, so that was probably time well spent.

Overall impressions

I went into this extremely prepared, and very biased in favour of clojure. What I am working on will probably not be enough to hit the major pain points of using the language, so I am still in the “honeymoon” phase of using a new platform.

That being said, I have found the development experience to be absolutely delightful. I find in general, clojure libraries, and developers, seem to be very high quality. My big take away is how profoundly awesome interactive development can be. I am a big fan of testing, and have spent a large part of my career learning how to do it well. As someone with a huge investment in testing culture, I would call life without the constant need to write tests downright freeing.

How I Learned to Stop Worrying, and Love Dart

| Comments

Darts history is a little spotty, to put it lightly. When it came out, Google billed it as the JavaScript killer (which it’s not), followed by saying it’s not the JavaScript killer, it’s going to be the dominant mobile platform. Then it wasn’t about mobile, or replacing JS anymore, it was a compile-to-js language, and that would be its future.

As someone who tries hard to stay ahead of the curve when it comes to web technology, it was on my radar, but I wasn’t terribly interested. It is not exactly an exciting or super interesting language (like clojurescript or roy), and it seemed to have a questionable future — Google itself didn’t seem to know what it was good for. Finally, the JS interop seemed kind of “meh”, so using it pretty much meant giving up on the JS eco-system.

Fast forward a few years, and it’s situation is dramatically different. It managed to break 1.0, which is always a good sign for a language. Google is starting to push it quite a bit internally, which means it will have an investment in its continuing growth and improvement. There are hard plans for it to get into chrome. The dart2js compiler is approaching vanilla javascript speeds. And finally, you can build really cool web applications with it, as AngularDart is nearing 1.0.

I think at this point, there is a good chance that dart will be a “thing”. Dart killing JavaScript? That outcome is too far in the future to be predicted. But it doesn’t have to kill JavaScript to develop a viable community and infrastructure of its own.

Dart, The Language

The first thing to talk about is types. The dynamic revolution has happened, static types are definitely not “in”. However, what most people rail against in type systems is essentially the Java implementation. Dart takes a very different, more tasteful approach.

First, there is no runtime type checking. The type system is only there to catch a certain class of compile time errors for you, provide documentation, and give you the tools to express protocols and interfaces explicitly. If you don’t want to use static typing for something, you don’t have to. In fact, the official Dart style guide says type annotations should only be used in method / class signatures. What that means is that we are going from building out documentation like this

1
2
3
4
5
6
7
8
9
10
/**
 * @description
 * It foos the bar.
 *
 * @param {string} bin
 * @param {string[]} baz
 * @returns boolean
 */
function foobar(bin, baz){
}

to this

1
2
3
4
5
/**
 * It foos the bar
 */
bool foobar(String bin, String[] baz){
}

You are expressing the exact same information, only

  • it is easier to read
  • it is easier for your editor to parse
  • it will throw compile time errors for you when you do something dumb

I understand that people don’t want to code in Java anymore. I dig it, I don’t really like the Java language either. This isn’t Java, and by unilaterally panning anything with any form of static type checking, you are really doing yourself a disservice. Darts optional type system gives you another tool to help find bugs during dev mode, while maintaining the flexibility and readability of dynamic languages.

Classes and their Interfaces

Classes are pretty straight forward in Dart. The first thing I read about them that was interesting is the way constructors are handled.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Foobar {
  String foo; // class field

  // default constructor
  Foobar(){
    this.foo = "Something";
  }

  // named constructor which takes a string, and assigns it to the foo field
  Foobar.withValues(this.foo);
}

var foo = new Foobar(); // invokes the first constructor
var foo2 = new Foobar.withValues("hi!"); // invokes the second constructor

The this.foo assignment syntax is actually really, really cool. I do my best to keep complex logic out of constructors, so this style of constructor lets me move away from left_hand = right_hand style code. That kind of code is pure boilerplate, and can hide a surprising amount of bugs if there is enough of it.

Since Dart does not support overloading, multiple constructors could potentially be a problem. Dart solves this with named constructors, which actually solve the issue in an interesting way. You can have multiple constructors for different purposes, and actually give a name to why you have them.

One property that is really cool about Dart classes are that they have an implicit interface. So lets say we have a Vehicle class, which takes an Engine.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Vehicle {
  Engine engine;

  Vehicle(this.engine);
}

class Engine {
  start(){
      print("vroom!");
  }
}

var vehicle = new Vehicle(new Engine());

Later on, you want to be able to pass different types of engines into a vehicle. There are several different ways you can go, but implicit interfaces allow you to do a type of pattern that is very similar to duck typing in dynamic languages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Vehicle {
  Engine engine;

  Vehicle(this.engine);
}

class Engine {
  start(){
      print("vroom!");
  }
}

class RocketEngine implements Engine {
  start(){
      print("to the moon!");
  }
}

var vehicle = new Vehicle(new RocketEngine());

You can keep Engine as a basic, default implementation. By having RocketEngine implement Engine, it means that it can be used in places Engine can be used. This allows for a code structure that is very similar to what you would find in dynamic languages. The difference is that in Dart, if RocketEngine ever falls out of sync with the Engine interface, the type checker will let you know.

this and function, I will not miss you at all.

One of the most irritating things about the javascript syntax is that you end up typing this and function. You type them a lot. A hell of a lot. Often, multiple times per line.

In Dart, this becomes optional when referring to class / instance members. Most functions you write will be methods, when you are doing anonymous functions, you can use the () => syntax instead.

1
[1, 2, 3].map((n) => n * 2); //=> [2, 4, 6]

What is better then Angular? AngularDart, thats what.

AngularDart takes the good parts of angular, and cleans up some of the cruft. For example, there is a unified model for injectable components. So instead of having directives be a strange psudo-dsl, controllers be constructor functions, and services be functions that return objects, they are all implemented as classes. Each class has it’s angular specific functionality configured via class annotation.

Another key difference is that instead of element and attribute directives, directives are now explicitly encouraged only for attributes. If you want to implement an element, you probably want to use the new primitive of “Component”, which is implemented using web components and the shadow DOM.

AngularDart compared to AngularJS is a fairly involved topic, and I doubt I could do as good a job explaining as my friend Victor Savkin does here.

AngularDart brings a level of practicality to Dart. It is a modern, top tier framework for building web applications in a productive and maintainable fashion. Realistically, for Dart to start gaining traction in the mainstream, this was required. Now it is here.

Dart is here, and you should pay attention to it.

With ES6 coming down the pipe, many of the warts and problems with JavaScript will be addressed. However, many will not, as JavaScript needs to maintain backwards compatibility. However, that is not a cross that Dart has to bear, allowing for a very clean (albeit a bit boring) javascript-y language that will run in browsers. The benefits you see are in a much cleaner DOM API, promises used consistently for async, and an extensive, full featured standard library.

Dart is still not my favourite language in the world, but it is a good, consistent, clean language. Which is something we are sorely lacking in the world of the browser.

Code Organization in Angular

| Comments

The number one question I see over and over with programmers new to angular is “how do I organize my code?”. I think that this is because the way you organize sample code is completely different then simple code, which again, is totally different then a complex application, and those transitions are not self-evident.

Sample Code – aka One Big File

This is how you see most code on the internet

1
2
3
4
5
6
7
8
9
angular.module('foobar', []).

controller('MyCoolController', function(){
  // controller
}).

directive('evenCoolerDirective', function(){
 // directive
});

This makes a lot of sense when you are showing some sample code. But it will very quickly become unwieldy and difficult to work with if you are building anything even slightly complex. I would not recommend using this for anything you would check into source control.

Simple App – aka The Angular-Seed Method

The angular project published a sample “boilerplate” project called “angular-seed”, as a way to help developers new to angular get rolling without having to do a bunch of grunt work.

The way angular-seed organizes it’s files is by type. In a nutshell, it looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// in app.js
angular.module('app', ['app.directives', 'app.services', 'app.controllers', 'app.filters']);

// in app.directives.js
angular.module('app.directives', []).
directive('myDirective', function(){
// stuff
});

// in app.services.js
angular.module('app.services', []).
factory('myService', function(){
// stuff
});


// in app.controllers.js
angular.module('app.controllers', []).
directive('myController', function(){
// stuff
});


// in app.filters.js
angular.module('app.filters', []).
directive('myFilters', function(){
// stuff
});

This has the advantage of at least giving you some precision when trying to locate a given piece of code. It will also scale up well enough so that it is still usable by the time you finish building a simple application.

The problem here is what happens if you are not building a simple application? What happens if you have dozens of directives, and hundreds of controllers and services? At that point, 5 files won’t help much.

Splitting your application up into modules

This is widely considered to be the best way to organize non-trivial angular code. The idea is instead of thinking of your application as one giant thing, think of it as a number of small, independent modules that come together to form a giant application.

The benefit to structuring your code this way extends beyond being able to find things easily. People get into trouble when building large scale code bases by not thinking about dependancies. When everything in your app can “talk to” anything else in your app, those dependancies are everywhere. This means that even small, innocuous changes can impact things you couldn’t foresee, causing bugs. It also means when you want to re-design something, it is extremely difficult, because it means changing how it is used everywhere in the rest of your application.

This is a very large and complex topic, but as a general rule of thumb, thinking of your application as a group of small, self-contained modules with a limited API used to communicate with each other will go a long way towards the long term health and maintainability of your codebase.

Thankfully, angular has a module construct. Unfortunately, it is extremely primitive, and most of this “encapsulation” will have to exist in your own head.

When splitting your application apart this way, every module is given its own folder, which contains all the code required for that section of the codebase. These modules should be as small as possible, and should be as self contained as possible. It helps a lot with the containment if you use require.js.

Angular and Require.js

Do you even need require if you have angular? There is a lot of division on this topic, many people feel that since angular takes care of most application dependancy issues for you, that you can use a simpler build system and punt on require all together.

I think the real power in require (compared to other module loaders) comes from how you are divorcing dev-time file loading from production-time loading. Since angular has no story at all on file loading (only dependancy management), I think the need for that power is inevitable. You can embrace it immediately, or wait until you feel the pain, but hundreds of files coming down at the same time when the application loads will be brutal to develop against.

But beyond that, since there is no such thing as a module level injectable in angular (all dependancy injection draws from the same pool), it means if you want to have a module level model or service, it is impossible to control visibility. When you use require, you can have source level dependancies which are not published to the rest of the system, and use the angular dependancy injection for exposing an API.

This has worked great for me so far, with the sole exception that it is fairly common that I want to use $http for repository classes (would be the same issue if you wanted to use $resource). In these cases, I will pull that dependancy out of angular, and keep a reference in some sort of shared utility file (or base class). This can be done fairly easily

1
2
3
var injector = angular.injector(['ng']);
var http = injector.get('$http');
// .instanciate can also be used if you want it to "new" something for you

The main purpose of dependancy injection in angular is so that you can wire up UI code declaratively, while keeping everything easy to test. Since services like $http are on the edges of the system, I don’t think it is going against the spirit of the framework to pull them out. Hopefully, the angular team will add module level visibility in the future, and the whole issue will just go away.

Choosing what is right for your project

Since angular has taken such a hands off approach to the subject of code organization, there really is no “right” answer on what you should use. I have described some common (and less common) ways that people have found work for them, but it really comes down to a project by project choice.

Transclusion in Angular

| Comments

Transclusion is almost a gift to people criticizing Angular. It sounds incredibly complicated and computer-science-y. The spotty documentation around the topic and mysterious API only adds to the illusion of what a complicated concept this is. In practice, transclusion is a fairly simple concept, and one that is necessary if you are writing more advanced directives in angular.

In this post, when I talk about the “end user”, I am referring to the developer using the directive (not the user who uses the application).

So WTF does it mean anyways?

The wikipedia definition of transclusion is really pretty simple.

In computer science, transclusion is the inclusion of a document or part of a document into another document by reference.

So in the context of angular, transclusion would be the embedding of an end user template into the directive template, or the directive template into the end user template. To put it more simply, have a directive (with a template) that either wraps, or is wrapped by end user code.

Basic Transclusion

Basic transclusion is when you are simply wrapping end user code. Let’s say, for some reason, you are building a blog where each post needs to be programmed in (I know, kind of silly, but just work with me here :) The post would have meta information as attributes, and the content of the directive would become the post body.

There are two key pieces that make transclusion happen. First, transclude: true in the directive declaration tells angular we are performing transclusion.

The second piece is the presence of the ng-transclude directive in the post template. This tells angular where to embed the end user template.

Gotcha: Transclusion and scope

A big thing to keep in mind is that since this is the end users code, it requires the context of the scope tree, not the isolated scope of the directive. Because of that, transcluded content scope is not the child of the directive scope, it is instead a child of the directives parent scope, effectively making it like the directive scope does not exist in the inheritance chain.

transclude: element

transclude: true allows us to wrap a user’s template with our template. But what about when we want to wrap everything in a template? For example, we are building a directive that displays a panel under an input box. The easiest way to do this sort of positioning is when you have a wrapper to position against. Here is a quick example

If you look at the compiled DOM, you will see something like this

1
2
3
4
5
6
7
8
<div class="drop-panel is-active" type="text" drop-panel="">
  <span ng-transclude="">
      <input type="text" drop-panel="" class="ng-scope">
  </span>
  <div class="drop-panel-panel">
    This is some panel content
  </div>
</div>

transclude: element means that the entire element was transcluded into the ng-transclude placeholder (rather then just the elements children). replace: true allows us to define a new root node for the directive, so this is also necessary for wrapping to work.

Transclude linker function for ultimate power

transclude gives a lot of power, but what happens when you need total control over the transclusion process? This is very rare, but can be needed if you need to transclude the end users template multiple times, or need to choose where to transclude based on some kind of logic (maybe as part of compile). For these cases, angular provides the transclude linker function, which lets you do pretty much anything you want.

Let’s say you were building a directive which duplicated it’s content a specified amount of times. Each duplication will have access to an $index property on the scope, that will tell it what number it is in the list.

If you understand this, you understand the core of how ng-repeat works, which is one of the most complex directives that ships with angular.

For this one, since we aren’t defining a new root element, we don’t need replace: true. When replace is set to false (the default), and transclude: 'element' is set, what is actually inserted into the dom is a comment. The way this duplicate directive works is that each “duplication” is inserted after the previous one, and the first one is inserted after that comment.

You may also notice that priority is set very high. This is because we want our duplication to happen before any other directive gets applied.

Finally, since we are not using ng-transclude, we need to take care of what scope we want our duplication to link to. We do this by manually creating inherited scopes, and setting the $index property accordingly.

Keys to the City

Transclusion is considered an advanced topic, but as you can see, there is nothing to be scared of. Even at its most complex, as long as you understand how scope and linking works, transclusion is very easy to understand. This is what I believe to be one of the strengths in the design of angular, everything in the framework is built on top of a handful of core abstractions. If you have a good foundational understanding, advanced topics come very easily.

Scope in Angular

| Comments

Angular goes in a different direction then most other frameworks, by having the html you write drive the composition of UI components. This allows you to succinctly wire up components without boilerplate, but it also creates some issues. How do you share data? How to components get configured? How do components communicate with each other, or the outside world? The part of angular which answers these questions is scope.

What is scope?

The purpose of scope is to hold shared UI state of an element and it’s descendants. Since the UI is defined as a tree of nodes, the scope of an element is visible to all descendants of that element. When a descendant introduces a new scope, the new scope inherits properties of it’s parent scope.

This is a very elegant solution to the problem, since the further you go down the DOM tree, the more specific the data requirements get.

As an example, here is an extremely basic employee directory, which allows people to add contacts to their personal directories.

There is 3 levels of scope in play here. The first is the root scope, which is defined automatically by the angular bootstrapping process. The second is the directory level, which is created by ng-controller. The third level is the employee elements, which are created by ng-repeat.

Each level inherits from the previous level as illustrated here

scope tree

This inheritance is very important, as you can see with what is happening with the “add to my directory” button. currentUser being on the root scope means it is available to all child scopes, so even though most of what needs to happen at the employee scope level is satisfied with the employee object, it is still able to see currentUser if needed.

ZOMG global state!

This may be a bit terrifying, especially for JavaScript developers. The difference between this and global state is that the scope tree is directly linked to the DOM tree.

If two different nodes share a parent, usually there is a reason, and if you put state on that parent node, usually it is very applicable to both children. Those children don’t make much sense without the parent, so it becomes unlikely they will be accidentally separated.

As long as you keep your state as localized as possible, having state inheritance is a very elegant solution to the very tricky problem of sharing data.

That being said, if you publish everything on $rootScope, yes that is global state, and yes, that is bad. Don’t do that.

Using scope in directives

Using scope is pretty straight forward when using things like ng-controller and ng-bind. But how about a directive which interacts with the scope?

Here is a directive which exposes a number from the scope, and whether or not the number is even or odd.

The way angular achieves its data binding, is by constantly checking values on scopes to see if they have changed. This is accomplished by scope.$watch. Angular will automatically create $watch expressions for any data binding you give it, but you can also add custom ones. Every time angular thinks something may have changed, it will call the $digest method on the appropriate scopes, which cycles through watch expressions looking for changes. If an expression is found to have changed, angular will execute whatever the callback is.

Another interesting thing here is the $parse service. $parse is the way angular translates expressions (the things inside {{}}) into javascript. Angular will automatically wrap an expression passed into scope.$watch as a string, but since we are going to assign a value to the same expression, it makes more sense to wrap it ourselves.

Most of the rest of the link function is around synchronizing the value of number from the outer scope to the inner scope. The reason for that is that this directive has a template which requires the number to be passed into it (via ng-model). Because of that, we need a fixed, known value for the scope.

Isolate scope

Now, what we have here works, but there is quite a bit of “manual lifting” going on. It would be nice if the framework could handle that two way scope synchronization for you, wouldn’t it? Well it can, using a feature called isolate scope.

Normally, scopes will inherit from their parent. But in the case of directives, this can be undesired. A directive is a generic piece of functionality, and the scope is full of application and context specific values. Isolate scope allows a directive to create a “scope sandbox”, cutting it off from the rest of the scope tree, except for specific values. Here is the previous example re-done using isolate scope.

It looks a lot nicer without the synchronization code. That is because we moved that into the scope part of the directive declaration.

The way that the scope property works is the key is name you want to publish on the local scope, the value is a symbol that signifies how the local scope and the outer scope values will get linked.

  • = two way synchronization, by far the most common. This will link an outer scope property to an inner scope property, where the outer scope property is specified by what is in the attribute being referenced.
  • @ one way, this will copy the literal value from the attribute into the isolated scope. If the attribute value changes, the isolated scope property will be updated to reflect the change, but if the isolated property changes it doesn’t get copied to the attribute.
  • & will wrap the expression in a function, which can then be called as needed. If the expression is a function, you can inject arguments into it by passing a context object at the point of invocation. This may not make much sense, but see the next plunk for an example.

so for example, scope: { foo: '=' } means “Isolate scope for this directive, and set up two way synchronization between a property on the local scope called foo, and whatever expression was entered into the property foo on this directives element”.

Often, it is fine to use the same name as the attribute, but if you want to use something different, you can name the key whatever you like, and put the attribute name after the symbol. So scope: { foo: '=bar' } would be synching between the expression in the attribute called bar, and the isolated scope property foo.

Here is an example of all 3 types of isolate scope declarations

Why would you ever not want to isolate scope in a directive?

The only reason you don’t isolate all directives is that there can only be one scope per element, so only one directive per element can ask for scope isolation.

In practice, this isn’t as limiting as you would expect. Usually there is at most one directive per element which requires complex integration into the rest of the ui state. If there are other directives, they tend to just do things like configure 3rd party libraries.

Unfortunately, you should only use this feature if you really need it. If you are writing library code, you should go to even greater lengths to avoid it, since it can potentially restrict situations where the directive can be used.

This is one of the things I find frustrating about the framework, the properties of isolate scope are so incredibly useful when writing directives, they really should be always available (in my opinion).

A few words of warning

Scope enables most of the aspects that have made angular the most popular JavaScript framework today. But there are some gotchas that are good to be aware of

Beware complex $watch expressions

Angular takes a brute force approach to dirty checking (until ES6 anyways), which means that your watch expression can be run many, many times. Slow $watchs are the most common source of performance problems in angular apps.

If there isn’t a “.” in your binding expression, you are doing something wrong

This is obvious if you understand how inheritance works, but comes up surprisingly often in issues by newbies. If you read from a property that is on ancestor scope, there is no problem. But if you write to a property on an ancestor scope, you will just end up adding the property to your local scope. By publishing objects on the scope instead of values, JavaScript will first have to find the object before writing, bypassing the problem.

Here is an example of the problem

In general, just stick with the rule of thumb that binding expressions always need a dot in them.

Think carefully before publishing on $rootScope

It is a quick way to make something globally accessible, but there are several tradeoffs.

  • It will make it hard to change in the future, since it is not apparent what is using the variable (since any view code could potentially be using it)
  • You are increasing the chance of a name collision. If something further down the page uses the same name, you could introduce a very subtle bug.
  • When properties are referenced on the $rootScope, it is not terribly clear where they come from.

There is a time and place for $rootScope, but publishing to it should be done with thought and care.

Debugging

The Angular Batarang is an incredibly helpful tool for exploring the current state of the scope on an element. It should be the first thing you reach for when scope isn’t behaving the way you think it should

Understanding Angular Directives

| Comments

Angular is the hottest JavaScript framework out there right now, and for good reason. It is a very powerful, flexible, and well designed framework for building web applications. However, like many projects, one of its major weaknesses is both the quantity, and quality, of its documentation. Because of that, Angular can be exceptionally difficult to learn.

Thankfully, a lot of Angular is pretty straightforward once you have a basic understanding of the concepts and some of the pitfalls. However, there is one topic that is definitely not straight forward at all, and is essential for any non trivial Angular work. That is directives.

This blog post is written with the assumption that you know basic Angular knowledge (things like ng-if, what a service is, what scope is). Also, when I talk about HTML, I am referring to the markup language, when I talk about the DOM, I am referring to an active, living tree of UI elements that is running in a browser.

What is a directive?

The tagline of Angular is “Teach HTML New Tricks”, and directives are the mechanism you use to make that happen. I would even go so far as to say that directives are Angular, the rest of the framework (with very few exceptions) is there to support the usage of directives.

In a more practical sense, directives are HTML artifacts which handle all DOM manipulation and interaction. This can be everything from jQuery style “DOM enhancement” code, to HTML control flow (like ng-if or ng-switch), to data binding (ng-bind / ng-model). Unfortunately, with that power and flexibility comes a substantial amount of complexity.

Comparisons to Backbone Views

The idea of a directive sort of lines up with a Backbone view, in that it is the place that you put code that interacts with the DOM.

A key difference, is that a Backbone view usually has a one to one relationship with a DOM element. In the case of Angular, it is quite common for multiple directives to be attached to the same DOM element.

Another difference is that in Backbone, there is a substantial amount of code required to wire together, views, the DOM, and the models/collections. In Angular, the wiring up is done by the framework, according to HTML annotations and dependancy injection.

This dramatically reduces the amount of code required to build a complex view. When people talk about writing less code in Angular, the majority of it comes from the lack of this code, which is pure boilerplate 90%+ of the time. However, it also means less flexibility in how to coordinate interactions between components. This is a double edged sword, having a single, well understood way of doing things makes the code easier to understand, but when you are doing something that pushes the framework, it means you have less tools at your disposal.

Simple directives

Let’s look at what goes into building a simple directive. This directive will make an alert box pop up when you click on an element, which will say “Hello, world!”. If a name is provided when applying the directive, it will use that instead of “world”.

It is important to note that Angular will translate the name myGreeting which is properly cased JavaScript, into dashed case my-greeting, which is proper for html/css.

The first thing to look at is restrict, which determines how your directive will be used. This can be a combination of the following codes

  • A: restrict to attributes. <input type="text" my-greeting/>
  • E: restrict to elements. <my-greeting></my-greeting>
  • C: restrict to class. <button class="my-greeting">Greet!</button>
  • M: restrict to comment. <!-- directive: my-greeting -->

Now four choices in how to apply directives may seem to be a lot. In reality, it is considered to be a best practice to use the first two, since comments and classes are there for edge cases which very rarely occur. Typically, you will have more attribute directives then elements, since those are easier to compose.

link function

The next thing we will look at is the link function. To understand why it is named link only becomes clear after understanding the directive life cycle, but for now, think of it as the place where you put your DOM manipulation code.

You can see that we have three arguments being passed in — scope, element, and attrs (there are an additional two arguments which can be used, but they are for more advanced situations, which we will explore in future posts).

  • scope is the current scope of the element. It is hard to list all the ways a scope reference can be used in Angular. But in the context of directives, the core use case is to translate what is in the DOM into JavaScript properties, and apply DOM changes based on JavaScript properties. The best way to think of scope is the glue between the world of the view (HTML) and the world of the rest of your application (JavaScript).

  • element is the DOM node on which the directive is applied, wrapped in jQuery. You can do anything to it that you would otherwise be able to do with jQuery. A good rule of thumb is that a directive should only ever really be modifying its own element. I would consider it a very strong code smell if a directive was doing DOM traversal to change other elements, or even worse, looking up other parts of the DOM by id or css.

  • attrs is an instance of ng.Attributes. This is primarily useful for reading the properties of other attributes on element. It can also be used to react to an attribute changing (attrs.$observe), or to set a value on an attribute (attrs.$set). A nice property of attrs is that it will do the same casing normalization as what happens with directives — so if you were looking up the value of my-attr="foo" on an element, you would do it by checking attrs.myAttr.

The Angular directive lifecycle

If you have made it this far, you already understand how to use a directive in a simple fashion. However, to fully understand directives, you have to understand how Angular uses them.

When you start your Angular application, you provide two pieces of information to the framework: A top level module, and a root element. The module is loaded, so that its dependancies can be registered for injections. The DOM node then gets passed to the $compile service for compilation.

$compile walks the DOM tree, looking for nodes which have directives it knows about. Once it has this list built, it begins processing each one in turn.

To compile a node, Angular needs to know how to combine the world of HTML (the DOM node) with the world of Angular. When you provide a link function in a directive definition, you are telling Angular how to accomplish that task — how to link the two worlds together. This is also the point at which directive templates are compiled and inlined into the DOM.

Angular gets these linking functions by calling the compile function on each directive, in order of priority. compile defaults to whatever function is provided by the link property of the directive definition, if present. These linking functions are then combined into a composite linking function for that element.

Once all the linking functions are gathered, Angular will start linking from the bottom of the tree going up.

compile vs link

So that begs the question, when should you use compile, and when should you use link?

The easy answer is that you should just use link, unless you need to do something (like manipulate the child DOM nodes) before the linking process starts. Since compile happens before the scope really comes into play, its uses are dramatically limited to cases where you need control over the DOM template rather then the fully realized directive. If you are in a case where you do need compile, you must return your own linking function, since the link property of the directive definition will be ignored.

Putting it all together

Let’s take the classic FizzBuzz interview question, and modify it to be about directives.

Write a directive that will be applied to an element with children, each containing a number. The directive will then modify the child elements to apply a directive. When the child element contains a number divisible by 3, apply a fizz directive. When the number is divisible by 5, apply a buzz directive. When it is divisible by both 3 and 5, apply a fizz-buzz directive.

Each of those directives will change the element to display the appropriate text (‘Fizz’, ‘Buzz’, or ‘FizzBuzz’), and increment a counter on the page.

Directives are one of the most complex parts of Angular, but hopefully this post gives you a good foundation to build your knowledge on. There are more advanced properties and techniques available, but using what was described here will take you very far.

Sometimes, It’s OK to Leave a Mess

| Comments

Recently…

we watched the excellent lunch and learn video from Hashrocket, where Sandi Metz talks about test design. While the whole video is worth watching, one thing that stood out to me was her term “Omega Mess”.

The first time I heard someone refer to this concept was pairing with Victor Savkin, where he referred to parts of the code as his “Dirty little secrets”. While this is still my favourite name for the concept, I think Sandi’s name of Omega Mess, meaning a mess that is at the end of everything, is far more apt, so I have used it ever since.

The Boyscout Rule

Uncle Bob tells us that as professional software developers, we need to practice the Boyscout Rule, meaning always leave things in a cleaner state then when you arrive.

Imagine you are a developer, and you pick up a support task to fix a corner case bug in some crazy calculation. Now, this calculation is in a part of the application which is the stuff of legend on your team. It consists of a few thousand lines of code spread across a dozen different files with methods that have cyclomatic complexities reaching the levels of the national debt. You make a cup of coffee, put on some high energy music, and dig in.

Several hours later, you are pretty sure you understand the problem, and the interactions in code around that problem. You write a unit test to expose the issue, and go about fixing it. All you really need to do is add another if (in code already indented twelve levels deep), so you do it, the tests go green, and you breath a sigh of relief.

The Choice

It is at this point the boyscout rule comes into play. You have a choice; close the task, go to a bar, and drink until you no longer remember the pain of the day, OR, using the understanding you have gained over your long day of work, try do something that will make this horror slightly less horrific.

The programmer that believes the bar is the better option is putting his short term pain ahead of the long term maintainability of the application. They will say, “I already wasted a whole day on this BS, time to move on to something new so that I can be productive!”

The wise programmer knows that typing keys is not the only measure of productivity, and by not utilizing the knowledge gained to chip away at the vital task of improving the maintainability of this core part of the application, they are basically wasting a hard days worth of work, and not moving forward on a task which could one day become so important that the business dies because of it.

The Omega Mess

That cautionary tale may seem like I am overly stating the importance of constant refactoring, but software shops fail all the time because they don’t do it.

Sometimes, the costs don’t work out. Sometimes, it isn’t worth putting in the time to clean things up. Those cases are when you are faced with code which a) basically works, and b) has a very low probability of change. Code that fits this profile is always at the end of a chain of method calls which is why “Omega Mess” is such a great name; it is a mess at the end of all the things.

One day you will probably want to clean it up when you have the free time, but there is also a pretty good chance that the only reason this code will ever change is because it is being re-written. If you are working on a large enough app, this is a relatively common occurrence. In this situation, being a good boyscout is a bad thing; you are wasting your company’s time for very little benefit, and you are introducing the possibility of regressions for very little reason.

How to determine probability of change

This is really an experiential thing, but I would recommend asking yourself the following three questions

Is this code stable? Some code gets written once, and then stays the same for years. While other code gets touched every few weeks or months. An omega mess is something that doesn’t change much.

Does this code touch other code? If your code is executing other code, there is now two possible reasons for this code to change. If the code it calls invokes other code, this can be an exponential thing. If code is not at the “end of the line”, chances are, it is not an Omega Mess.

How many places is this code called from? An Omega Mess sits at the periphery of the system. If this code is called from 100 places in your application, it is important and needs to be fixed.

Data-attributes Are an Anti-pattern

| Comments

HTML5 has a lot of cool things in it, but the one thing I wish I could remove are data-attributes, because of the crimes against clean front-end code that it seems to encourage.

What is this clean web code you speak of?

We have 3 technologies that go into building a web app, HTML, CSS, and JavaScript. All three operate on an abstract concept called the DOM, in their own ways.

  • css
    This is the language we use to declaratively set the visual properties of our UI. It consists of a path matching syntax, and a series of rules. Clean css is a) readable, b) doesn’t repeat itself too much, and c) is modular (i.e. you shouldn’t have styles intended for one thing leak into another thing) CSS is very hard (and frustrating) to learn, and even harder to write well.

  • javascript
    This is the language we use to specify the behaviour of our application. Up until the last 2 years there wasn’t a lot of guidance on how to do this properly, but nowadays there is a tonne. Clean javascript is worthy of a book rather then a half paragraph, but for the purpose of this blog post, clean javascript is keeping your behaviour in javascript and your javascript out of the html. Also, that your DOM centric code should be segregated from the more abstract code.

  • html
    Html is the language we use to form the base structure of the DOM. Many people confuse HTML with being the DOM, but that usually comes from not much javascript experience. The HTML should be expressing the structure of your interface in a very abstract way. For example, if you have a navigation sidebar, it may look something like this

1
2
3
4
5
6
7
8
9
<nav>
  <header>Pages</header>
  <ul>
    <li><a href="foo.html">foo</a></li>
    <li><a href="foo.html">foo</a></li>
    <li><a href="foo.html">foo</a></li>
    <li><a href="foo.html">foo</a></li>
  </ul>
</nav>

There is nothing talking about whether this sits at the left, right, or bottom of the page. There is nothing that talks about how the links should be pjaxing the main content div of the app. All it describes is a navigation widget at a very high level.

  • the DOM
    This is where all of those things come together. The DOM is the in memory representation of your UI. It has event handlers bound to elements, it has styles, and it changes dynamically. When you hit view source in your browser, you are looking at the html. When you open the web inspector, you are looking at the DOM (made to look html, due to how confused people are about these things).

The role of data attributes

Data attributes are a new way of serializing information into a DOM node about what it represents, so that you are not forced to use the class attribute improperly. For example, a blog post could look like this

1
2
<article class='video' data-publish-date="2012-08-10">
</article>

We are using an article tag to represent the post, its class tells us what type of post it is (a video), and the data attribute is used to tell us something about it. This seems pretty obvious to me, class is for type of thing being represented, data is for that things data.

Now, with the rails 3 javascript helpers, to send some data to the server via AJAX, you do something like this

1
2
3
4
5
6
<form action="/posts" method="POST" data-remote="true" data-confirm="are you sure you want to post this?">
  <input type="text" name="[post]title" />
  <textarea name="[post]body"></textarea>

  <input type="submit" data-disable-with="Loading…" />
</form>

Now, this looks like a very elegant solution to a common problem. But it’s not really using data attributes the way they are intended to be used.

First we have the data-remote="true". Why would you use a data attribute for something that obviously should be a class? data-disable-with and data-confirm are even worse, since they have a) nothing to do with data, and b) have no business being in the HTML.

Why does it matter that rails co-opts data attributes?

In the small scale, it really doesn’t matter at all. More then that, it works very well. You can make arguments about purity and aesthetics, but at the end of the day, we are co-opting technology that was intended to model papers and blog posts, and using it to build applications. Rails as a whole is meant to build things like base camp, which is the smaller end of mid-sized application, so if you are building that kind of app then they will serve you well (just like the rest of the default rails stack).

If you are building highly dynamic apps, or larger scale apps, things start to break down. When people are taught by rails that data attributes are a way to configure javascript libraries, you end up with stuff like this

1
<%= text_field_tag "text_field_import_scenario_#{scenario.id}", "", :style => "width:346px;", :size => 24, :'data-autocomplete-path' => search_scenarios_quote_scenario_path(scenario.quote, scenario), :'data-autocomplete-raw-html' => true, :'data-autocomplete-send-form' => true, :'data-autocomplete-select' => "$j('#import_error_message').html('');$j('#text_field_import_scenario_#{scenario.id}').val(ui.item.name); $j('#object_id_#{scenario.id}').val(ui.item.value);", :'data-autocomplete-after-update-bad' => "$j('#import_link_#{scenario.id}').show(); resizePopup('import_pop_up_#{scenario.id}');" %>

or completely baffling things, like this

1
data-print-action="check_sku:selected_skus:Item"

One reason we strive for clean code is because it is easy to read. Since HTML is already a very verbose language, this becomes more important. Keeping things simple and focused is the heart of clean HTML, and the previous two examples are almost the antitheses of that. After 10 years we have finally gotten people to stop using inline styles, and the rails community is replacing that with something much worse to maintainable html, inline behaviour.

Ok fine, rails is doing it wrong, but there are still valid use cases, right?

The valid use case for data attributes are when you are doing relatively simple front end work, and jQuerying your way to victory. The javascript community has found that jQuerys DOM centric approach to code structure is a nightmare passed small scale, but if you are in the jQuery sweet spot, then you are also in the data-attribute sweet spot.

If you are doing more complex behaviours and interactions, making the DOM the source of truth is a bad idea. Your source of truth should be objects that wrap data structures and handle synching those data structures to a server. Beyond that, most of your UI will be rendered by javascript anyways, so you duplicating information that will not stay in synch.

TL;DR;

Data attributes are data, not javascript configuration. The rails way of using them works well in trivial cases, but gets exponentially worse the more complex your use cases get.

Mixins Are Not Always a Refactoring Anti-pattern

| Comments

Steve Klabnik just posted an interesting post about mixins. Steve is a really smart guy, and I usually agree with him, but I think his justification is a little bit weak in this case.

Mixin Refactoring through Class Gutting

Oh man, he is so right that this is an anti-pattern. It happens a lot in ruby, someone says “Hey, this thing is doing too much. The only method of code reuse I really believe in is mixins, so I’ll just take the implementation, and dump it into a mixin.”

By doing that, you haven’t decreased complexity, you have actually increased it by breaking locality. Steve introduces the idea of reducing complexity through ecapsulation (right on), and talks about Data Mapper and Repository. Very OOP, and great solutions, especially in larger systems. Still diggin what Steve has to say.

Method Count as a metric of complexity

Here is where we part ways. Lets take the Enumerable module in the ruby standard library. It adds 94 methods on to a given thing, with the requirement that that “thing” provides an each method.

But enumerable is an “idea”, and if something is enumerable, you sort of know how to work with it — through those 94 methods.

Steve talks about how encapsulation reduces complexity of the implementation, well Enumerable encapsulates the “idea” of enumerating. So that means that when providing a public interface, a data structure can focus on its fairly simple implementation, and only provide the most low level and simplist of methods (each), while bringing in Enumerable and let it do the heavy lifting to give the rich interface that people expect from a ruby data structure.

How is that increasing complexity? When I look at Enumerable, it is talking about a single concept. When I look at array, it is talking about a single concept. The only thing I can change to break the implicit protocol between the two is to break the each method at a fundamental level.

Composition would have been a terrible choice here, I think providing 94 stub methods and an internal enumerator object would just increase the complexity, not reduce it. Providing an enumerator as an external thing would have made the api much more of a pain to work with. Inheritance would be better then composition or separation, but the problem is that Array is a datastructure, it is not an “Enumerable”. Enumeration is an ability, not the root of a concept. I think the best choice here is mixin, and that it is fairly obviously the best choice. And I think most people who have implemented data structures in ruby would agree.

So what we have is something that is close to inheritance, but more of a “vertical slice” of functionality. An “ability” rather then a “thing”. This is what mixins give up, the ability to model “abilities” in a concise way.

What is complexity

Rich Hickey defines complexity as an interleaving of ideas. I think that is a great definition. In the case of Enumerable, you are providing significant functionality through providing a simple implementation, the only interleaving is that each method. Sure, the runtime method count is 94 methods higher, but who cares? When you are calling methods on array, you are thinking of it as a single thing. When you are maintaining array, you don’t have to worry about any interations with enumerable outside of each.

I think that the amount, and shape, of a mixins interaction with its containing class is a good measure of complexity. The amount and shape of a classes interactions with the internals of a mixin is a great metric of complexity. The only thing the number of runtime methods is telling you is that maybe you should be looking at those other things, which isn’t that great a smell.

The important thing here is interactions.

Large classes often become complex. But it isn’t a property of their runtime method count, or even inherant to their lines of code. It is because large classes and large methods tend to interact in ways that are hard to understand. Small classes can get complex too for the same reasons, but the larger the class, the easier it is to get to that place.

Why “Gut the class and dump” it into a mixin doesn’t work

It doesn’t work because you haven’t tackled the complexity of the interactions in the code. Maybe it needs to get pulled into another class, maybe methods need to get merged together. Or maybe you are just talking about an inherantly complex thing, and doing the earlier things will make it worse. In any case it is not the runtime method count that will tell you this, it is analysis of how the class interacts with itself and others.

Complexity Smells

Steve wasn’t writing about complexity smells in a general way, but since I have spent so much time talking about what isn’t a smell, I sort of feel compelled to talk about what is. I am sure he would agree with most, if not all of the following

  • When a mixin mucks with class internals.
  • When a mixin mucks with other mixins.
  • When you read the inheritor of a class, and can’t understand it without reading its parent
  • When you read an inherited class, but can’t understand it without its children
  • When there are so many interactions with other things that you have to read many classes to understand how a single thing works
  • When classes do too many things
  • When classes have too many dependancies
  • When classes are aware of too many other objects
  • When too many other objects are aware of a class

And that is just the tip of the iceburg. I would say that a significant percentage of our job is managing complexity in code, it is a huge and nuanced topic. Mixins are also not a simple thing, and are extremely easy to use in the wrong ways.