Agile UI
Well, I'm been talking for quite a while about the problems you get when you get into when you're trying to build User Interface using Test Driven methodology. The main problem seems to be that in order to do TDD properly, you need to test things which are inherently difficult to test.
Add that to the fact that in .Net, most controls duplicate the displayed data, which means that it's easy to just start using the UI as the backing store for you data and you get a situation that it hard for testing and hard for doing agile work.
Right now I'm doing UI work in the following way:
- Build the visible UI as simply as possible - this usually means using the form designer.
- Create an inner class named Context which manage all the logic for the form. As a side affect, this class hold no state, which make it good for threading, but I'm not using this yet.
- Wrap any data that the Context need with a property and make sure that it's accessed in a non UI-bound way.
For example, if the form display a TextBox which should contain the user's name, the form expose a property:
{
get { return usernameTextBox.Text; }
set { usernameTextBox.Text = value; }
}
- Generate an interface (I just love ReSharper) for the required functionality from the UI.
- Test the Context class against the interface.
This way allows you to still use the UI Designers, which can save quite a bit off work, and still maintain indefence in the logic from the UI itself. Later, I could move the context class to a Controller, but currently I don't feel the need.
What I do find is that code that works for Unit Testing sometimes produce code that is easy to test, but not to use. This is mainly because I'm not thinking through the tests, and I end up with code that is hard to work with. The advantage is that it's usually minor changes, and can be safely done with the tests existing. I made some big modifications (to the architecture of the application) and managed to carry them safely and easily with the tests that I've. I also began to fix problems by first writing a failing test, I caught myself this way several times already, and I know that what I would've done without tests would have only made it harder to find the error.
One of the drawbacks of this appraoch, however, is that I'm no longer using Test First approach. I first do a rough model, and code some basic functionality, and then test the logic behind it. Currently, I'm in discovery mode, meaning that I look at the UI, see what can be done, and then I do it. But when I'll move to more familiar area, I don't see why I can't do it in Test First way.
One thing I'm not sure of is how to store the data in the UI objects themselves, it does not sit well with me that I store it all in the controls. But considering that I usually work with something like this:
{
string Username { get; set; }
SecureString Password { get; set; }
string Email { get; set; }
}
I don't see much Evil in doing it this way.
Any ideas?
Comments
Comment preview