Challenge: How would you start this problem? 7

Posted by Brett Schuchert Wed, 17 Jun 2009 05:16:00 GMT

On Thursday, we’re holding our first Coding Dojo at the recently opened OkC CoCo. This isn’t the first Coding Dojo to happen in Oklahoma City. Some time back, Dave Nicolette held a Randori with a Fishbowl at the OkC Java User’s Group, and that’s the format I’ll be using for this problem. It was a blast then and I’m hoping it’ll be the same this time around.

This first DoJo is with C#, though I hope we manage to use several languages over time. I’d like to sneak in Smalltalk as soon as we have enough of a critical mass so we don’t lose people. I also plan to slowly introduce BDD (maybe not so slowly, who knows – depends on the group).

The recent refactoring exercises (here and here), they come from this problem. We’ll be starting from scratch, so you can probably imagine that those refactoring examples are not going to come up right away (actually probably not at all given the time).

So your challenge this time is not one of refactoring but rather one of an initial value problem. Given the problem statement, how would you go about starting it? I’m assuming TDD, do you make that same assumption? If so, what’s your first test? Your first few tests? What features do you try to tackle first? What questions do you ask yourself about the problem?

I’ve used this problem several times and it’s a great problem to practice many things including:
  • Test Driven Development
  • refactoring (lower case r deliberate – can you guess why?)
  • Refactoring to Design Patterns
  • Most of the SOLID principles

Anyway, how would you go about starting this problem? Or better yet, give it a try and post your first few tests (in the order you create them).

I’ll be interested in seeing how people start and I’ll compare it to what I’ve done (hint, I use this as a class-driven thing, so I’m pretty flexible on how to start it).

p.s. As a result of studying the manual for my HP 32SII, I have a much better understanding of just how its stack works. I have a EE and CS background, so the stack implementation makes sense, but I left some of its details out of the problem.

Comments

Leave a response

  1. Avatar
    Thomas Vidic about 15 hours later:

    When creating a new class / method, i usually write the simplest test that is possible, so that “test fails” means “does not compile” and the test passes after some trivial coding. So my first test was something like this:

    public class RpnCalculatorTest {
    @Test
    public void shouldContainZeroInEachRegisterAfterCreation() throws Exception {
        RpnCalculator calc = new RpnCalculator();
        assertEquals(BigDecimal.ZERO, calc.getX());
        assertEquals(BigDecimal.ZERO, calc.getY());
        assertEquals(BigDecimal.ZERO, calc.getZ());
        assertEquals(BigDecimal.ZERO, calc.getT());
    }
    }

    Next i tried to get some values into the registers. All the tests first used ints instead of BigDecimal and char, but i refactored later to these types…

    @Test
    public void shouldContainNumberAfterTakingIt() throws Exception {
        calc.take('1');
        assertEquals(new BigDecimal(1), calc.getX());
    }
    @Test
    public void shouldContainTwoDigitNumberAfterTakingEachDigit()
            throws Exception {
        calc.take('4');
        calc.take('2');
        assertRegisterValues(calc, new BigDecimal(42), BigDecimal.ZERO,
                BigDecimal.ZERO, BigDecimal.ZERO);
    }
    @Test
    public void shouldCopyContentOfXToYIfEnterIsCalled() throws Exception {
        BigDecimal two = new BigDecimal(2);
        calc.take('2');
        calc.enter();
        assertRegisterValues(calc, two, two, BigDecimal.ZERO, BigDecimal.ZERO);
    }

    After that i started with class OperandStack and tests like these:

    @Before
    public void setUp() {
        mockStack = mock(java.util.Stack.class);
        stack = new OperandStack(mockStack);
    }
    @Test
    public void shouldDelegatePush() throws Exception {
        BigDecimal value = new BigDecimal(1);
        stack.push(value);
        verify(mockStack).push(value);
    }
    @Test
    public void shouldDelegatePopIfStackIsNotEmpty() throws Exception {
        when(mockStack.empty()).thenReturn(false);
        stack.pop();
        verify(mockStack).pop();
    }
    @Test
    public void shouldPopZeroIfStackIsEmpty() {
        when(mockStack.empty()).thenReturn(true);
        assertEquals(BigDecimal.ZERO, stack.pop());
        verify(mockStack, never()).pop();
    }
    @Test
    public void shouldReturnZeroForElementFromTopWithNonExistingIndex() {
        when(mockStack.size()).thenReturn(0);
        assertEquals(BigDecimal.ZERO, stack.elementFromTop(0));
        verify(mockStack, never()).elementAt(1);
    }
    @Test
    public void shouldReturnElementFromTopWithExistingIndex() {
        when(mockStack.size()).thenReturn(2);
        when(mockStack.elementAt(0)).thenReturn(new BigDecimal(42));
        assertEquals(new BigDecimal(42), stack.elementFromTop(1));
    }

    These are the first of currently 27 tests beeing now at the point where the second exercise starts.

  2. Avatar
    Martin Vilcans 1 day later:

    Sorry for being a little off topic, but isn’t it funny that HP were able to market RPN as a feature, while it’s a way to make the calculator’s design simpler? A typical calculator parses the formula the user enters to create a tree and then executes it on a stack. HP calculators skipped the parsing step and required the user to work directly on the stack. It’s like RPN is the assembly language of calculators. :-)

  3. Avatar
    Brett L. Schuchert 1 day later:

    Martin Vilcans wrote:

    ...isn’t it funny that HP …

    Maybe. It IS easier to build (in circuits or software) for the reason you mention. However, RPN has been around since 1920, so I’m not sure if their reason was to make something that was easier to build (maybe) or something that is easier to use (well it is for me, but I love vi as well).

    According to the hp museum site, they decided on RPN because of its ability to handle more complex expressions. Given the time-frame (1968), and the weigh (40 pounds), going with a simpler way to represent expressions was a good idea!

    And personally, I have a much better time using RPN than infix calculators.

  4. Avatar
    Neal Blomfield 5 days later:

    The core of the problem revolves around manipulating the operand stack. Looking at the worked examples in the problem definition, the simplest assertion you can make is that when popping an empty stack, the returned value should be 0, so that is where I started from. The test is at http://randomcode.net.nz/2009/06/22/yet-another-bdd-extension-for-xunit/ as I used it to drive out a BDD style extension for xUnit.

  5. Avatar
    ?????? ???? 26 days later:

    @Test public void ??? shouldContainZeroInEachRegisterAfterCreation() throws Exception { RpnCalculator calc = new RpnCalculator(); assertEquals ??? ?? (BigDecimal.ZERO, calc.getX()); assertEquals(BigDecimal.ZERO, calc.getY()); assertEquals(BigDecimal.ZERO, calc.getZ()); assertEquals(BigDecimal.ZERO, calc.getT());

  6. Avatar
    nike shoes hosting 6 months later:

    Given the time-frame (1968), and the weigh (40 pounds), going with a simpler way to represent expressions was a good idea!

  7. Avatar
    FLV extractor 10 months later:

    what is wrong with me

Comments