User Interfaces and TDD

I was having a conversation with a colleague of mine the other day. We were talking about user interfaces and how a sketch of what the interface should look like would help him have a clearer picture of the design. This is not that odd. Many use the same technique to show customers what a possible interface of the end application could look like. The customer can then evaluate whether he/she likes it or prefers to change some detail (and it's never just a color). 

For this purpose, some use designer tools to sketch out a user interface, while others work with development tools hoping that they don't have to throw out the prototype they printed on paper to show the customer.

image

A few decide to make hand-made sketches because they believe showing the customer a WinForm/WPF/PNG can mislead them into believing that the work is nearly finished. If that is the case, educate the customer, don't blame the "messenger" (be it whatever electronic format).

image

 

Irrelevant of the technique used, many see this as a natural process; it's not peculiar or odd to show a customer what the user interface might look like, despite the fact that behind that user interface there is no functionality.

 

 

Take the previous search screen. It was displayed to Joe (a fictitious customer) and he decided he didn't  like it . He said he preferred to have to click on a Search Records button which then would pop up another screen where he would fill in the data and then hit Search (Joe was having a bad day).

image

 

The developer took the feedback into account and designed this particular functionality (not what Joe wanted but what the developer thought Joe really needed). Is there anything wrong with that approach? No. It is perfectly valid. Customer feedback is a good thing, especially when it's really taken into account.

 

Now let's change roles. Let's make the customer be the developer and the user interface be a specific class. What is the developers's user interface to that class? It is the API of the class. It's the properties and method calls. The requirement of class, much in line with that of the form, is to search for particular customers based on a series of fields and return a list of them.

The developer starts out by designing the API like so:

   1: public class CustomerSearch
   2:     {
   3:         public ICollection<Customer> Search(string name, string surname) {
   4:             
   5:             // Call database
   6:             // Add search conditions
   7:             // Filter records
   8:             // return records
   9:  
  10:             return new Collection<Customer>();
  11:         }
  12:         
  13:  
  14:     }

[At this point, you must be wondering WTF is this all about? To be honest, I've lost track myself, but let's hold the thought for a moment…] 

The developer, Jack, then starts to use the interface and as he's a good developer, his first real usage of the interface is a test. As he's writing the test, he realizes that he's made a mistake. He's limited the Search method to two fields, and the customer record has five fields. He then goes back to the class and changes the method to use specifications.

   1: public class CustomerSearch
   2: {
   3:         
   4:     public ICollection<Customer> Search(Criteria criteria) {
   5:     
   6:         // Call database
   7:         // Add search conditions
   8:         // Filter records
   9:         // return records
  10:  
  11:         return new Collection<Customer>();
  12:     }
  13:     
  14:  
  15: }

He then changes the whole code to implement the new functionality. Once he's happy with the result, he then returns to the test and starts to write the test, happy that he's accomplished his objective. Problem is, he threw away 2 hours of work by not thoroughly thinking through the requirements.

But you must be thinking why he hadn't thought of this beforehand. I mean it is pretty obvious, specially if you've done this before. The reason is that you don't know it all up front. It's only when you start using something that it "hits" you. Just like customers don't know everything up front, and they ask for changes as they start to use the program, as developers we don't know it all up front either. As much design as we try to do on paper, it's not until we actually start to use our code that we find we need to change our design.

 

 

Jack could have skipped the first implementation altogether. He could have started using the interface before implementing it completely. Wait a second. How could he use the class before it existed? Well let's think back. What was Jack's usage? He started writing his test like so…

   1: [Test]
   2: public void CustomerSearch_When_Name_Is_Joe_Should_Return_All_Customers_Named_Joe()
   3: {
   4:     CustomerSearch customerSearch = new CustomerSearch();
   5:     
   6:     customerSearch.Search(....    
   7: }

It's when he started writing Search when he realized that he only had two fields and that a customer could have up to five fields. This is where he realized he needed more fields, and the initial design of passing in field names was not very scalable.

 

Welcome to Test Driven Development

If Jack had started to use his own code before implementing it, he would have realized his shortcomings. Here is where TDD comes into play. TDD is not about writing your unit test first, it's about designing your code. It's about you, as the user, defining your user interface. Much in the same way we sketch out a user interface for the customer to give his feedback before we implement the functionality, writing tests is defining the calls you need for your classes before implementing them. As an added value, you end up with a test so that as you re-factor your design to suit your needs, you can validate the functionality.

 

I know this is old news to many, but still to date, it amazes me at the amount of developers that still think that Test Driven Development is about writing tests first. It is, but not to have your test, but to define your usage.

 

 

 

5 thoughts on “User Interfaces and TDD

  1. Ken Knopfli

    Then rename it. Call it Usage Definition Driven Development. In UML our starting point is normally the Use Case.

    Reply
  2. Hadi Hariri

    @Ken,

    I didn’t invent TDD or the naming. In any case I don’t see a problem with Test. Test is a use case and it clearly allows you to define the API.

    Reply
  3. Ken Knopfli

    I was just trying to point out that, if the term "Test" is used to describe something that in the more widely known UML methodology is called a "Use Case", it shouldn’t be too surprising that people make the mistake.

    I appreciate you didn’t invent it, I just assumed you might be in a position of some influence.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s