This posting is part of the Silverlight HyperVideo Platform documentation and a Silverlight Mini-tutorial. The information in this posting, however, should be of interest to anyone writing meaningful Line of Business applications with Silverlight.
The premise of the classic 1956 film Invasion of the Body Snatchers is that there are “pod people” among us, who are converting “normal” people into pod people one by one.
“Once you are a pod person, you think everyone should be one”
Once you begin seeing the benefits of TDD you tend to evangelize; its working great for you and you want everyone to become one. This can be helpful, annoying or alarming depending on who you’re talking to. My daughters, for example, are quite sick of hearing about it.
“They’re here already! You’re next! You’re next!”
It seems reasonable to many developers to create unit tests for their code; but the presumed high cost of doing so implies for waiting for a project that is not in “crunch mode.” Most developers will be waiting a long, long, long time.
Experience indicates that TDD actually saves time – you spend less time debugging and more time coding. Unfortunately, that sounds like “a good theory” and we all know that In theory, theory and practice are the same,
But in practice, they never are.
The bigger problem is Isaac Newton. Most of us suffer from Newton’s first law (significant inertia) and when confronted with an evangelist, we are governed by his third law (the more you push, the more I push back.)
“Give Up! You Can’t Get Away From Us! We’re Not Going To Hurt You!”
That said, for the past few years I’ve had the nagging sense that I was missing something important. Especially given that some of the folks I respect most in the industry were strong proponents; not least my mentors in all things good: RMSquaredF: Robert (Uncle Bob) Martin and Martin Fowler who laid the ground work and established best practices in their seminal works Refactoring: Improving the Design of Existing Code (Fowler) and Clean Code: A Handbook of Agile Software Craftsmanship (Martin). In the latter book, Robert Martin summarizes his approach which I paraphrase here:
- Don’t write production code until you’ve written a failing unit test
- Write just enough of a test to fail.
- Write just enough code to pass the test
What you are aiming for is about a 30 second cycle of write-test, write-code, Run-test.
Uncle Bob’s premise is that you tremendously reduce your risk and thus your fear because your production code never gets ahead of what you know; and you know it because you’ve tested for it.
“I Don’t Want Any Part Of It.”
“But You’re Forgetting Something….. You Have No Choice.”
A second premise of folks who evangelize TDD is that you really have no choice; it is a case of “pay me now, or pay me later.” Either you create the unit tests or you spend that much time and a good deal more on debugging.
The Silverlight HyperVideo Platform project offered the ideal opportunity to take on TDD, and the only way to do so was by Fiat. Thus, I made the executive decision to require unit tests for all code checked into the project (not hard to enforce so far, as at the moment all the code in the project is mine).
“The words, the gesture, the tone of voice, everything else is the same, but not the feeling.”
The rules for writing good tests are very similar to writing good code, but with a couple extra requirements. Stealing again from Robert Martin, here is a paraphrase of the good-test rules developed at his company, Object Mentor:
- Test must be quick. The slower a test runs the less likely you are to run it.
- Tests must be independent of one another; any side effects or dependencies must be avoided
- Tests must be repeatable: running the same test against the same code base must give the same results
- Tests must return unambiguous results
- Tests must be isolated from the production code
Configuration – ViewModel Objects
I published a plan for configuration that made use of Xaml files. I realized yesterday, in one of those forehead slapping moments, that a design that relies on placing configuration files on the client of course will not work due to access limitations. No harm done: the Xaml files were just a mechanism for creating the configuration business objects; and there are natural server-side analogs.
|We’ll use the Xaml file approach for enabling the user to maintain the state of the program when suspended or shut down (using local storage), post V1.|
The working design now looks like this (using a relational database for persisting the configuration information, and WCF-RIA Services for moving the objects to the client. (A forthcoming blog entry will walk through that aspect of the implementation in detail)
(Click on image for full size)
Links Vs Units
Links are a unique identification of a Unit, and Units are not represented by a class. A Unit is a set of Items (and the selected item), each item’s set of topics (and the selected topic) and each item’s set of links (and which links are currently displayed). Notice that units are identified by a URL. In V1 the selected item and selected topic are the first in the set, and this design is used only for configuration.
After v1, we’ll move from read-only to read-write, allowing the user to persist the current unit and to recreate the state of the application at a later time.
From Tables To Objects
The diagram above was created to show how the RDB would work, but it is a bit misleading. What we really want is not tables but rather objects. There is a very small jump (in this case) from the tables to the business objects as shown here:
There are a number of advantages to creating these objects, the most significant of which is that I can go ahead and implement the configuration without regard to how these objects were created, providing two implicit benefits:
- I don’t have to get all the WCF Ria Services code working before I can make configuration work and…
- The design now allows me to substitute virtually any persistence mechanism (database, Xaml configuration files, etc.) to back these business objects.
Further, these objects are part of the ViewModel, and facilitate binding the View to the ViewModel (as discussed in my mini-tutorial on MVVM).
We’re now (finally) ready to implement this, and as an experiment in open, honest and direct explanation I’m going to do this in real time, documenting my experience of creating the Unit Tests and the classes and their methods as I do it.
The great advantage of testing first is that it forces you to think about what the ideal API would be to each of your classes.
The Configuration Objects
The first implementation issue is this: I already have the following objects in the project:
It isn’t clear if the existing Item, Link and Topic (location) classes can be used for configuration, and I have a nagging feeling that I want something more. But here is where Agile development comes to the rescue: Design for what you need right now.