Clean code, fuzzy bunnies, and rainbows

Behaviour Driven Development for JavaScript: Part One

Marco Emrich is an author, trainer, software developer and project manager with an academic degree in computer science. He speaks at various IT-conferences (OOP, Seacon, Webtech, SoCraTes), writes articles (ObjektSpektrum, RailsWay, PHP & Web Magazine) and facilitates code retreats. This extract is taken from his eBook Behaviour Driven Development with JavaScript, which was released by our sister publishing arm, Developer.Press.

 

Back in 2005 when I first started learning about TDD, I was hooked – or ‘test infected’ as they say. At this point, I already had over a decade experience in software development. Even though I had some experience in automated testing; discovering TDD was like discovering a new world. Applying TDD provides huge benefits. In the words of famous Uncle Bob:

“...your code will be cleaner, you’ll get done with software faster, your software will work better, and fuzzy bunnies will happily hop over hillsides overarched by double rainbows all the way!”

In order to get all these benefits, you have to apply TDD the right way, and that's the tricky part. Despite my experience and dedication it took me a very long time to realize the most important rule of TDD…

It's not about testing!

As surprising as that sounds, it's true. TDD brought us many things, and testing is just one small aspect of it. Just in case you are wondering, I will thoroughly cover this in the chapter “What is BDD?” The main point I would like to emphasise is: To use TDD well, you will have to think of it as a design technique, think about behaviour and specification – not about testing.

I wasn't the only one having a hard time getting the most out of TDD. There were many questions floating around online, like: 

  • Where to start in the process?
  • What to test and what not to test?
  • How much to test in one go?
  • What to call the tests?
  • How to understand why a test fails?

Then Dan North came along and wrote a very interesting article answering some of these questions. He suggested that we replace the vocabulary of TDD with one that isn't focused on testing but on the behavior of your application. Without the misleading testing terms a beginner could learn the important things much faster. He coined the term BDD. With the help of others, BDD grew to become what it is today. Now we have a set of methods and techniques that assists us in communication and provides a concept for better documentation.

This helps us to write high quality code and to discover well factored designs. It appeals to developers as well as to business people, product owners and testers. Since it's still a young methodology, I'm pretty sure we will see it continue to grow in the future.

 JavaScript and its ecosystem improved quite a lot in the recent years. It has become the most important language of the web – the language of the web. It doesn't matter if you code in Java, Ruby, PHP or anything else on the server. On the client you need to use JavaScript! While the language has many great BDD-frameworks available, I am still confronted with bucket loads of bad JavaScript code every day. While BDD and TDD are making their way to becoming a regular feature on the server side, the adaption rate on the client side is much slower than I would like it to be. Maybe the lack of focused and specialized documentation is an influential factor. Question: “What's the difference between Java and JavaScript?” Answer: “They have as much in common as car and carpet.”  

JavaScript is not a toy language

JS had the reputation for being a ‘toy’ language which couldn’t compete in the same league as Java, C++ and other popular languages. It took most developers years to recognize the importance and utter brilliance of JS. There were a few individuals like Douglas Crockford who fought a long battle to educate people on the strength of JavaScript1. JS has some really useful language features like prototyping, function expression and closures. Sadly Brandon Eich had only ten days to implement the first version of JS, thus he made some mistakes which are still a problem for JS today2 – but you can't really blame him.

Most of these problems are syntactical in nature and will improve in future versions of JS. The ECMAScript5 standard (ES5) already improved the situation. The next version will be ECMAScript6 aka Harmony which will fix many more of the current issues.

 You can take a look at http://kangax.github.com/es5-compat-table/ to see which browser versions support ECMAScript5  

Basic tools

console.log As I mentioned before, you really should use a development tool in order to get a console.log command that you can use to debug your code.

var a = [1, 2, 3];
console.log(a);

It provides better feedback than alert-boxes and you don't have to close those annoying boxes continuously. 

jsHint/jsLint

In order to get feedback on possible errors and bad style early, you should use a lint tool. Lint tools look out for possible problems in your coding style, for example assignments in if statements (listing 1.2), global variables and unreachable code.

if (a = 3) //should have been if (a == 3) or (a === 3)

If a lint tool finds any problems, you get a warning and can fix the problem early – when it is still small.

There are two great tools available: jsLint (www.jslint.com) and jsHint (www.jshint.com). Which one you use is just a matter of preference. Some IDEs (for example JetBrains Webstorm3) support them directly in the editor.

You should also disable some of these lint checks, since some BDD-frameworks use a coding style that lint tools would consider dangerous. 

use strict

Another great checking aid is the strict-mode of ES5. You can put a modern browser in strict-mode by providing this string:

"use strict";

Older browsers will ignore it – it’s just a string! But modern browsers will switch the js-engine to strict-mode. In this mode the browser reports various additional errors found within the following code – just like the lint tools. You will catch weird bugs really early in the development cycle.

JavaScript is functional

JS is a functional language as much as it is an object oriented one. It may lack some features of more modern functional languages like Haskell, but it inherited some really useful properties from the functional world.

I think that the most useful functional features of JS are functional expressions and closures. Let's start with the first one.

Creating function expressions

In JS functions are first class citizens. This means you can use them like any other value. You can bind them to variables, use them as arguments for other function calls, and even return them from functions.

Maybe you are used to defining functions this way:

function greetMe() { return 'Hello' }

But actually that’s almost only ‘syntactic sugar’ for this:

var greetMe = function() { return 'Hello' };

This line defines a function value and assigns it to the greetMe variable. Now greetMe contains the function – or more precisely, the variable name greetMe it is bound to the function. You can verify this by calling:

alert(greetMe);

The alert command needs a string representation of the function in greetMe. So it invokes the decompiler which returns the original implementation of greetMe as a string. Now alert can print the string in its box.

 

Using function expressions

JS distinguishes between calling the function and the function as a value by the parenthesis “( )” after the function name.

There are even some examples in JavaScript's base library. Think about the sort-method of Array; sort does lexical sorting by default. Thus, the following expression

['Brandon', 'James', 'Alan'].sort()returns this array:

['Alan', 'Brandon', 'James']

But the next expression

[4, 1, 2, 3, 31, 10].sort()

returns this result:

[1, 10, 2, 3, 31, 4]

This is probably not what you want. It will use lexical sorting even if you want numerical. Without functional decomposition the JS library team would have had to write various sort methods for all kinds of order variants.

To avoid this all you have to do is to provide a function that defines the sort order by comparing two values. Sort expects a function that takes two arguments and returns -1, 1 or 0, depending on their relationship. For example, numerical sorting can be done this way:

function numericalOrder(a, b) {

if (a < b) {return -1};

if (a > b) {return 1};

return 0;

}


[4, 1, 2, 3, 31, 10].sort(numericalOrder)

//returns [1, 2, 3, 4, 10, 31]

The sort-algorithm is separated from the order logic. If you need another ordering, just write a new order function. You don't have to write any sort logic (like quicksort or hashsort) yourself.

I once wrote an application for a club. One feature was to list the members of the club. A special requirement was that the club president should always be listed first. An easy thing to do:

function memberOrder(a, b) {

if (a == 'Chris Clubchief') return -1;

if (b == 'Chris Clubchief') return 1;

return a > b;

}

Now we have:

['Brandon', 'Chris Clubchief', 'James', 'Alan'].sort(memberOrder)

This produces:

["Chris Clubchief", "Alan", "Brandon", "James"]

To be continued! Part Two to this tutorial will published on Friday 7th March. 

 

 

 





 


 





 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 



Marco Emrich

What do you think?

JAX Magazine - 2014 - 06 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions