Friday, September 19, 2008, 9:16:18 AM, you wrote:
> Another addition could be to write a simple Template Engine in TDD.
Interesting choice. Back in 2003 I wrote a series of articles on
TDD for the Java Ranch Journal which worked through that very topic.
See http://blog.punchbarrel.com/2008/09/20/the-friki-way/ for a
collection of links to the articles.
> Some requirements :
From a pure TDD perspective I am a bit surprised by the prescriptive
nature of these "requirements"
> - Should evaluate template single variable expression.
I agree with this as a test case but I don't see it as a particularly
useful place to start. Personally I would have started with a much
simpler test more like:
assertEquals("", templater.evaluate(""));
then followed with something like
assertEquals("Hello", templater.evaluate("Hello"));
before ever getting to the case with a template expression in it.
Both of these tests serve to help drive the structure of the solution,
and they are both perfectly valid (and even potentially common)
cases.
Interestingly, the simple nature of these tests has driven a slightly
different design already. These cases have not needed any source of
values to substitute, so no such source was supplied.
By the time we do get to needing a source of named values it is much
more obvious that we actually have several choices, including:
* change the method signature to supply a source of values (which
requires going back and fixing compllation failures in the existing
tests.)
* keep the existing simple signature and provide the values another
way (in a constructor or a separate "setter" method, for example.)
* add another method alongside the existing one which does take the
source of values as a parameter (but this feels a bit like
duplication.)
At this point I have grown to like the expressive simplicity of the
tests so far, so my personal preference would probably be to supply
the value source in a constructor parameter to the templater. YMMV,
of course.
My point is that if we start with your first test, we are already
imposing some design choices which would probably be better
test-driven, especially in a tutorial example.
I'm also slightly puzzled by the syntax you have chosen
The first test imples that the template expression syntax is {$name}
> mapOfVariables.put("name","Cenk");
> templateEngine.evaluate("Hello {$name}", mapOfVariables); should
> evaluate to "Hello Cenk"
The second test implies that both {$name} and ${name} are acceptable
(which may be what you want, but seems overly complicated for an
introductory example)
> mapOfVariables.put("firstName","Cenk");
> mapOfVariables.put("lastName","Civici");
> templateEngine.evaluate("Hello {$firstName} ${lastName}",
> mapOfVariables); should evaluate to "Hello Cenk Civici"
The third test follows the syntax from the first test and drives some
useful behaviour
> map empty
> templateEngine.evaluate("Hello {$firstName} ", mapOfVariables); should
> throw missingvalueexception
The final test then confuses this completely by mixing the two syntax
types in a non-intuitive way. On the surface it would seem equally
valid for "Hello ${$name}}" to evaluate to a missing value exception
for "$name" or even for "$name}", or perhaps to "Hello $Cenk}" given
the mis-matched brackets.
> mapOfVariables.put("name","Cenk");
> templateEngine.evaluate("Hello ${$name}}", mapOfVariables); should
> evaluate to "Hello ${Cenk}"
I'm guessing that this confusion is probably due to typos in the test
cases. However, I still feel that jumping from the first three cases
to the fourth is too large a step. Before then I would have probably
coded tests for partial template expressions such as "Hello $",
"Hello $name", "Hello {", "Hello {}", "{$", "{$}", etc.
For me TDD is about learning from each step, while making the steps as
small and quick as possible, so that the understanding gained from
each step may be applied as soon as possible.
I would hope that such values would be communicated in a tutorial
example.
Frank.
--
Frank Carver frank@... http://www.efsol.com