Monday, February 14, 2011

Test-Driven Development of FizzBuzz

It's been a while since I last posted an entry here. So, let me take some time out to go back to basics. I've recently given a short talk about TDD (Test-Driven Development) using JUnit 4 to some young Java developers. I chose the FizzBuzz problem as an example.

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz.” For numbers which are multiples of both three and five print “FizzBuzz.”


I started with a test. I also decided to have the class return a string (instead of printing it out onto the console).


import static org.junit.Assert.*;

import org.junit.Test;

public class FizzBuzzTest {
private final FizzBuzz fizzbuzz = new FizzBuzz();
}


With this, I had to create the corresponding class.


public class FizzBuzz {
}


I continue with adding tests.


import static org.junit.Assert.*;

import org.junit.Test;

public class FizzBuzzTest {
private final FizzBuzz fizzbuzz = new FizzBuzz();

@Test
public void returnsNumber() throws Exception {
assertEquals("1", fizzbuzz.of(1));
}
}


With this, I had to create the corresponding method and make it pass.


public class FizzBuzz {
public String of(int number) {
return String.valueOf(number);
}
}


I continue to add more tests.


import static org.junit.Assert.*;

import org.junit.Test;

public class FizzBuzzTest {
private final FizzBuzz fizzbuzz = new FizzBuzz();

@Test
public void returnsNumber() throws Exception {
assertEquals("1", fizzbuzz.of(1));
assertEquals("2", fizzbuzz.of(2));
}

@Test
public void returnsFizzWhenNumberIsMultipleOfThree() throws Exception {
assertEquals("Fizz", fizzbuzz.of(3));
}
}


With this, I had to add code and make it pass.


public class FizzBuzz {
public String of(int number) {
if (number % 3 == 0) {
return "Fizz";
}
return String.valueOf(number);
}
}


I continue to add more tests.


import static org.junit.Assert.*;

import org.junit.Test;

public class FizzBuzzTest {
private final FizzBuzz fizzbuzz = new FizzBuzz();

@Test
public void returnsNumber() throws Exception {
assertEquals("1", fizzbuzz.of(1));
assertEquals("2", fizzbuzz.of(2));
}

@Test
public void returnsFizzWhenNumberIsMultipleOfThree() throws Exception {
assertEquals("Fizz", fizzbuzz.of(3));
assertEquals("Fizz", fizzbuzz.of(6));
assertEquals("Fizz", fizzbuzz.of(9));
}

@Test
public void returnsBuzzWhenNumberIsMultipleOfFive() throws Exception {
assertEquals("Buzz", fizzbuzz.of(5));
}
}


With this, I had to add code and make it pass.


public class FizzBuzz {
public String of(int number) {
if (number % 3 == 0) {
return "Fizz";
}
if (number % 5 == 0) {
return "Buzz";
}
return String.valueOf(number);
}
}


I continue to add more tests.


import static org.junit.Assert.*;

import org.junit.Test;

public class FizzBuzzTest {
private final FizzBuzz fizzbuzz = new FizzBuzz();

@Test public void
returnsNumber() throws Exception {
assertEquals("1", fizzbuzz.of(1));
assertEquals("2", fizzbuzz.of(2));
}

@Test public void
returnsFizzWhenNumberIsMultipleOfThree() throws Exception {
assertEquals("Fizz", fizzbuzz.of(3));
assertEquals("Fizz", fizzbuzz.of(6));
assertEquals("Fizz", fizzbuzz.of(9));
}

@Test public void
returnsBuzzWhenNumberIsMultipleOfFive() throws Exception {
assertEquals("Buzz", fizzbuzz.of(5));
assertEquals("Buzz", fizzbuzz.of(10));
}

@Test public void
returnsFizzBuzzWhenNumberIsMultipleOfThreeAndFive() throws Exception {
assertEquals("FizzBuzz", fizzbuzz.of(15));
}
}


With this, I had to add code and make it pass.


public class FizzBuzz {
public String of(int number) {
if (number % 3 == 0) {
return "Fizz";
}
if (number % 5 == 0) {
return "Buzz";
}
if (number % 3 == 0 && number % 5 == 0) {
return "FizzBuzz";
}
return String.valueOf(number);
}
}


At this point, my previous tests fail. So, guided by tests, I went back and fixed things up.


public class FizzBuzz {
public String of(int number) {
if (number % 3 == 0 && number % 5 == 0) {
return "FizzBuzz";
}
if (number % 3 == 0) {
return "Fizz";
}
if (number % 5 == 0) {
return "Buzz";
}
return String.valueOf(number);
}
}


Now that all of the tests are passing, I thought about refactoring (by removing duplication). Obviously, the "Fizz" and "Buzz" strings are repeated. Again, guided by tests, I changed my code to something like:


public class FizzBuzz {
public String of(int number) {
StringBuilder b = new StringBuilder();
if (number % 3 == 0) {
b.append("Fizz");
}
if (number % 5 == 0) {
b.append("Buzz");
}
if (number % 3 != 0 && number % 5 != 0) {
return b.append(String.valueOf(number));
}
return b.toString();
}
}


As I glance over the code, I can see there's still some duplication. The modulus was operating on the number twice: one by three, and another by five. Again, guided by tests, I modified my code to remove duplication. Here's the result.


public class FizzBuzz {
public String of(int number) {
boolean multipleOf3 = (number % 3 == 0);
boolean multipleOf5 = (number % 5 == 0);
if (!multipleOf3 && !multipleOf5) {
return String.valueOf(number);
}
StringBuilder b = new StringBuilder();
if (multipleOf3) {
b.append("Fizz");
}
if (multipleOf5) {
b.append("Buzz");
}
return b.toString();
}
}


I know this is simple. But it's a good coding exercise.
Sunday, October 17, 2010
Tuesday, May 18, 2010

How They Looked When They Launched

I've been busy working with the wonderful team at haybol.ph, building a real estate search engine for the Philippines. Recently, we've started to review how our page looks like. The team is getting better at indicating what they like most, and what works best.

As a tribute to the hard working team at haybol.ph, I'm posting how some popular websites looked when they launched, and compare them to haybol's (grin). Go to haybol blog: How They Looked When They Launched.

Kudos to the haybol.ph team!