Falling Into the Pit of Success with Web Components

Being able to build components (AKA “directives” if you’re in the Angular camp) has changed the way we structure web applications on the front end. This is a big move forward and provides a lot of power in addition to some much needed encapsulation.

However, even with the drastically improved tools we have at our disposal for building client side applications, I still see projects going down the wrong path. Code is tightly coupled and maintenance quickly becomes an issue.

The best way I’ve found to mitigate this is to separate concerns as much as possible. I’m going to say that again just because I think it’s that important: separate concerns of your components as much as possible.

We all start out having our components do too much, myself included. It’s hard to get into the habit, but our goal should be to make components as small and dumb as possible. This ties right in with other software development best practices like DRY and SRP, but it’s not something I see people doing a lot in client side applications.

Here are two big revelations I had about developing components that have made my life a lot easier, along with a an example from a recent project where I broke apart a component that was doing too much.

Pass In Your Data

When I started building components I often made them responsible for managing their own data. After they were instantiated, they would be responsible for making API calls to fetch and manipulate their data. This works for a while, but becomes difficult to maintain over time.

Passing data in to a component provides a lot of the same wins as dependency injection. It allows your components to be very small and focused which makes them easier to maintain and test.

This can be accomplished by creating containers, also components, that are solely responsible for managing data injecting it into their children. I’ve also done this by instantiating data through a router and exposing that to the view where the components are rendered.

If you’re coming from a framework like Angular, I’m not just talking about separating things from directives and controllers, either. It will be tempting to just toss some additional logic into your controller for managing data, but this should actually be injected into the component’s controller, so it needs to come from another source.

The main goal here is to make our components as dumb as possible so they become more reusable, testable and maintainable.

There’s No Such Thing As A Component That’s Too Small

At first it’s going to feel weird to break things down into smaller and smaller pieces. It’s common to think that it isn’t worth the overhead of creating a new component when evaluating where you might be able to break things apart. However, this is where you are able to set yourself up for success.

Let’s take a look at an example from a recent project I was working on. We had some widgets that stood alone as individual components.

Widget preview

We had a single controller and view backing this entire widget. It worked fine for a couple weeks, until we had requests to see this same data represented in similar but different forms throughout our app.

It was hard to decide whether to write a new component or try to modify the design to make our existing components fit. Neither of these options were ideal. In the end, this widget was broken out into 7 different components and composed of 10 total. I’ve annotated another screenshot to show the breakdown.

Annotated widget

We ended up breaking things out into a bunch of pieces that are very easy to maintain and test individually. Now we have all the building blocks we need to develop other complex interfaces with these same components. Another big win here is that we are passing all of our data in to the components so they can just worry about rendering. The data comes from the top level component, which is not annotated in the screenshot since it just handles data.

Conclusion

Breaking things down into small pieces that have a single responsibility is always a win. The story is no different for web components. Don’t forget, managing data is a responsibility.

If you have other techniques for writing maintainable components, please share them in the comments.

Angular Directive Testing Best Practices

Getting in the habit of testing is hard, but I’ve found that a big turning point for me when I start testing in new languages and tools is to identify patterns in how tests are written. Once I know a pattern for testing something, it’s easier to walk through each step to write my tests. Just like anything else, it’s more approachable when you break it apart into smaller pieces.

When testing directives, this is the main pattern I see:

  1. Mock
  2. Compile
  3. Interact
  4. Assert

An Example Directive

I’m going to walk through each step in the directive testing pattern for a directive I wrote recently. Here is the source of the radioButton directive, which provides a way to use custom style and markup for a radio form control.

angular
  .module('kit.forms', [])
  .directive('radioButton', radioButtonDirective);

function radioButtonDirective() {
  return {
    require: '?ngModel',
    link: function(scope, element, attributes, ngModelCtrl) {
      element.addClass('button');

      ngModelCtrl.$render = function() {
        element.toggleClass('primary', angular.equals(ngModelCtrl.$modelValue, scope.$eval(attributes.radioButton)));
      };

      element.bind('click', function() {
        if (!element.hasClass('active')) {
          scope.$apply(function () {
            ngModelCtrl.$setViewValue(scope.$eval(attributes.radioButton));
            ngModelCtrl.$render();
          });
        }
      });
    }
  };
}

Note: This example shows some of the power of ngModelController, which I think is pretty cool. If you’re interested in learning more about what you can do with ngModel, send me an email or let me know in the comments.

Mock

The first thing we need to do is mock out our dependencies. In this example, we are mocking out the kit.forms module and injecting a new instance of $rootScope to use later in our tests.

