Clean code, fuzzy bunnies, and rainbows

Behaviour Driven Development for JavaScript: Part One

MarcoEmrich
BDD

Marco Emrich was ‘test infected’ when he first started learning about TDD – the hardest part is just getting it right. In the first of a two part series, he shows you how to do just that.

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 JavaScript
1. 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 today
2 – 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. 

 

 

 



 


 





 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 



Author
Comments
comments powered by Disqus