Thursday, April 15, 2010

JS Class Patterns

I've been in a lot of discussions lately about JavaScript design patterns, specifically around how to write a class. The two patterns in the lead are as follows:

Decorator pattern, new Foo() returns a decorated BaseClass object:

function Foo(bar) {
  var self = new BaseClass();

  var baz = 42;

  self.publicFn = function() {
    return bar + baz;
  };

  return self;

  function privateFn() {
    bar = 0;
  }
}

Prototype pattern, more traditional JS:

function Foo(bar) {
  BaseClass.call(this);

  this.bar_ = bar;
  this.baz_ = 42;
}
Foo.inheritsFrom(BaseClass);

Foo.prototype.publicFn = function() {
  return this.bar_;
};

Foo.prototype.privateFn_ = function() {
  this.bar_ = 0;
};

At first, I was 110% in the Prototype camp. It feels like how JS is "supposed" to be used and has some undeniable advantages. Object construction using prototype instead of decoration is much faster, uses less memory, and is usually considered a Good Thing™.

It also lets you know what type objects are in a more intuitive way. With the Prototype pattern, typeof new Foo() will return Foo, where as with the Decorator pattern typeof new Foo() will return BaseClass since what you really have is a decorated BaseClass object.

Using the prototype object to add functions to your class lets you also gives you a lot of flexibility regarding function overriding. It makes mocking objects much easier, and lets you wrap functions with things like logging on a global level instead on an instance by instance basis.

The Decorator pattern does have some advantages though. You can have privately scoped variables and functions. You don't have to worry about execution scope since you always have a variable "self" to reference. You definitely hear a lot less "is this this, or is this that... which this is this?!" when using the Decorator pattern.

Overall, the Decorator pattern behaves much more like other OO languages at the cost of performance and flexibility you get with the prototype object.

When listed out like that, I'm still at least 99% in the Prototype pattern camp. However there are some other key factors that have started to change my mind:

Talking to the team, we discovered that development speed has increased significantly by moving to the Decorator pattern. This could be attributed to a lack of JS knowledge by the developers since the Prototype pattern is fairly JS specific, but they are all very smart, talented engineers so the learning curve affects should be minimized. I think even the reduced debugging time from having the "self" variable has helped a lot. I've done a lot of JS development, and I know I forget to bind functions to the right "this" from time to time.

Test effectiveness has also been much better with the Decorator pattern. With actual private variables and functions there are less shortcuts taken in tests. We end up doing less pure "unit" tests and more domain tests, and since we don't have automated integration Selenium-ish tests for our current project's platform that has been quite helpful.

Also, on our project, the performance loss from not using the prototype object is basically a non-issue, so the Decorator pattern doesn't hurt us much in that regard. We are only constructing a handful of objects at a time (less than 100) so we're only sacrificing a couple milliseconds of CPU cycles if that.

I don't claim to have the all encompassing answer for which pattern is better, but for our project, I'm starting to lean more towards the Decorator pattern, or at least acknowledge how it's helped our development. Anything that can improve both development speed and quality wins major points in my book.

One of the reasons I bring this up on the blog is that the whole discussion is the perfect anti-cement cutting board story. In another world, someone could come in and impose cement cutting boards like "You need to use the Prototype pattern since that's the most JavaScripty way." Or even "Both those are wrong, use Crockford's latest and greatest pattern."

However, on our project, we, the developers, not only get try multiple patterns but discuss and come up with a solution that works best for us in the real world. These kinds of decisions couldn't come from anyone other than those in the trenches with real hands on experience.

Ultimately, we are the ones it matters most to since we are the ones that have to deliver a great product to our client. Even if we use a design pattern that loses us some academic brownie points, if we deliver a better product faster, we still win, our client wins, and that's what really matters.

Wednesday, April 14, 2010

What's in a comment?

One of the biggest surprises I had at my new job was finding out that writing code comments pretty much doesn't happen. It's not explicitly forbidden, but it is unofficially looked down upon by the developers.

Previously, I have always used code comments - Javadoc style method comments were more or less required (for the useless metric of code/comment ratio), and I would sprinkle others throughout the code as I thought was needed. I definitely don't want to fall into some sort of macho "you need comments?!" type of mentality, but if there is a better way of doing things I'm all ears.