describe('Forms module', function() {
  var element, scope;

  beforeEach(module('kit.forms'));

  beforeEach(inject(function($rootScope) {
    scope = $rootScope.$new();
  }));

  // ...
});

Compile

Directives need to be compiled in order to make assertions on the HTML they produce. This can be done by injecting the $compile service and running a string of HTML through it. After it is compiled, the digest cycle needs to be kicked off with a call to $digest() from the $scope instance created earlier.

describe('[required]', function() {
  beforeEach(inject(function($compile) {
    element = angular.element(
      '<div class="button-group">' +
        '<label ng-model="model" radio-button="'yes'">Yes</label>' +
        '<label ng-model="model" radio-button="'no'">No</label>' +
        '<label ng-model="model" radio-button="'maybe'">Maybe</label>' +
      '</div>'
    );

    $compile(element)(scope);
    scope.$digest();
  }));

  // ...
});

Interact

Now you can script some interactions on the compiled HTML before you make assertions. Storing a reference to the element(s) you want to manipulate and make assertions against at the beginning of your specs is usually helpful.

it('applies the "primary" class when clicked', function() {
  var radios = element.find('.button');

  radios.eq(1).click();
  // ...

  radios.eq(2).click();
  // ...
});

Assert

Finally, we can make assertions that the markup has changed the way it’s expected to.

it('applies the "primary" class when clicked', function() {
  var radios = element.find('.button');

  radios.eq(1).click();
  expect(radios.eq(1)).toHaveClass('primary');
  expect(radios.eq(0)).not.toHaveClass('primary');
  expect(radios.eq(2)).not.toHaveClass('primary');

  radios.eq(2).click();
  expect(radios.eq(2)).toHaveClass('primary');
  expect(radios.eq(1)).not.toHaveClass('primary');
});

Sometimes the interaction step isn’t necessary for making assertions. For example, it’s usually best to assert that a directive initially compiles the way you expect it to.

it('adds the "button" class', function() {
  expect(element.find('.button').length).toBe(3);
});

E2E Testing Directives

When I first started testing directives I thought I was doing it wrong because I was testing the DOM but I wasn’t using a true integration testing tool, like Protractor. However, I realized a lot of times it’s hard to know the context a directive is going to be used in so it’s difficult to end-to-end test effectively. In most cases it’s easier to avoid an integration testing tool for an individual directive test and just rely on that for flexing the main flows of your SPAs.

Other Patterns

Directives are easily the most difficult thing to test in Angular, but I’ll be sharing some other Angular testing patterns and best practices I use over the next few weeks. Make sure to subscribe to email updates if you want to keep up with this series of articles on Angular testing and please share any other patterns you’ve seen in the comments.

Pimp Your Chrome Dev Tools with Custom Stylesheets

Did you know that Chrome gives you a stylesheet you can use to customize the look of your dev tools? I didn’t either until I looked over at my buddy Zach‘s screen and saw him rockin’ a dark color scheme in his dev tools when we were working at a coffee shop a couple weeks ago.

He informed me that you can put custom styles in ~/Library/Application\ Support/Google/Chrome/Default/User\ StyleSheets/Custom.css and these will override the default dev tool styles. Obviously, I spent the next couple hours looking for the perfect color scheme and I finally settled on this Readable Theme. To install it you just drop the theme’s Custom.css over Chrome’s. The theme even has some SCSS you can pull down and tweak to configure the scheme to your liking if you don’t like some of the defaults.

Before and After

Before:
Chrome Dev Tools before customization

After:
Chrome Dev Tools after customization

You might think this is a trivial upgrade, but I’ve found that this has actually saved me a fair amount of time. The tweaks to the selected attributes and active selector highlights, updated font styles and guides around the contents of the selected element all make it easier to find what you’re looking and have definitely made me more efficient in the dev tools.

It only takes a couple minutes to install a theme and there are quite a few to pick from, so what are you waiting for?

Update: There are now a number of themes available as Chrome extensions. This is the way I would recommend installing them so that you don’t need to worry about updating the styles all the time.

Lessons Learned from Selling My First Business

We recently sold a coffee shop and I think we did almost everything wrong. Here are a few lessons I learned selling my first business. Hopefully this will help others avoid the mistakes we made.

Don’t show your hand

We found out a few months ago that my wife is pregnant. She has been putting in 60+ hour weeks and we knew this wasn’t a sustainable thing so we wanted the deal to move quickly. We advertised this to our buyers openly saying that we would take less money in exchange for a shorter timeline on the deal. This seemed harmless at the time because it was the truth, but it came back to bite us.

Letting our potential buyers know that we were in a bind immediately gave them all the control in the negotiations. They knew our options were limited and that it wouldn’t take much for their offer to be more attractive to us than having to liquidate everything and find someone else to take over our lease.

