Me and my colleagues do a small TDD-Kata practice everyday for 30 minutes. For reference this is the link for the excercise http://osherove.com/tdd-kata-1/
The objective is to write better code using TDD. This is my code which I've written
public class Calculator
{
public int Add( string numbers )
{
const string commaSeparator = ",";
int result = 0;
if ( !String.IsNullOrEmpty( numbers ) )
result = numbers.Contains( commaSeparator ) ? AddMultipleNumbers( GetNumbers( commaSeparator, numbers ) ) : ConvertToNumber( numbers );
return result;
}
private int AddMultipleNumbers( IEnumerable getNumbers )
{
return getNumbers.Sum();
}
private IEnumerable GetNumbers( string separator, string numbers )
{
var allNumbers = numbers
.Replace( "\n", separator )
.Split( new string[]
{
separator
}, StringSplitOptions.RemoveEmptyEntries );
return allNumbers.Select( ConvertToNumber );
}
private int ConvertToNumber( string number )
{
return Convert.ToInt32( number );
}
}
and the tests for this class are
[TestFixture]
public class CalculatorTests
{
private int ArrangeAct( string numbers )
{
var calculator = new Calculator();
return calculator.Add( numbers );
}
[Test]
public void Add_WhenEmptyString_Returns0()
{
Assert.AreEqual( 0, ArrangeAct( String.Empty ) );
}
[Test]
[Sequential]
public void Add_When1Number_ReturnNumber(
[Values( "1", "56" )] string number,
[Values( 1, 56 )] int expected )
{
Assert.AreEqual( expected, ArrangeAct( number ) );
}
[Test]
public void Add_When2Numbers_AddThem()
{
Assert.AreEqual( 3, ArrangeAct( "1,2" ) );
}
[Test]
public void Add_WhenMoreThan2Numbers_AddThemAll()
{
Assert.AreEqual( 6, ArrangeAct( "1,2,3" ) );
}
[Test]
public void Add_SeparatorIsNewLine_AddThem()
{
Assert.AreEqual( 6, ArrangeAct( @"1
2,3" ) );
}
}
Now I'll paste code which they have written
public class StringCalculator
{
private const char Separator = ',';
public int Add( string numbers )
{
const int defaultValue = 0;
if ( ShouldReturnDefaultValue( numbers ) )
return defaultValue;
return ConvertNumbers( numbers );
}
private int ConvertNumbers( string numbers )
{
var numberParts = GetNumberParts( numbers );
return numberParts.Select( ConvertSingleNumber ).Sum();
}
private string[] GetNumberParts( string numbers )
{
return numbers.Split( Separator );
}
private int ConvertSingleNumber( string numbers )
{
return Convert.ToInt32( numbers );
}
private bool ShouldReturnDefaultValue( string numbers )
{
return String.IsNullOrEmpty( numbers );
}
}
and the tests
[TestFixture]
public class StringCalculatorTests
{
[Test]
public void Add_EmptyString_Returns0()
{
ArrangeActAndAssert( String.Empty, 0 );
}
[Test]
[TestCase( "1", 1 )]
[TestCase( "2", 2 )]
public void Add_WithOneNumber_ReturnsThatNumber( string numberText, int expected )
{
ArrangeActAndAssert( numberText, expected );
}
[Test]
[TestCase( "1,2", 3 )]
[TestCase( "3,4", 7 )]
public void Add_WithTwoNumbers_ReturnsSum( string numbers, int expected )
{
ArrangeActAndAssert( numbers, expected );
}
[Test]
public void Add_WithThreeNumbers_ReturnsSum()
{
ArrangeActAndAssert( "1,2,3", 6 );
}
private void ArrangeActAndAssert( string numbers, int expected )
{
var calculator = new StringCalculator();
var result = calculator.Add( numbers );
Assert.AreEqual( expected, result );
}
}
Now the question is which one is better?
My point here is that we do not need so many small methods initially because StringCalculator has no sub classes and secondly the code itself is so simple that we don't need to break it up too much that it gets confusing after having so many small methods.
Their point is that code should read like english and also its better if they can break it up earlier than doing refactoring later and third when they will do refactoring it would be much easier to move these methods quite easily into separate classes.
My point of view against is that we never made a decision that code is difficult to understand so why we are breaking it up so early.
So I need a third person's opinion to understand which option is much better.