Around my new office, the general thought on comments seems to be that if you need them you're doing something wrong. Also, we will often look at tests to see what any piece of code should do. Since we're using Jasmine (basically modeled after RSpec) each of our tests starts out more or less like a code comment anyway.

For example, say you saw this code:

MyApp.prototype.launch = function(action) {
  if (action == 'viewActivePages') {
    this.view.showActivePages();
  }
}

Reading this, you start wondering when launch would get called this way - there isn't any time you can think of where you would want to launch with this action. Then, looking at the tests you see this:

desc("#launch") {
  desc("when user taps dialog") {
    it("should show the active pages") {
      myApp.launch('viewActivePages');
      ...
    }
  }
}

Suddenly it all makes sense, you remember that the app can be launched by tapping on a dialog, and when that happens you should expect to see the active pages. The tests have successfully served as the comments.

This clarity could have also been accomplished with a comment:

MyApp.prototype.launch = function(action) {
  if (action == 'viewActivePages') { // tapping on dialog
    this.view.showActivePages();
  }
}

However, what if after looking at that comment you saw that the tests instead said this:

desc("#launch") {
  desc("when user taps dialog") {
    it("should show the user's work items") {
      myApp.launch('viewWorkItems');
      ...
    }
  }
}

Now you have conflicting information. The comment says that 'viewActivePages' should happen when a user taps on a dialog, but the tests say that 'viewWorkItems' should happen instead.

I drug you through the example above so you will have an idea of where I'm coming from on this. I don't know what the right answer is for whether or not to write code comments, but here is what I have figured out so far:

- Code comments, when they exist, should explain the why, code should explain the how
- Comments should be used when the code can't be made as clear as you would like (happens in CSS a lot)
- If you feel you have to write a ton of comments, you probably are doing it wrong
- Reading a comment is a lot faster than looking at a test
- An accurate comment can save you a lot of time

However, I also have found this to be true:

- Comments are often inaccurate, they get outdated very quickly and aren't well maintained
- An inaccurate comment is much worse than no comment at all
- Tests aren't perfect but are maintained much more than comments are

One place that I definitely think comments should be included is when the code can't convey all the information. For example, if you chose one algorithm over another because it performed better, it's probably worth putting in a comment to say so. The old slower algorithm won't be left around to show people reading your code that it was removed or explain why.

Another place that comments can be very useful is in things like CSS where you are very limited in how you code things. Conveying intent can be very useful when you come in later and try to figure out why something was done a certain way.

So what do you think? What is the right time to write comments? What should your threshold be for when warning bells go off when you find yourself wanting to write one?

Tuesday, April 6, 2010

You should "should"!

I never thought I would grow attached to the word "should". Weighing in at around six letters, it seemed fairly unremarkable, however now I use many times every day. "It should show a login page when the user starts the app." "It should let the user set notifications to either on or off." "It should overload the constructor until you can't possibly understand what is going on." (Ok, maybe not that last one... more on that later.)

These "should" statements above are called user stories, and in agile development, these are what the developers are given to work on. You get a big ol' queue of user stories and start cranking from the top, marking stories complete as you go.

So, you might be wondering, what is so great about the whole "should" thing? Couldn't you phrase the stories like this:

"Show login page when app starts"
"Set notifications to on/off"

They are shorter and probably display better in your bug tracker, why bother with all this extra typing? I mean, what are you... a Java developer?!

In my experience, stories like the ones above are only one step away from the dreaded one-word-requirement:

"Login page"
"Notification settings"

Ok, two words, but still. It sounds like a caveman wrote the stories above... What should we work on next? "Login page!" Well what should that do? "Login page!" When should we show it? "LOGIN PAGE!" At that point, your customer clubs you over the head and finds another vendor wondering why you were too stupid to know exactly what was meant by "Login page".

How often have you seen requirements like this and scratched your head wondering what to do? I've had features that lasted for multiple months based on three words written in a meeting I didn't even attend.

Now, try to phrase the requirements above using the word "should". Can you make a caveman story with "should"? I dare you to try it. Even better, try to write the stories with both the words "should" and "user". "Login page" turns into "It should show a login page when the user starts the app" and suddenly you have an actionable story.

I'm not claiming that you can't write good stories without the word "should", I think that "Show login page when app starts" is completely fine. However, you can prevent the slippery slope toward the one-word-requirements by making "should" a requirement for your stories.

Another effect of writing your stories using "should" is that they become much manageable - exactly what agile says you should do. It's hard to write a giant requirement like "CMS" as a user story with "should". It becomes obvious pretty quickly that a story like "It should let the user manage content for each page and let them save content before publishing and should let them publish only if they have permission and should check whether content is already there and if so prompt and if not add it to the publish queue" is really multiple stories.

It also helps make your story scope easier to understand. "It should show the login page when a user starts the app" doesn't say anything about not showing the login page if the user has cached credentials. If that is also a requirement, it should be another story. By writing your stories this way, both the developers and clients can be much more clear about what expect when a story is delivered.

It's no coincidence that test frameworks like RSpec and Jasmine start each test with it("should ..."). It works well for the exact same reasons. Which of the following tests is easier to understand:

it("should update the user's credentials after login")
testLoginUpdateUserCredentials()

So, don't write caveman requirements, you should "should"! (That Geico guy is going to get me for this...)

Friday, April 2, 2010

Thoughts on pairing

Pair programming can be hard. It can be daunting at first to work side by side with someone for 8 hours every day, talking about almost every decision you make as you work. However, I really think the benefits far outweigh any downsides. You'll learn more, work faster, and likely produce the best code you ever have. You'll be better for it, the team will be better for it, and the client will get a better product because of it.

Before I get into it, first a little disclaimer. The company I'm working for does pair programming full time. Every project for every client is done in pairs. I've also only been at the company for a couple weeks, so I'm still learning all this myself. However, I think that puts me in a great position to compare pairing to non-pairing since I have both fresh in my mind (and is also why I started this blog in the first place).

Really, pairing is all about finding your rhythm. Once you hit your groove, pairing doesn't seem to be as much work as it might at first. After about two weeks it started to feel really natural for me, and so far I definitely prefer it to working alone.

Here are a few techniques I've picked up so far to make it a little easier to do:

First is the setup. Each member of the pair should have their own keyboard and mouse plugged into the computer. This allows either person to immediately take control from their seat and help out. It also lets people use the hardware they like, cuts down on germs, and basically lets pairing work really smoothly. I really can't emphasize this part enough, I think that each person having their own keyboard/mouse combo is truly essential to being able to pair repeatedly day after day.

Next is a technique called ping-pong. This technique works especially well with TDD. Say, for example, I'm pairing with Joe. I'll write the first unit test and make sure it fails for the right reasons. Then, Joe will implement whatever is needed to make the test pass. He will then write the next test and I will make it pass. Doing this, you ensure that both people in the pair get some keyboard time for both the tests and code, and, more importantly, it makes sure that both people in the pair understand each feature that is being added.

Much less formal than ping-pong, but even more important: don't be the victim of a keyboard controller! In each pair, inevitably there will be one personality that is more controlling than the other. Maybe one person is more familiar with the language or the framework being used, or maybe they just really like typing. The important part is to make sure that you are trading off who is driving regularly.

I would say 5 minutes is about the longest you want one person to be at the wheel, and ideally even shorter than that. One of the big benefits of pair programming is the knowledge transfer that goes on, and even if someone is slower at first, it's worth making the investment in them to help them become more productive.

Ping-pong also helps combat the keyboard-controller, so if you're having problems either being one or getting pushed around by one, try implementing a formal ping-pong coding style.

Another thing about pair programming that might not seem intuitive at first, is do everything as a pair! If you have a question about something and need to go talk to someone, go together. If someone else needs to ask you a question about a feature, answer it together. Remember, programmers aren't limited by their typing speed. Any seemingly lost productivity by having 2 people involved in discussions will be quickly made up by having 2 knowledgeable people working on the project.

TLDR; Pairing can be hard, especially at first. But if you stick with it and find your rhythm, it is definitely worth the investment.