Don’t count on anything until it’s in writing

We wanted to do everything by the book but we ended up getting verbal offers and making agreements on a handshake with the promise that the paperwork would come later. We banked on these agreements and started planning our lives around transition dates that came and went without any word from our buyer. Even if you ask for things in writing, people are going to try to negotiate with you before making a formal offer. Don’t count on anything from a verbal agreement because you don’t have anything until it’s in writing.

This was one of the most frustrating things I’ve ever had to deal with. We kept asking for things in writing but we didn’t get them. At first we trusted the person we were negotiating with and he would say “my laywer is putting something together” but it never came. We had agreed on a price, transition date, etc., but because the offer wasn’t in writing there was nothing we could do when our buyer didn’t hold up his end of our agreement.

Put everything in writing

My wife originally said that she would be happy to help with the transition. Unfortunately, nothing was laid out in the contract about what that transition period would look like. We thought it meant that they would come in a couple weeks early to shadow and learn our processes, but they took it to mean that my wife or someone from our staff would be sticking around after the new owner took over.

Anything that could possibly be negotiable needs to be written down. No matter how small a detail, if you think of it, put it in writing. It really isn’t that hard and you’ll thank yourself later when you can say “what does the contract say about that?”

Always be looking for a better offer

When we made a verbal agreement to accept an offer we put our marketing efforts on hold. We were stuck scrambling when the agreement wasn’t upheld by the buyer which put us in an even worse spot than where we started for negotiating a new deal with someone else.

Had we kept marketing the sale of the business we would have put some pressure on the person we were working with to move things forward on his end and we may have even found a better offer. There is no way it could have hurt us and it came back to bite us in the end because we ended up working with our original buyer, but completely on his terms.

Don’t be desperate

When we met with potential buyers I’m positive that we came off desperate and that it took power out of our hands. We acted like someone was doing us a favor by buying our business, but that’s certainly not the case. I guarantee that having this mentality during a negotiation will leave you frustrated and disappointed with the outcome.

Save yourself some energy and frustration. Don’t be desperate to sell your business and don’t be afraid to ask for what you want. You’re not going to scare anyone off by asking for more favorable terms.

Develop Faster with iTerm Profiles and Window Arrangements

My friend, Jon Kinney, was showing me how he’s able to jump into dev mode with his server, Rails console, database console, test suite and Vim all running at once using tmux and the tmuxinator gem. I was obviously jelly and I wanted to find a way to do something similar, but since I don’t really use terminal Vim for regular development I thought tmux was overkill for just starting up my server, consoles and tests so I decided to find a way to be more productive in iTerm 2.

Using split panes, profiles and window arrangements we can create a workspace that has everything we need to be productive and we can launch it with a single click. Here’s a preview of the kind of thing you can do:

A preview of the terminal setup

Above we have a regular terminal session, Rails console, database console and server running in 4 different panes.

Profiles

In order to open all the panes and run the commands to start our server, console, etc., we need to create profiles for each type of pane. You can create a profile by going to the Profiles tab in the settings pane. Give it a name and set the command you want to execute when the pane opens in the Send text at start input. You might also need to select the Reuse previous session’s directory as the working directory.

Here are the settings for a profile that I use to start a Rails server:

Preview of iTerm's Profiles tab

Window Arrangements

After you have your profiles setup, you can setup your workspace the way you want and then save the arrangement to use it again later. To create a new pane, use Command + Option + Shift + H for a horizontal split, or Command + Option + Shift + V for a vertical split. When creating a split, it will ask what profile you want to use.

Once you have your panes setup the way you like, just hit Command + Shift + S to save the window arrangement. Unfortunately, you can’t set a hotkey for different window arrangements, but you can launch your default arrangement with Command + Shift + R.

Other Tips and Tricks

  • You can save tabs in your arrangements as well. One cool thing I’ve used this for is starting up a bunch of web services I’m working on so all the APIs are available locally. This would be a huge pain without a saved window arrangement.
  • You can dim, adjust the dimness and animate the dimming for inactive panes under the Apperance tab in the settings.
  • Command + Option + [Arrow Key]: Switches to the next pane in that direction.
  • Command + Shift + Enter: Maximizes the active pane. I find this to be really handy when digging through server logs and stuff.
  • Command + [ or ]: Select the previous ([) or next (]) pane.
  • You can customize the hotkeys by going to the Keys tab of the settings.

Getting Started with Laravel 4

With the release of Laravel 4 just around the corner a lot of people are trying to decide whether to start a new project with a stable 3.2 build or wait for the new version. I found myself in that position earlier this week so I decided to pull down Laravel 4 and work off that since I figured the transition would be smoother once a stable version 4 is released.

