I'm committed to trying to move from Access programming to OOP/TDD, and I'm
looking at moving to C# and/or Java. So, I'm trying to think of projects to try
to implement as self-teaching projects.
I've read enough now here and elsewhere to know that for TDD, the idea is
usually to try to keep the UI as thin as reasonably possible since that's the
hardest thing to write tests for, and code as much as possible to be UI
agnostic. That sounds great, but my brain is having trouble bending that way.
It's not that Access is the only thing I've ever known. I started out
programming in Applesoft Basic, taught myself Assembly Language, then went on to
C, Modula II, ad did a fair amount of hobbying in C++ before ending up working
in database development using Paradox, Foxpro, then MS Access.
Still, I find I've been steeped in Access for so long that my thought process is
that everything starts out as a UI tied to a back-end, then sprinkle code as
necessary (I'm a hammer now, and every problem looks like a nail to me). How to
I develop a replacement way of thinking to break out of this? What does a thin
UI feel like? How does code that now seems like an extension of the UI begin to
feel like a part of the internal process instead?
Any tips? Links? Books?
Thanks,
- Steve Jogensen
Here's an exercise that will take you a few hours, and will teach you
what you want to learn. Write the game "Hunt the Wumpus". This is a
very simple game from the 70s that people used to write in Basic on
their Apple II or TRS-80, or Commodore 64.
Play it here: http://www.taylor.org/~patrick/wumpus/
As I said, write this game. HOWEVER, write absolutely no user
interface code! Write test cases that check to see that every
function works. Also write test cases to make sure that the program
knows what messages to emit and the right times. However, do not
include the strings of the messages, and do not emit the messages on
any device. Instead, write an interface (in Java) that has methods
for emitting the appropriate messages, but have the tests implement
the methods simply to verify that they were called at the right time.
Do not write code that reads commands from the user. However, *do*
write tests that invoke the functions that such commands would invoke.
I've done this exercise a few times, and it's always *very* revealing.
You can write the entire game without any UI. You can get the whole
game working without every playing it. And then, finally, as the very
last step, you can write the UI itself. You'll find that writing the
UI is trivial once you've gotten the whole rest of the program
working. You'll realize that you have thought through lots of issues
that make the UI simple to create. And yet the UI will be completely
decoupled from the game. The game won't care about the UI at all.
Robert C. Martin | "Uncle Bob"
Object Mentor Inc.| unclebob @ objectmentor . com
PO Box 5757 | Tel: (800) 338-6716
565 Lakeview Pkwy | Fax: (847) 573-1658 | www.objectmentor.com
Suite 135 | | www.XProgramming.com
Vernon Hills, IL, | Training and Mentoring | www.junit.org
60061 | OO, XP, Java, C++, Python |
Sounds like very straightforward advice. I shall try that. Thanks.
This also sounds like a good exercise for trying out other programming languages
like Perl, Python, C#, Haskell, etc. (still haven't found much info regarding
TDD w/ FP, though).
> Here's an exercise that will take you a few hours, and will teach you
> what you want to learn. Write the game "Hunt the Wumpus". This is a
> very simple game from the 70s that people used to write in Basic on
> their Apple II or TRS-80, or Commodore 64.
>
> Play it here: http://www.taylor.org/~patrick/wumpus/
>
> As I said, write this game. HOWEVER, write absolutely no user
> interface code! Write test cases that check to see that every
> function works. Also write test cases to make sure that the program
> knows what messages to emit and the right times. However, do not
> include the strings of the messages, and do not emit the messages on
> any device. Instead, write an interface (in Java) that has methods
> for emitting the appropriate messages, but have the tests implement
> the methods simply to verify that they were called at the right time.
> Do not write code that reads commands from the user. However, *do*
> write tests that invoke the functions that such commands would invoke.
>
> I've done this exercise a few times, and it's always *very* revealing.
> You can write the entire game without any UI. You can get the whole
> game working without every playing it. And then, finally, as the very
> last step, you can write the UI itself. You'll find that writing the
> UI is trivial once you've gotten the whole rest of the program
> working. You'll realize that you have thought through lots of issues
> that make the UI simple to create. And yet the UI will be completely
> decoupled from the game. The game won't care about the UI at all.
A "Representation Layer" turns one representation into another. In the above
exercize, the Wumpus Layer may have an object model the user would not
expect. The goal is to write a Representation Layer that has an object
module an end-user would recognize, if they grokked its notation.
--
Phlip
http://www.c2.com/cgi/wiki?TestFirstUserInterfaces
>A "Representation Layer" turns one representation into another. In the above
>exercize, the Wumpus Layer may have an object model the user would not
>expect. The goal is to write a Representation Layer that has an object
>module an end-user would recognize, if they grokked its notation.
I don't think so. I don't care if the end user groks the internal
representation. I want the internal representation to be convenient
and obvious to the programmers, not the end user.
The facade of the representation layer that the GUI layer uses can do
anything the GUI can, the same way it does it. Where the GUI picks from a
list, the representation layer indexes an array; same thing.
I think that has been said before, somewhere.
In this case (so far as I grok Wumpi), the two functions would be
shootAtTheWumpus(x,y) and move(x,y).
--
Phlip
http://www.c2.com/cgi/wiki?TestFirstUserInterfaces
Status update...
I plan to follow Bob's advice about Hunt the Wumpus, but I found I needed some
even more pedantic help to get me started since I'm new to Java, JUnit, and TDD
all at the same time!
I found an answer at xp123.com/xplor/xp0201.
With this challenge, I start with tests that someone else has already written
(one at a time - no looking ahead), and follow all of the other incremental TDD
rules. This way I get to see what a good progression of simple test ought to
look like before I try to start writing my own tests on my subsequent Hunt the
Wumpus exercise.
> I plan to follow Bob's advice about Hunt the Wumpus, but I found I
> needed some even more pedantic help to get me started since I'm new
> to Java, JUnit, and TDD all at the same time!
>
> I found an answer at xp123.com/xplor/xp0201.
>
> With this challenge, I start with tests that someone else has already
> written (one at a time - no looking ahead), and follow all of the
> other incremental TDD rules. This way I get to see what a good
> progression of simple test ought to look like before I try to start
> writing my own tests on my subsequent Hunt the Wumpus exercise.
It's a nice exercise. I already had some experience doing TDD when I tried
it, though. I found that I prefer to work in even smaller steps than the
exercise seems to propagate - so if you get stuck or find that it takes more
than a few minutes to make a test run, try to break them down further!
Regards, Ilja
As an example, I would probably implement the five blocks in
testThatNumericCellsAreIdentifiedAndStored one after the other.
Regards, Ilja