There isn’t really any documentation on how to get started with Laravel 4, and if you aren’t familiar with Composer, you might not know where to begin. That’s why I’m writing this. If you want to get started with Laravel 4 today, here’s how.

Laravel, Illumniate and Composer Packages

Laravel 4 breaks each core component of the framework into a Composer package. These packages are currently grouped together under the “Illuminate” organization on GitHub. All of these components are used by the Laravel framework, but now that they are stored as separate packages, they can easily be pulled into other projects with Composer.

Note: Familiarity with Composer isn’t necessary for this tutorial, but if you want to learn more, check out Easy Package Management With Composer by Phil Sturgeon.

Since Laravel 4 is dependent on Composer, you already have access to any package from the Packagist directory anytime you start a new project. That means you have thousands of packages at your fingertips and it eliminates the need for proprietary package management systems like Laravel Bundles and CodeIgniter Sparks.

Getting Started

There’s not much to this, it’s just 3 simple steps. I work on a Mac, but I’d imagine these instructions are pretty similar for other operating systems.

1. Pull Down the Application Template

First thing you need to do is pull down the Laravel application template. This is the starting point for Laravel 4 projects. The template is pretty empty, and if you’re coming from Laravel 3, you’ll immediately notice the absence of the laravel, bundles and storage directories.

2. Install Composer

Run the following script to install Composer into the root of your project:

curl -s http://getcomposer.org/installer | php

You should see a success message if everything runs correctly.

Troubleshooting

I received the following error when I tried to install Composer the first time:

Some settings on your machine make Composer unable to work properly.
Make sure that you fix the issues listed below and run this script again:

The detect_unicode setting must be disabled.
Add the following to the end of your `php.ini`:
    detect_unicode = Off

If you encounter this error, just do as it says and add detect_unicode = Off to the end of your php.ini file at /private/etc/php.ini.

3. Install the Laravel Components

After composer is installed, you can use it to install all of the other Laravel components.

php composer.phar install

Running this command will install the packages that are specified in the composer.json file. Here’s what that looks like:

{
    "require": {
        "illuminate/foundation": ">=1.0.0"
    },
    "autoload": {
        "classmap": [
            "app/controllers",
            "app/domain",
            "app/tests/TestCase.php"
        ]
    },
    "minimum-stability": "dev"
}

This doesn’t seem like much considering how many packages get installed when you run php composer.phar install, but that’s because each package can have its own dependencies. If we take a look at Illuminate’s foundation package, we can see that it has a whole bunch of its own dependencies that get installed too.

{
    "name": "illuminate/foundation",
    "description": "A web application foundation.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "authors": [
        {
            "name": "Taylor Otwell",
            "email": "taylorotwell@gmail.com"
        }
    ],
    "require": {
        "php": ">=5.3.0",
        "illuminate/auth": ">=1.0.0",
        "illuminate/cache": ">=1.0.0",
        "illuminate/config": ">=1.0.0",
        "illuminate/container": ">=1.0.0",
        "illuminate/cookie": ">=1.0.0",
        "illuminate/database": ">=1.0.0",
        "illuminate/encryption": ">=1.0.0",
        "illuminate/events": ">=1.0.0",
        "illuminate/exception": ">=1.0.0",
        "illuminate/filesystem": ">=1.0.0",
        "illuminate/http": ">=1.0.0",
        "illuminate/pagination": ">=1.0.0",
        "illuminate/profiler": ">=1.0.0",
        "illuminate/redis": ">=1.0.0",
        "illuminate/routing": ">=1.0.0",
        "illuminate/session": ">=1.0.0",
        "illuminate/support": ">=1.0.0",
        "illuminate/translation": ">=1.0.0",
        "illuminate/validation": ">=1.0.0",
        "illuminate/view": ">=1.0.0",
        "symfony/browser-kit": "2.1.0",
        "symfony/css-selector": "2.1.0",
        "symfony/dom-crawler": "2.1.0",
        "symfony/http-kernel": "2.1.0",
        "symfony/translation": "2.1.0",
        "underscore/Underscore.php": "1.3.1"
    },
    "require-dev": {
        "mockery/mockery": "0.7.*"
    },
    "autoload": {
        "psr-0": {
            "IlluminateFoundation": "src/"
        },
        "files": [
            "src/helpers.php"
        ]
    },
    "minimum-stability": "dev"
}

Start Your App

That’s everything! You can go visit your app just like you normally would and developing for Laravel is pretty much the same as it was before. Setup some controllers or start defining some routes!

Let me know if you have any troubles with this and I’ll be sure to revise this article or provide more troubleshooting tips!