Wednesday, May 06, 2009

Why BDD? Can it help me?

I've been watching a lot of people arround me and on the internet talking about BDD. Of course as alwars, some were more extremist and said that TDD is dead, and BDD is much better. 

Why is BDD needed, in general?

Most people develop code, and design, mainly on the simple tasks, by exploration. They write some code, see if it works, refactor it, make it better, then if it still doesn't work they sit down and think of a better solution. After this 3rd stage the real thinking is needed. This fact comes from human nature and the fact that most of us like to do things with the minimum effort required. Unfortunately, writing tests first, moves the real thinking phase ahead, thus making it more unconfortable, because the first thing you need to do is to think how to design the test that will design your code. This isn't as simple as just starting to type code then seeing if it works. So, conslusion one would be that writing tests first, is harder, because it doen't allow the people to warm up, before being sent onto the pitch. 

On the other hand, it seems that there are still lots of people that do not make a clear difference between writing automated tests and Test Driven Development, where the tests are written first, and actually drive the way you're developing the code, making it usually smaller, and less dependent, as a general rule better. This fact has been noticed by some incredibly smart people, and they said maybe TDD is too abstract, and we need a simpler way to show people the philosophy behind it, so we need to simplify it and enforce somehow people to write the tests first, and let the the tests drive the way the code is written. So the second concusion is that, maybe TDD should be simplified, renamed, handed out to the masses, as Dan North (original developer of BDD concept) said:

I had a problem. While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.

Why do I need it?

After practicing TDD for many years, I saw one drawback, that kept coming to me: in time, I forgot what they did, and sometimes I needed lots of time to understand them again. Unfortunately for this there isn't a solution:

 - small easy to understand unit test: If you develop lots of small unit tests, lots means that you have to read a lot of them to understand what is there they test. The problem of quantity
 - test names very explicit: well, even this sometimes becomes a mess, especially with integration or functional tests, as the names become longer and longer (TestMaskMoveRotateZoomWithUndo() or TestAddMoveRemovePointOnMaskAndCheckDimentionsOnPanelWithUndo() )
 - comments: just like any other piece of code, tests need comments, and they seem to be the best solution to understand what they do. But just like code, people either forget about them, write something just to be there, or forget to update the comments when they update the tests or copy paste.
 - lack of clear flow in tests: preparation, action and verification phases: any good test has 3 steps. One where the context is prepared, then when something is done, and the third is the verification phase. However, there are tests where these 3 aren't easy to spot, and with integration/functional tests especially, because they tend to take time, there are many cases where some of the steps are repeated (add/edit/delete tests for instance, where there is a preparation phase, then action add, verify, action edit, verify, action delete verify). This makes the tests harder to read.

So what do I do?

It seems that BDD tends to solve all the above problems, changing the naming and making test first easier to understand, and my problem by making tests easier to be understood later. It is not perfect, but definately helps. 

But BDD is not just this, BDD is a lot more. BDD for the first time, allows or simplifies the real implementation of the acceptance tests. If you use XP, and you have stories, and for each you define acceptance tests with the customer (see sample http://danbunea.blogspot.com/2008/04/chapter-3-communicating-and.html), which means that both you and him understand them, because they use english and not c, java, ruby or c#, BDD allows you to write them in code very close to the way they are written on the story card. Now this is a breakthough:

Story: import images

The customer will be able to import and process images using the API. 

Acceptance test X:

Given an image over 20Mb
When the user imports it
Then the program should reject it for being too big

would be in code:

   [Test]
  public void ShouldntImportOver20Mb()
  {
        Image image = null;
        ImportResult result = null;
       "Given an image over 20Mb".Given(
         () =>
         {
                image = new Image("largeImage.jpg");
         });


     "When the user imports it".When(
        () =>
        {
             result = Importer.Import(image);
         });


     "Then the program should reject it for being too big".Then(
       () =>
       {
           Assert.Equal("Image is too big, over 20Mb", result.Message);
       });
  }

Now this isn't any fancy BDD framework, but a simple string Extention methods, proposed by Mihai Lazar (brilliantly simple idea), which despite the simplicity of the test, allows me to read easily what is going on, see clearly the flow and see the real correspondence with the acceptance test in the story. 

Conclusion

The example above is too simple, to allow real advantages over TDD, because as a unit test it would be:

   [Test]
  public void ShouldntImportOver20Mb()
  {
           Image  image = new Image("largeImage.jpg");
            ImportResult result = Importer.Import(image);
           Assert.Equal("Image is too big, over 20Mb", result.Message);
  }

which is fairly simple to understand, but what if it were more complicated:


  [Test]
  public void Test2AddMoveRemovePointOnMaskAndPanelDimentionsWithUndo()
  {
  ViewShape view = DragDropShape();
  ShapeEditorControl ctrl = (ShapeEditorControl)view.FindName("shapeEditor");



  int pointsBefore = ctrl.CurrentOption.Points[0].Count;

  //simulate adding new point near to first point
  Point newPoint = new Point(ctrl.CurrentOption.Points[0][0].X + 1, ctrl.CurrentOption.Points[0][0].Y + 5);
  ctrl.InsertThumb(newPoint);


  Assert.AreEqual(pointsBefore + 1, ctrl.CurrentOption.Points[0].Count);
  Assert.AreEqual(1, ctrl.CurrentOption.UndoActionsCount, "added one undo action");

  //move
  Point pointBefore = new Point(ctrl.CurrentOption.Points[0][0].X, ctrl.CurrentOption.Points[0][0].Y);
  Thumb thumb = ctrl.Thumbs[0];
  thumb.RaiseEvent(new DragDeltaEventArgs(3, 3));
  thumb.RaiseEvent(new DragCompletedEventArgs(1, 1, false));

  Assert.AreEqual(pointBefore.X + 3, ctrl.CurrentOption.Points[0][0].X);
  Assert.AreEqual(pointBefore.Y + 3, ctrl.CurrentOption.Points[0][0].Y);
  Assert.AreEqual(2, ctrl.CurrentOption.UndoActionsCount, "added two undo actions");

  ctrl.IsTestMode = true;
  //delete
  MouseButtonEventArgs mbea = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left);
  mbea.RoutedEvent = Mouse.MouseDownEvent;
  ctrl.thumb_MouseDoubleClick(thumb, mbea);

  Assert.AreEqual(pointsBefore, ctrl.CurrentOption.Points[0].Count);
  Assert.AreEqual(3, ctrl.CurrentOption.UndoActionsCount, "added 3 undo actions");


  //Undo
  ClickUndo(view);
  Assert.AreEqual(pointsBefore + 1, ctrl.CurrentOption.Points[0].Count);
  Assert.AreEqual(2, ctrl.CurrentOption.UndoActionsCount, "undone delete");

  //undo
  ClickUndo(view);
  Assert.AreEqual(pointBefore.X, ctrl.CurrentOption.Points[0][0].X);
  Assert.AreEqual(pointBefore.Y, ctrl.CurrentOption.Points[0][0].Y);
  Assert.AreEqual(1, ctrl.CurrentOption.UndoActionsCount, "undone move");

  //undo
  ClickUndo(view);
  Assert.AreEqual(pointsBefore, ctrl.CurrentOption.Points[0].Count);
  Assert.AreEqual(0, ctrl.CurrentOption.UndoActionsCount, "undone add");

  }


and now:

  [Test]
  public void Test2AddMoveRemovePointOnMaskAndPanelDimentionsWithUndo()
  {
     ViewShape view = null;
     ShapeEditorControl ctrl = null;
     int pointsBefore = -1;


     "Given the countour editor open for an image ".Given(
       () =>
       {
                   view = DragDropShape();
                   ctrl = (ShapeEditorControl)view.FindName("shapeEditor");

                 
  int pointsBefore = ctrl.CurrentOption.Points[0].Count;

       });


     "Adding a new point".When(
       () =>
       {
              Point newPoint = new Point(ctrl.CurrentOption.Points[0][0].X + 1, ctrl.CurrentOption.Points[0][0].Y + 5);
              ctrl.InsertThumb(newPoint);

       });

     "should have one more point, and possibility to undo".Then(
       () =>
       {
               Assert.AreEqual(pointsBefore + 1, ctrl.CurrentOption.Points[0].Count);
               Assert.AreEqual(1, ctrl.CurrentOption.UndoActionsCount, "added one undo action");
       });

     Point pointBefore=null;
     "and having a point".When(
       () =>
       {
              pointBefore = new Point(ctrl.CurrentOption.Points[0][0].X, ctrl.CurrentOption.Points[0][0].Y);
       });


     "when moving it".When(
       () =>
       { 
                 Thumb thumb = ctrl.Thumbs[0];
                  thumb.RaiseEvent(new DragDeltaEventArgs(3, 3));
                  thumb.RaiseEvent(new DragCompletedEventArgs(1, 1, false));
       });

     "should be in another position".Then(
       () =>
       {  //move
              Assert.AreEqual(pointBefore.X + 3, ctrl.CurrentOption.Points[0][0].X);
              Assert.AreEqual(pointBefore.Y + 3, ctrl.CurrentOption.Points[0][0].Y);
              Assert.AreEqual(2, ctrl.CurrentOption.UndoActionsCount, "added two undo actions");    
       });

     "when deleting it".When(
       () =>
       { 
              ....
        });
     "should be gone".Then(
       () =>
       { 
              ....
        });

     "clicking undo".When(
       () =>
       { 
              ....
        });
     "should have the deleted point back".Then(
       () =>
       { 
              ....
        });

     "re-clicking undo".When(
       () =>
       { 
              ....
        });
     "should move the point back at initial position".Then(
       () =>
       { 
              ....
        });

     "clicking undo".When(
       () =>
       { 
              ....
        });
     "should get rid of the added point".Then(
       () =>
       { 
              ....
        });


  }

which now looks like a scenario, making it simpler to follow and understand how the application  should behave in this case.

It seems, as a final word, that the first and most productive property of BDD, is that the description of the behavior of the application suddently is in english, and could be read (if you just output the strings on the console) even by the customer. A great leap forward, at least for me. 



Labels:

Friday, May 09, 2008

CHAPTER 6: Quality and Testing

6. Quality and Testing

6.1 Internal and external quality of a system

Defining what quality is in software development, means following the two perspectives of the main stakeholders involved in a software project: the customer’s perspective and the programmer’s perspective.

If we look at defining software quality from the customer perspective, we realize that what the real user sees and feels when interacting with the software, defines the quality. Mary and Tom Poppendieck call it perceived integrity, Martin Fowler and Kent Beck call it external quality of a system.

A wonderful example, regarding external quality of a system, is given in “Lean Software Development: An Agile Toolkit” [], written by Mary and Tom Poppendieck, about how everyone needs to contribute to quality and about how different people see quality differently:

Walt Disney designed Disneyland as a giant stage where several hundred actors make it their job to be sure every guest has a wonderful time. One guest's requirements for having a wonderful time are quite different from the next, and the actors are supposed to figure out exactly what each guest thinks a quality experience should be and make sure he or she has it.

Quality at Disneyland

At Disneyland, even the tram drivers are actors. A friend told me the story of a tram driver who noticed a small girl crying on her way back to the Disneyland hotel. He asked her why she was crying and found out that the crowd around

Mickey Mouse was too large, so the girl had not been able to talk to Mickey.

The driver called ahead, and when the tram arrived at the hotel, there was Mickey Mouse, waiting to meet it. The girl was thrilled, and the driver had done his job of making sure she had a quality experience.

—Mary

Looking at a software product, only from the programmer’s point of view, means mainly looking at the maintainability and extensibility sides and not only if the program respects design patterns or object oriented principles. A software program is of high quality, or it is considered to have a good design or architecture, if it can be modified, adapted and extended with ease.

Martin Fowler and Kent Beck describe internal quality:

… internal quality. This reflects the quality of the internals of the system: how well it is designed, how good the internal tests are, and so on. This is a very dangerous lever to play with. If you allow internal quality to drop you'll get a small immediate increase in speed, rapidly followed by a much bigger decrease in speed. As a result you must keep an eagle eye on this lever and make sure it is always up as far as it can go. Nothing kills speed more effectively than poor internal quality.

[Planning Extreme Programming]

Mary and Tom Poppendieck extend the concept of internal quality to conceptual integrity:

Conceptual integrity means that a system's central concepts work together as a smooth, cohesive whole. The components match and work well together; the architecture achieves an effective balance between flexibility, maintainability, efficiency, and responsiveness.

[Mary and Tom Poppendieck, 2003]

6.2 Automated tests

It is not testing alone that leads to high quality but the constant focus on maintaining quality at its highest, all the time. Traditional processes tend to confuse quality with testing, and although a lot of time is allocated for testing, is the testing phase is left to be the last stage in the process.

Agile processes have developed techniques to maintain focus on the high quality all the time, the most important being continuous integration. At the base of these principles stand automated tests, acceptance tests (defined with the customer) and unit tests that are run frequently giving feedback to the programmers about the quality status of the system. Keeping all tests running at 100%, and having a good coverage of automated tests on the system, focuses the team on quality and detects breaks early so they can be fixed fast before they eat out trough the system.

Automated tests, continuous integration, refactoring and customer involvement, combined with the focus on quality that needs to be delivered at the end of each iteration, ensure that the system’s integrity is built in and maintained all the time, from the beginning to the end.

6.3 Test Driven Development

Ron Jeffries expresses the Test Driven Development paradox, very well:

Writing code and tests is faster than writing just the code, if the code has to work.

Now let’s see if this is true:

The mini TDD experiment

To demonstrate the concepts around test first approaches and test driven development, we will make a small experiment. We assume that we are programmers and we need to code a function that divides two positive numbers. For this experiment we will compare the traditional and the TDD approaches.

Approach #1. Code and fix

As programmers, for a simple division we will write the following “pseudo” code:

Function Divide(No1, No2)

Return No1/No2

For this very simple method, let’s assume we needed 5 seconds to write it. Now let’s test if it works. First we try 6 and 2, expecting 3. It works. Let’s try another combination: 1 and 2, expecting 0.5. It works. Now let’s try 8 and 0. An error just occurred. This means we need to modify the program to display a message to the user that the second number cannot be 0:

Function Divide(No1,No2)

If No2 = 0 then display message “Division by 0 cannot be performed”

Else Return No1/No2

Now let’s test our function again. 6 and 2, result 3, good, 1 and 2, 0.5 as expected, 8 and 0 and a message “Division by 0 cannot be performed” occurs as expected. Now, our program works fine.

Assuming that manual testing is slow and for each combination of numbers we need about 10 seconds, this means that a testing session takes 30 seconds. The total time in which we developed the code was: 5 seconds to write the function, 30 seconds to test and see it has problems with division by 0, then about another 5 to correct the function and 30 minutes to test it again and make sure it works: total 5+30+5+30=70 seconds, a minute and 10 seconds.

Approach #2: Test Driven development

In test driven development, there are a series of steps to write a piece of code, starting with and automated test written first and ending up making that test succeed, by writing the code that it tests. Let’s see how it goes:

Function TestNormalDivision()

Expect 3 as a result of Divide(6,2)

The code above compares the value expected and the value returned by our (yet unwritten code) and if they do not match it fails.

One very important step now is to make sure our test really tests something and it does not work every time, no matter what the code under test does. So for this we need to make sure that when it needs to fail, it fails. So we write the following function:

Function Divide(No1, No2)

Return 0

Now we run the test, and it fails saying: expected 3 but the result was 0. So now we modify the function to return pass the test.

Function Divide(No1, No2)

Return 3

Now we run the test again: 1 test succeeded. Excellent. Now let’s see if it works for 1 and 2, so we update the test:

Function TestNormalDivision()

Expect 3 as a result of Divide(6,2)

Expect 0.5 as a result of Divide(1,2)

We run the test. Failure. Oooh, we just realize the mistake we made (code always returns 3) and modify the Divide function:

Function Divide(No1, No2)

Return No1/No2

Running the test, now passes all our expectations. But now we think, what would happen if we used 8 and 0. Let’s add a new test to the test suite (now we have two) and make sure that if there is division by 0, the user is notified:

Function TestDivisionByZero()

Expect message “Division by 0 cannot be performed” displayed as a result of Divide(8,0)

We run the test. It fails. Now we modify our function to make it work:

Function Divide(No1,No2)

If No2 = 0 then display message “Division by 0 cannot be performed”

Else Return No1/No2

Running all our tests, we discover that they all succeed.

How much time did we need to write this code? We needed 5 seconds to write the first test, 5 seconds to make sure it fails, 1 second to run the test (now testing is done by the computer so we assume it should be at least 10 times faster then manual testing), 5 seconds to modify the code to make the test work, 1 second to run the test, another 5 seconds to extend the test to verify the 1,2 combination, 1 second to see that the test fails, 5 seconds to modify the function and 1 second to see it working, another 5 seconds to write the second test and 2 seconds to see the first test work but the second failing, and 5 seconds to complete the code and another two to run the 2 tests and make sure it works. Wow, a long way: 5+5+1+5+1+5+1+5+1+5+2+5+2 = 42 seconds.

Using both approaches, we ended up with the same code. The amount of code written for the second approach is bigger then for the first, having the code and the tests. The amount of time needed for the second approach was arguably smaller then the amount for the first approach, which leads us to Ron Jeffries’s conclusion: to obtain good code, writing tests and code is faster then code alone. The main advantage is that we use computer power to do the testing rather then human power, so we are much faster. Then we can run the automated tests over and over again and it will take 2 seconds to see if they work, manually it will take 30 to do the same thing.

Let’s go further with our experiment, assuming that now we need to extend the program to be able also to do addictions, subtractions and multiplications.

Approach #1. Since all these operation are not affected by 0, but we test that anyway, the code written first will work, so it would take about 5 seconds to write each method, and testing each with 3 combinations of numbers would result in about 30 seconds to test each. The amount of time, needed would be 5+30+5+30+5+30 = 105 seconds, 1 minute and 45 seconds. Testing the whole program (the 3 new methods and the division method) would take us 4*30 = 120 seconds, which is 2 minutes.

Approach #2. TDD

Operations just as above will need only one test, checking 3 combinations. Let’s say it takes 10 seconds to write a test method like this:

Function TestMultiplication()

Expect 0 as a result of Multiply(6,0)

Expect 3 as a result of Multiply(3,1)

Expect -9 as a result of Multiply(3,-3)

Then we’d have to make sure it fails: 5 seconds, 1 second to run the test, then we’d write the code to make it work: 5 seconds and 1 second to make sure it works, so it takes about 10+5+1+5+1 = 22 seconds for each new function, resulting in 3*22 = 66 seconds or 1 minute and 6 seconds to write the new functions. Testing all the code would mean running 5 test methods (2 for division and 1 for the other three), which would be run in 5 seconds.

Tests and code, faster then just code

Comparing the times needed to test our incredibly simple system: 2 minutes vs. 5 seconds show us that not only the code is written faster (110+105=215 seconds vs 66+45=111 seconds), but making sure it works requires far less time for the TDD approach. And second big advantage, it can be done by a computer.

Using a continuous integration machine that downloads the program sources and runs the test suite, then sends us an email telling us what happened, means 5 seconds for the machine and 0 seconds on my side to test the whole system. Using the first approach, would take me 2 minutes to make sure the whole system works. I could delegate this responsibility of testing the whole system to the testing team, but the feedback times, telling me whether the system works as a whole or not, increase rapidly to days and weeks and by that time I should be doing something else.

Scalability

In the 3rd phase of our little experiment, we analyze what would happen if our system would have 400 functions instead of 4. Using the first approach it would need about 12000 seconds (that is over 3 hours) for a full test, while using the TDD and automated testing suite about 500 seconds or, better said, less then 10 minutes. This simple sample shows us scalability when it comes to TDD vs traditional coding approaches. The testing team could work, to some extent in parallel, but after, all I could set my integration machine to divide the tests and work in parallel.

After making this very small experiment, we showed how test driven development is, compared with just coding:

- faster to develop

- faster to test the whole system and give feedback

- scalable

Tests as documentation

Another advantage of the method described above is that, the automated tests can act as a very good documentation of the code written. In traditional approaches, just documenting things that can be very easily deduced from the automated tests, like how a function works, would increase even more the development time. After all, just reading:

Function TestDivisionByZero()

Expect message “Division by 0 cannot be performed” displayed as a result of Divide(8,0)

tells me or someone new in the project, that if you try to perform a division by 0, the system will display an error message on the screen.

Embrace change: how?

Having a system with 4, 400, 1000…100.000 methods, doesn’t really comfort me when it comes to making a change in it. If I change one tiny piece of code somewhere, could I break something in another part of the system? And if I do, how could I know fast enough, to be able to either correct it or reverse my changes?

To have the feedback from the code, telling me if and where I’ve broken some existing functionality, I would normally need to retest the whole system. For a 4 methods system, it would take 2 minutes, but for a more likely system, it might take hours, days or even weeks. So the courage to change decreases with the system getting bigger, thus is shortening the life of the system. When a system is too rigid and can no longer adapt to the changes on the market, it is bound to die.

Having a full regression automated test suite, that runs very fast and can be run very often, means fast feedback. Fast feedback means changes are less risky and can be done easier and faster, thus extending the life of a system.

Design advantages

Another advantage of writing automated tests for the code is that the code written tends to be very loosely coupled, thus better designed. Test driven development also tends to eliminate “partially completed code”, encouraging less code to be written, as the programmer is more focused on what is really needed, thus decreasing the amount of code and its complexity.

At a macro level, the fact that changes, even in the architecture are much easier to be performed, when using TDD combined with aggressive refactoring, allows the programmers to continuously upgrade the design and update the architecture. Since the changes are easy to do, the evolutionary design technique is encouraged, having a much smaller need to build a flexible architecture upfront, following the YAGNI principle from XP.

How do we achieve external quality at 100% all the time?

After each iteration, a potentially shippable system is delivered, so quality is at 100%, every 2-4 weeks, maintaining this way the system at the highest level throughout its lifecycle.

Frequent releases that allow the customer representatives to see the system all the time are maintaining the project on the right path and at the right perceived quality. When the customer sees the software he can very easily spot things that are not according with what he thought they would be, and together in the next iteration these issues can be fixed. The focus on quality in agile development is mainly expressed by the iterative and incremental development model, which allows the stakeholders in a project to identify problems early and correct them as soon as they are found, thus maintaining the system on the highest quality.

As a small sample, we think about one frequent non-functional requirement: the system must be fast. In traditional testing techniques, the test and development teams had to figure out by themselves what fast means. This is a very difficult requirement to deal with, because it is almost impossible to measure. Presenting the system, after an iteration, to the customer, might let him say: “I want that report to be faster. At this time it needs about 10 seconds. Can you make it faster? Let’s say 2-4 seconds”. Suddenly, there is a clear definition on where “fast” applies, allowing the team to focus on solving a concrete problem. This is a simple sample, showing how perceived quality is maintained by the continuous collaboration and feedback between the customer and the team.

Who is involved in quality, how and when?

Everyone, all the time. In traditional systems, the responsibility for quality is mainly delegated to testing teams that must make sure the code is of high quality. Agile thinking makes quality a collective responsibility of the customer, the developers and the testers all the time from the first, to the last minute of a project.

The customer is involved in quality by defining acceptance tests. The developers are involved in quality by helping the customers write the tests, by writing unit tests for all the production code they write and the testers are involved by helping the developers automate acceptance (customer) tests and by extending the suite of automated tests.

Manual vs. automated testing

Manual testing is not forgotten, although in agile methodologies a great emphasis is put on automated tests. Manual testing is still performed. Agile testing is about balancing between the need to automate when it is beneficial and relying on manual testing when it is more efficient then writing automated tests.

How do we achieve internal quality?

Simplicity, unit tests running at 100%, refactoring, YAGNI, collective ownership, continuous integration combined with good coding techniques, are all practices that as a whole are aimed at maintaining the code quality at its highest all the time.

Regarding code quality and the simplicity principle, Ron Jeffries writes:

Everything we write must:

  1. Run all the tests
  2. Express every idea we need to express
  3. Say everything once and only once
  4. Have a minimum number of classes and methods, consistent with the above

[Ron Jeffries, 2001]

Friday, May 02, 2008

CHAPTER 5: Managing and Organizing

5. Managing and Organizing contents:

5.1 A small agile process practice sample
5.2 Iterative and Incremental process
5.3 Adaptive planning strategy
5.4 Evolutionary design strategy
5.5 Fast delivery strategy
5.6 People first strategy

5. Managing and Organizing

5.1 A small agile process practice sample

Let’s consider that we have a new client who wants a new software product to manage and track his sales and customers. He wants the system to go live in 2 months. We meet and establish what is required, then plan to meet the deadline.

After the first meetings we come up with the following feature list, that he thinks he wants, that is afterwards estimated by us:

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)
  4. Sales reports (3p)
  5. Client activity management (3p)
  6. User management (2p)
  7. Sales workflow (3p)

Now together with the customer, we make the first plan, dividing the work in two iterations:

Iteration #1: 10 p

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)

Iteration #2: 11p

  1. Sales reports (3p)
  2. Client activity management (3p)
  3. User management (2p)
  4. Sales workflow (3p)

As you can see estimates are given in an abstract measuring unit: points. We as the development team, know we can deliver about 10.5 – 11 point per iteration. After we have a plan to deliver the 21 points features in 2 months, we start working, by beginning the first iteration, at the end of which we deliver features 1, 2 and 3.

We now show the customer the first 3 features implemented, but he suddenly realizes that he needs more then what was planned for the release. We start by adding what he wants to the list of features, after that, each of the new features is being estimated.

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)
  4. Sales reports (3p)
  5. Client activity management (3p)
  6. User management (2p)
  7. Sales workflow (3p)
  8. Activity calendar (3p)
  9. Forecast reports (3p)
  10. Document templates and document merging (3p)

With the client, we realize that we cannot deliver all in the 2 months term, but we decide that we can still make a delivery after the two months and we plan another delivery after that, which will include other features that will make the system more compete. The new plan looks like:

Release #1: 2 months

Iteration #1: 10p

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)

Iteration #2: 11p

  1. Sales reports (3p)
  2. Client activity management (3p)
  3. User management (2p)
  4. Forecast reports (3p)

Release #2

Iteration #3: 9p

  1. Sales workflow (3p)
  2. Activity calendar (3p)
  3. Document templates and document merging (3p)

As you can see, the customer considered that it is more important to have the forecast reports in the first delivery, so he moved the forecast report into the second iteration and the sales workflow to the 3rd iteration.

After the second iteration is over, we have the features 1-7 finished, in 2 one month iterations, delivering on term what the customer wanted, and deploying it to be used by its end users.

At the beginning of the 3rd iteration, the customer realizes that he wants a few more things and he would like to have the delivery of the complete system, in another two months so he can fit his budget. He adds a few new features, having the following list now:

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)
  4. Sales reports (3p)
  5. Client activity management (3p)
  6. User management (2p)
  7. Sales workflow (3p)
  8. Activity calendar (3p)
  9. Forecast reports (3p)
  10. Document templates and document merging (3p)
  11. Contact communication management (3p)
  12. Microsoft Outlook integration (2p)

The plan now becomes:

Release #1: 2 months

Iteration #1: 10p

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)

Iteration #2: 11p

  1. Sales reports (3p)
  2. Client activity management (3p)
  3. User management (2p)
  4. Forecast reports (3p)

Release #2

Iteration #3: 9p

  1. Sales workflow (3p)
  2. Activity calendar (3p)
  3. Document templates and document merging (3p)

Iteration #4: 5p

  1. Contact communication management (3p)
  2. Microsoft outlook integration (2p)

After finishing and showing to the client the resulting product, having now 10 features out of 12 implemented, he realizes that there is one more feature he’d like to have, and that can be implemented in the last iteration: sales processes. The list of feature becomes:

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)
  4. Sales reports (3p)
  5. Client activity management (3p)
  6. User management (2p)
  7. Sales workflow (3p)
  8. Activity calendar (3p)
  9. Forecast reports (3p)
  10. Document templates and document merging (3p)
  11. Contact communication management (3p)
  12. Microsoft Outlook integration (2p)
  13. Sales Processes (5p)

And the updated plan:

Release #1: 2 months

Iteration #1: 10 p

  1. Client management (3p)
  2. Product management (3p)
  3. Sales leads management (4p)

Iteration #2: 11p

  1. Sales reports (3p)
  2. Client activity management (3p)
  3. User management (2p)
  4. Forecast reports (3p)

Release #2

Iteration #3 – 9p

  1. Sales workflow (3p)
  2. Activity calendar (3p)
  3. Document templates and document merging (3p)

Iteration #4 – 10p

  1. Contact communication management (3p)
  2. Microsoft outlook integration (2p)
  3. Sales processes (5p)

At the beginning of the 4th iteration the client says he’d like one more feature that is estimated by the team to be of 3 points. Adding that feature would mean not meeting the second release target, so after balancing the options he decides to drop it.

After the 4th iteration the final product is delivered. The sample above cannot show by any means how any project can be developed, but it shows the agile process at work, iteration by iteration, planning, adapting and delivering incrementally a product to the end customer.

The evolutive process of gathering the client requirements is shown below:

Building a burn down chart, showing iteration by iteration the number of remaining features to be implemented would be like:

5.2 Iterative and Incremental building

Iterations are the base of stability in agile methodologies. They are the ground for learning and adapting trough customer feedback. The iterations are the foundation of the whole adaptive approach used in agile processes.

Iteration properties:

1. Iterations give a close deadline, increasing focus and the need to organize inside the team

Since iterations are kept small (1-4 weeks) the deadline is very close, and as Ken Schwaber explains, the team must focus much better to deliver what is planned by that deadline. A big problem with traditional approaches is that focus is increasing as the deadline approaches:

Everyone in the development group had a lot to accomplish, so why wasn’t the whole department hard at work at 9 a.m.? The vice president observed that the team usually didn’t feel any pressure until three months before the release date and that members of the team started developing in earnest only during the last two months of the release cycle. Assignments at the task level, assignment of individuals to multiple teams, and particularly the waterfall approach all led everyone to feel isolated from the reality of the release during the first three or four months. During the last two months, the developers tried to make up for what they hadn’t completed in the first four months.

[Ken Schwaber, Agile Project Development with SCRUM, Service 1st sample]

2. Iterations are a good instrument for planning, tracking progress

The plan can be easily readapted at the end of each iteration to the customer’s needs. At the end of each iteration, a piece of the final product is shown to the customer, thus showing progress.

3. Iterations minimize risks

Agile thinking minimizes the risks because it always focuses on the most important and valuable features for the customer, developing them first. When they are delivered, the priorities for the remaining might have changed, so now, a new plan is made up, reprioritizing and delivering what is important now. In the next iteration, if reprioritization is necessary then it is used to plan what to do next.

4. Iterations are a good instrument for managing changes in software

At each end of an iteration, direction can be changed if it needs to, and plans adapted to the new needs.

5. Iterations are a good instrument to build trust

By showing the software after each iteration, the customer can see the product growing as planned, seeing progress being made, thus starting to increase his confidence in the development team and that the product will be delivered.

6. Iterations allow learning and adapting

Because the customer sees the results in iterations, he can better express his needs, learning about what can be done and learning about costs. On the other hand, the developers can learn what the customer’s needs are as the project is being developed.

7. Iterations are a good instrument for development

At the end of an iteration, a set of features must be shown working. This transfers the focus of the developers, which might be tempted to develop a system horizontally, layer by layer, from data access, to business layer and presentation layer, assembling the whole system at the end, to a vertical approach, where the focus is put on delivering working features, developing them vertically on all layers, and delivering them one by one.

8. Iterations are building confidence and motivation in the team

One very important aspect in development, especially in the early stages of a project is an early victory. By delivering the first iteration, the team starts to see something positive happening and starts to build confidence that it will win. With each new iteration, a new battle is won, getting closer and closer to winning the war.

9. Iterations bring honesty

Since iterations are short, and after each iteration, the customer sees the real product developed, delays are surfaced very early, not allowing them to grow into a huge problem.

10. Iterations are a good instrument to increase quality

At the end of each iteration, a potential shippable product must be shown to the customer. This focuses the team on keeping the quality high, never letting bugs and quality problems unhandled.

5.3 Adaptive Planning strategy

Kent Beck defines planning as:

Plans are not predictions of the future. At best, they express everything you know today about what might happen tomorrow. Their uncertainty doesn't negate their value. Plans help you coordinate with other teams. Plans give you a place to start. Plans help everyone on the team make choices aligned with the team's goals.

And he defines the planning strategy:

We will plan by quickly making an overall plan, then refining it further and further on shorter and shorter time horizons—years, months, weeks, days. We will make the plan quickly and cheaply, so there will be little inertia when we must change it. […]

The strategy for the team is to invest as little as possible to put the most valuable functionality into production as quickly as possible, but only in conjunction with the programming and design strategies designed to reduce risk. In the light of the technology and business lessons of this first system, it becomes clear to Business what is now the most valuable functionality, and the team quickly puts this into production. And so on.

[Kent Beck, 1999]

The big, high level, direction and goal establishing plan

Many critics of agile methodologies, claim that they sustain going directly in developing code, without any vision of the whole product that will be developed, implementing and delivering randomly features, that have no direction and can lead to a never ending process of development with no finished product ever being shipped. The truth is quite the opposite. Agile methodologies do emphasize the need for an overall vision of the product, but that vision must not be very complete from the beginning and can be shaped and changed later according to the necessities of the software buyer.

In all agile methodologies, software is delivered to the end users in releases, which usually take from 1 to 6 months, depending on the specifics of the methodology and of the project. These releases are divided into iterations, that do deliver potentially releasable software to the customers, but usually the results of the iterations are there to demonstrate progress, maintain a high level of quality and most of all, collect feedback from the customer representatives that supervise the development.

A Scrum project starts with a vision of the system to be developed. The vision might be vague at first, perhaps stated in market terms rather than system terms, but it will become clearer as the project moves forward. The Product Owner is responsible to those funding the project for delivering the vision in a manner that maximizes their ROI. The Product Owner formulates a plan for doing so that includes a Product Backlog. The Product Backlog is a list of functional and nonfunctional requirements that, when turned into functionality, will deliver this vision. The Product Backlog is prioritized so that the items most likely to generate value are top priority and is divided into proposed releases. The prioritized Product Backlog is a starting point, and the contents, priorities, and grouping of the Product Backlog into releases usually changes the moment the project starts—as should be expected. Changes in the Product Backlog reflect changing business requirements and how quickly or slowly the Team can transform Product Backlog into functionality.

[Ken Schwaber – Agile Project Management with SCRUM]

Since software is delivered to the end users every few months, it is very important that at first at least one release is planned, defining what will be developed in that release. In XP, this is called release planning, in SCRUM this is done trough the product backlog, in Crystal it is done by defining a product plan.

After defining the high level features of the product, the developers estimate them, mostly in terms of weeks and months, giving the customer or product owner, as it is called in SCRUM, the cost for each and then the possibility to act on those costs, by saying which features are the most important, which can be left for a later release or which can be dropped. After the customer prioritizes the features, they are divided into iterations to be developed, having the most important into the first iteration, with the next iteration developing the next and so on until the end of that release.

The main advantage of the agile approach is that the product plan is very flexible; allowing it to be at first, at a high level and allowing the customers to complete it as the program is being developed.

The small, detailed, short cycle plan

Once the high level plan is defined, it is high time to start working at the first iteration. An iteration is a small project, that goes trough all the phases used in traditional processes like: requirements analysis, design, implementing and testing phases. The result of an iteration must be a potentially releasable piece of software, delivering “running, tested features”.

The first step in an iteration, is the iteration planning meeting that is very well exposed by SCRUM sprint planning meeting, which has inspired the planning sessions that are used in other agile methodologies like the planning game in Extreme Programming or the blitz planning sessions used in Crystal. The main purpose of this meeting is to obtain the details of the user stories or backlog items and based on these details the team breaks them into programming tasks that are estimated again and based on these estimates (which are now much closer to reality) the team can commit to a list of features that will be developed in the current iteration:

At the start of an iteration, the team reviews what it must do. It then selects what it believes it can turn into an increment of potentially shippable functionality by the end of the iteration. The team is then left alone to make its best effort for the rest of the iteration. At the end of the iteration, the team presents the increment of functionality it built so that the stakeholders can inspect the functionality and timely adaptations to the project can be made.

[Ken Schwaber ]

In SCRUM, the sprint planning meeting is a one day meeting session, where the customer representatives and the team of developers all get together, in a meeting that is divided into two time boxed sessions of 4 hours. The first is the part where the details are exposed and the second part is when the developers can now estimate and commit.

In XP, where user stories are defining the functionality to be developed, each story is discussed with the customer, getting its details, then the programmers disaggregate the story into more programming tasks, and for each of these tasks a programmer accepts the responsibility to develop it, re-estimating the time needed to develop it in order to make sure he does not over-commit. As a sample, if we have a user story like: the user can search for contracts could be divided into the following list of tasks:

  • build search page
  • build advanced search page
  • display results screen
  • build the SQL database query for basic searches
  • build the SQL database query the database for advanced searches
  • document new functionality in help system and user's guide

Ron Jeffries recommends that the programmers commit to user stories rather then tasks, so that they commit to full pieces of functionality having a much clearer focus.

The most important of agile aspect techniques is that, the planning is a continuous collaboration and adaptation activity between the customer representatives and the team of programmers, where the customers define what needs to be done with the help from programmers and the developers estimate the cost and commit to doing it on their own estimates.

5.4 Incremental design strategy

In agile methodologies, the design strategy starts from two fundamental lessons learned while developing software:

  1. Complexity is very hard to manage
  2. Irreversible decisions are to be avoided in design

One of the big problems in software development is the managing complexity. The bigger a system becomes, the harder it becomes to change, to add new functionality to it or to maintain it. Starting from this assumption, the agilists have built a series of practices and tools that enable developers to manage the growing complexity in a software project easier and also help them take decisions that can easily be reversed.

Simplicity is at the very core of every agile methodology, as stated in the agile manifesto principles: Simplicity--the art of maximizing the amount of work not done--is essential. One of the principles, promoted especially by Extreme Programming is the YAGNI principle, or “You Ain’t Gonna Need It”. Its fundament comes from the fact that, in many projects, when creating a design before any code was developed, the need for a very flexible design is very strong. Often, those designs which had flexibility built into them, ended up with lots of parts never used, thus only adding to the complexity of the whole system. In other cases, the “bullet proof” designs, only contributed to making simple things harder to put in practice.

Traditional processes presume that the whole architecture and design of the software is developed before any code is written. Although the idea sounds good, in practice it has been proven that it is almost impossible to foresee all the needs in a software project. In other cases, this technique also known as BDUF (Big Design Up Front) failed even when a very good design was defined because it was impossible to code. Martin Fowler states that “UML-like design can look very good on paper yet be seriously flawed when you have to program the thing” continuing “even skilled designers, such as I consider myself to be, are often surprised when we turn such designs into software”. One of the biggest problems with BDUF is the fact that it is very risk prone to changing requirements, and thus exposing the problem of trying to build extra flexibility into the design, that ends up never used.

So if the design is not done up front, is it dropped and software is being developed in a “cowboy programming” manner? Martin Fowler, one of the most respected authors when it comes to design, architecture, patterns and UML wrote an article about evolutionary design called “Is Design Dead?” in which he explains how XP has built some methods to allow continuous design to be performed and adapted by continually focusing on the architecture and refactoring it to the needs little by little all the time.

Martin Fowler explains that XP has developed some enabling practices such as: test driven development, refactoring and continuous integration. Full automated test suites for the code enable refactoring of the existing code to be performed aggressively and continuously thus making the code simpler and easier to handle. Continuous integration is the technique that keeps the team is sync all the time and since built in focus is enabled by the iterations, daily meetings and reflective workshops, the code can be kept at the highest level of quality all the time, respecting the simplicity and YAGNI principles. This expresses how XP followers understand and support the “Continuous attention to technical excellence and good design enhances agility. ” agile principle.

Evolving an architecture is not the same as just letting the system grow in any shape that's convenient for the moment. Growing an architecture takes thought and discipline. We keep the architecture optimized for the current conditions. When those conditions change we refactor the architecture to keep it optimized.

[Robert C. Martin blog]

Even in the agile community, there are some continuous debates over the evolving architecture concepts, although most of the agile methodologies seem to favor and encourage this practice. One of the most known criticism of this approach is expressed in Doug Rosenberg and Matt Collins’s book: “XP Refactored: The case against Extreme Programming” [] where the authors publicly criticize the evolving architecture technique promoted by XP, favoring a design upfront technique, but which is quite different from BDUF technique because it is concentrated mostly of smaller pieces of the project, like an iteration, rather then on the whole project.

It is very important for the team using agile approaches to find the method that suites them best, either choosing to design a whole piece of the project in one go, concentrating on not falling in the BDUF trap, or choosing the evolutionary design practice, making sure they do see the whole, as recommended in the lean principles and refactor effectively.

Modeling is something encouraged by agilists all the time, from CRC cards, to system metaphor, UML sketches, drawn on the whiteboard, following the principle of sufficiency. Agile modeling concentrates on those techniques that bring value to their projects and customer and eliminate modeling (just like documentation) done without a very clear purpose, becoming a burden in time.

5.5 Fast delivery strategy

One of the most important aspects of agile thinking is that the result of an iteration must be working, tested software, and not anything else. There have been cases where organizations believed they have adopted agile practices using iterative and incremental processes, but they only masked the old waterfall model under an iterative one, building in the first few iterations the requirements, in the next iterations the design and so on. This breaks one of the most fundamental rules of agile and lean thinking: delivering valuable software as soon as possible.

Not delivering at the end of an iteration, especially in the first stages of development, a partially implemented part of the whole system, with a small list of features implemented, can become a major drawback in agile development. Not delivering software at the end of an iteration, minimizes the feedback that can be obtained from the customer, feedback that is at the base of the learning and adapting process sustained by agile movement. Not delivering software early, does not focus the team, making collaboration between team members less needed and does not contribute to building trust between the software buyer and the software vendor that is essential in agile development.

Another very important agile rule for early delivery, is that the features planned to be delivered in one iteration must be delivered at 100%, being defined, implemented, tested and ready for production. It is very important to have 8 features out of 10 planned, developed at 100% rather then 10 out of 10, at 80%.

Agile methodologies have built in practices to keep focus, all the time, at the most important thing to do, having the customer prioritize the features, having a very clear goal planned for the end of the increment that is usually very close and with the manager having as main purpose eliminating obstacles from the team’s delivery path and keeping the team focused in daily meetings designed exactly for this purpose.

In order to be able to deliver fast, the team must be able to always know where they are in development. The purpose of planning is to give the team a direction to follow, and to be able to calm them down by letting them know at all times where they are by comparing reality with the plan. If reality and the plan are different then either the team is off track or the plan is no longer valid. Agile, adaptive planning activities make sure the plan is continuously updated and adapted so it is always as needed.

Tracking activities to compare reality with plans are in agile methodologies very transparent, having big visible charts on the walls in XP, or burn down charts showing how much of the product backlog has been implemented and delivered in each iteration. With the variable purpose, the burn down chart, shows how the number of features varies over iterations and how many of them are implemented iteration after iteration.

When it comes to code, fast delivery can only be done by keeping the code in very good shape at all times. Complex and unhealthy code has been proven to slow team down very drastically as the amount of code grows, that is why in all agile methodologies, the code must be developed at the highest quality. The emphasize on automated tests tends to enforce loose coupling in code and simplicity and refactoring decrease complexity, continuously improving the design.

5.6 People first strategy

Building a team of highly capable and motivated individuals that work very effectively as a team is not an easy task to achieve, however agile methodologies expose several tools and practices:

a. People build software not processes

The focus must be put on people, letting themselves organize, letting them participate in taking decisions, with the most important tool of this being the ability to let the people estimate the tasks rather then having them estimated for them.

“Individuals and interactions over processes and tools”, is the first value in the agile manifesto, showing that it is not the tools and the religious following of a process that produces valuable software for the customer, over and over again, but the people developing it, self organizing and collaborating all the time.

Building a team is more important then building the environment. Many managers make the mistake of building the environment first and expecting the team to gel automatically. Instead work to create the team and let them configure the environment on the basis of need

[Robert C. Martin, 2005]

b) Motivation, leadership and self organization as tools of management

Management can work usually with the team of programmers in two ways: telling the programmers what, when and how to do, or telling the programmers what needs to be done, and letting them decide how long it will take and how it will be implemented. In agile methodologies, the second method is used, people are being put first and given responsibilities and rights, letting them work in their self organize and this method has been proven to be extremely successful both in software and outside.

The big difference, between self organized teams and teams that are organized by the upper management is motivation. In self organized teams, very high motivated individuals work, collaborate very well as a team focusing on what is important for all the team. In teams that are told what and how to do, the motivation is very low, people find it hard to work together, having more individualistic attitude because even if they do want to collaborate, the possibilities are very restricted.

Ken Schwaber states that in agile methodologies, teams are forced to collaborate better and to organize themselves at a higher level, because the deadline is always very close and they need to be very focused because of this. He says:

In most circumstances, management imposes a deadline and tells the workers what to complete by that deadline. This violates the rule of common sense: “You can tell me what to do or how to do it, but you can’t tell me both”. With agile processes the length of the iteration imposes the deadline. … The team selects how much work they can perform within the iteration, and makes commitments for it. Nothing demotivates a team as much as someone else making commitments for it. Nothing motivates a team as much as accepting the responsibility for fulfilling commitments that it made itself.

In agile teams, the project manager’s main role is to make sure nothing stands in front of the team so that they can organize themselves and build valuable software. These teams of programmers work together all the time, decisions are taken together, design is done together, and testing is done by the testers together with the programmers. The team is allowed to decide how to use their resources better to achieve the goal, without intervention from upper management, on who does what, who tests, who designs, who implements.

d) People are not pluggable and compatible units that can easily be replaced

Alistair Cockburn continues the idea, by showing that people are not plug compatible units, as some of the traditional processes try to believe and enforce. In his paper “Characterizing people as non-linear, first order components in software development” he shows what led to the belief that software developers are replaceable resources that come in different shapes: analysts, coders, testers, managers etc:

In the title, I refer to people as components. That is how people are treaded in the process/methodology design literature. The mistake in this approach is that people are highly variable and non-linear, with unique success and failure modes. Those factors are first order, not negligible factors. Failure of process and methodology designers to account for them contributes to the sort of unplanned project trajectories that we often see.

e) The developers have the power to take decisions

Many organizations claim that their biggest asset are the people they have, however when it comes to actually proving their people oriented processes, it is most often shown that the power to take decisions is in the hands of very few in upper management. If the people do not have the power to take decisions, even in their own area of competency: technical environment then how is this “people oriented process” really “people oriented”?

Ron Jeffries summarizes the need to empower the team, in an article called “Making the date”, in which he emphasizes that if the developers are responsible in making the deadline, then they should have the power to do so, otherwise the responsibility of not making a deadline is by no means theirs:

If the primary issue is to "make the date", and in my experience it usually is, then whoever has that responsibility needs to have the authority to apply people and resources, and to set the detailed objectives and goals. Unless we plan to give our developers the authority to hire and fire, to buy computers, to bring in contractors, we'd better not imagine that they can be responsible for the date. Unless we plan to give our developers the authority to decide which features will be delivered on the date and which ones will be deferred until later, we'd better not suppose that they can be responsible for the date. They can't: they don't have enough authority to steer.

To deliver the best possible combination of features by a given date, there must be control over the resources, and over the feature list. There's no way out of this. If you go to the store with a huge shopping list and twenty dollars, you need the authority to go to the money machine for more cash, or the authority to make changes to the list. And shopping is a lot easier than software development.

Agile processes emphasize the need that the programmers and the technical stuff take ALL the technical decisions. Management in agile thinking is done in a very different manner then in traditional methodologies, shifting the command and control model to a self organizing one.

The developers take a very active part in planning, designing, implementing and testing the software they produce. Agile thinking emphasizes that when planning, the estimates are done by those really doing the work. This is the most important aspect of giving the power to the people, being able to estimate how much their work will take. This is a tremendously motivational tool.

Friday, April 25, 2008

CHAPTER 4: Learning and adapting

4. Learning and Adapting

Introduction

Software development is a continuous learning activity between the customer who knows the business domain and the developers who know the software. Since the software product needs to combine the two areas of knowledge, the customers must teach the software developers about the business domain and the software developers must teach the customer enough about software so that they can better express their requirements. This learning activity is done throughout the project, having both the business domain experts and the software developers communicating and collaborating all the time, teaching each other what is needed in order to build the best software.

Circle of life – learning and adapting

In most occasions, at the beginning of a software project, the customer doesn’t really know what he wants or cannot express very well what he wants. The intangible, virtual nature of software is often the main factor in this problem. Traditional, predictability based processes, which need to write all the customer requirements at first, are exposed to high risks in projects where the customer cannot express his needs from the beginning. Not knowing what they want at first, means that the customer will want changes later and the cost of change is very high late in development, in waterfall based processes:

[Cost of change in traditional processes, by Scott W. Ambler]

Agile methodologies have acknowledged the problem of having customers that cannot express their whishes at first, and have built, at the base of their processes, a way of development that allows continuous learning and adapting throughout the project lifecycle, handling very well the cost of change:

[Cost of change in XP, by Scott W. Ambler]

In “Extreme Programming: Embrace Change” [], Kent Beck, explains how XP handles the problem of having customers that don’t know what they want and want changes late in development:

For decades, programmers have been whining, "The customers can't tell us what they want. When we give them what they say they want, they don't like it." This is an absolute truth of software development. The requirements are never clear at first. Customers can never tell you exactly what they want.

The development of a piece of software changes its own requirements. As soon as the customers see the first release, they learn what they want in the second release...or what they really wanted in the first. And it's valuable learning, because it couldn't have possibly taken place based on speculation. It is learning that can only come from experience. But customers can't get there alone. They need people who can program, not as guides, but as companions.

What if we see the "softness" of requirements as an opportunity, not a problem?

In his book “Agile and iterative development: A manager’s guide”, Craig Larman shows a very good sample of how, iteration by iteration, requirements evolve:

[Craig Larman, 2004]

The iterative and incremental nature of the agile methodologies allows the customers and the developers to continually adapt the software to their needs. Kent Beck compares software development with driving a car:

We need to control the development of software by making many small adjustments, not by making a few large adjustments, kind of like driving a car. This means that we will need the feedback to know when we are a little off, we will need many opportunities to make corrections, and we will have to be able to make those corrections at a reasonable cost.

The software process is a continuous cycle following a few simple steps: the developers and the customer decide what to do in the next iteration, the developers do it and then they show the result to the customer, who can now see the software and learn from it. The customers can now decide what needs to be corrected or improved and they can now give feedback about the product, that makes the programmers understand better what the customers really want. After a cycle like this, everything is taken from the beginning again. This is a continuous learning activity between the customer and the developers. Ron Jeffries calls this “the circle of life”, saying that:

On an XP project, the customer defines business value by writing stories, and the programmers implement those stories, building business value. But there’s an important caveat: on an XP project, the programmers do what the customer asks them to do!

Every time we go around the circle, we learn. Customers learn how valuable their proposed features really are, while programmers learn how difficult the features really are. We all learn how long it takes to build the features we need.

As important it is to develop closely with the customer and learn and adapt after every iteration, in order to improve the software, it is more important that the developers collect feedback from its real users, every release when the software is put in production and is used daily. Throughout the development of a release, the learning and adapting is done with the customer together, but nothing can give better feedback than real use of the software after a software release or delivery has been made to the real end users.

Development and production

Mary and Tom Poppendieck consider that one of the most important principles in lean thinking (adapted to software development) is amplifying learning, and that this is done as described above, using the main tools: iterations and feedback.

They also manage to show that it is very important to make the distinction between software development and product manufacturing, saying:

Think of development as creating a recipe and production as following the recipe. … Developing a recipe is a learning process involving trial and error. You would not expect an expert chef's first attempt at a new dish to be the last attempt. In fact, the whole idea of developing a recipe is to try many variations on a theme and discover the best dish

Showing the main differences between development and production

Development - Designs the Recipe

  • Quality is fitness for use
  • Variable results are good
  • Iteration generates value

Production - Produces the Dish

  • Quality is conformance to requirements
  • Variable results are bad
  • Iteration generates waste (called rework)

[Mary and Tom Poppendieck, 2003]

Not seeing these very important differences means not seeing development as a continuous learning and adapting process, thus working against nature, increasing the risks of failure in software projects.

A game of invention and communication

Alistair Cockburn defines software development as in Agile Software Development []:

Software development is a (resource limited) cooperative game of invention and communication. The primary goal is to deliver useful, working software. The secondary goal, the residue of the game, is to set up for the next game. The next game may be to alter and replace the system or to create a neighboring system

He expresses the need for cooperation between developer and customers as in a group game, and the need between the participants at the game to learn the problem and invent or imagine a solution for it, constantly readapting it to fit the needs.

3.3 Reflective improvement

One of the most important aspects of the agile movement is that its followers constantly need to look back at their activity, and learn from what they do about what is beneficial and what isn’t, and, based on this information, adapt and improve their working process. The need to improve the process is very well described by the last principle of the agile manifesto:

At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

Alistair Cockburn, describes a very pragmatic way to put the self improving technique in practice, in the book “Crystal Clear” []. At the end of each iteration, the team gets together and lists the activities they did in the last iteration, dividing them into two columns: to keep (activities that worked well and should be kept in the process) and to drop (activities, practices that didn’t work so well, and should not be put in practice anymore). Besides the two columns, a third column is added: “to try”, where ideas about different practices that could be tried are added by the team. Alistair calls this technique: reflective improvement.

The intervals at which the team reflects should not be very long, and Alistair suggests twice per iteration, once in the middle of the iteration when things can be improved as the iteration progresses, and one at the end of the iteration, to reflect on the entire iteration, including the delivery to the client and his satisfaction, called “post mortem” reflection workshop.

The activities and techniques discussed in a reflection workshop inside the team do not necessarily need to be from the past iteration or related to a project. They can be general conventions used throughout a larger base than the actual team like code conventions or database versioning and the people participating in them do not necessarily need to be from the team, so this kind of sessions could be done even with the customer to improve the whole collaboration and development process together.

Eliminating waste and cutting overhead

In order for a team to be able to drop some techniques that they are using, they need first to be aware that those techniques are not useful. Although this sounds incredibly simple, it proves to be one of the hardest to put in practice techniques. Seeing what generates waste is a very difficult activity and needs to be discussed in detail starting from what waste is.

Mary and Tom Poppendieck, have adapted a method to see waste in software development, from lean production manufacturing, that is based on Taichi Ohno’s first steps at Toyota in the 40s:

The 7 wastes in lean manufacturing

The 7 wastes of software development

Inventory

Extra Processing

Overproduction

Transportation

Waiting

Motion

Defects

Partially Done Work

Extra Processes

Extra Features

Task Switching

Waiting

Motion

Defects

In many occasions we develop code, especially when designing software, to allow flexibility for future changes. Some of the investment in the flexible design is well paid off, but in other occasions, those changes never occur, and the investment in the flexibility of the design is waste.

Following religiously a software process does not guarantee success. However, when software development fails, in many cases, the developers and the management come to the conclusion that the process wasn’t followed and they decide to make it stricter: more documentation is produced, more meetings are scheduled, the plans and designs go in further details. This can be good in some cases, but extra process overhead is one of the biggest problems in software development today. Programmers that work for 6 hours a day on writing documents that comply with the process and two hours on actually producing software is one of the best hidden wastes in software development, especially in large organizations.

Moving programmers from one project to another, requires time for them to get used to the new project. If that project is big, then understanding takes a lot of time, and if the task performed by the programmer moved to the project is small it does not cover the initial investment in understanding and, even worse, because the software wasn’t understood properly the programmers decrease the internal quality of the project, making it harder to extend and maintain.

One of the biggest problems with waste is that most programs have features that are never used. These contribute essentially to the cost, length and complexity of a software project, and not using them is just waste.

Self improving sessions

Back to work:

Some time ago, we started to use a new open source ORM on .NET, called NH. It was a fairly small (2.5 months) and non complex project, that was built by me and another colleague, let’s call him John. I was needed for the first 3 iterations (6 weeks) to help get the project started then it would be continued by John. The project was delivered on time for the customer and it still works. Then John and another colleague, Michael started a new web project, quite similar to the previous and developed it for two months. Then Michael and another colleague, George, started the third project.

On one discussion outside the company, Michel and George were complaining about the ORM saying that in many situations it proved to be an overhead. Suddenly, I detected a potential problem. I had been using it for the same period and my conclusion was exactly the opposite. Listening further, we decided to take a look in the code, and it was then that I realized that some parts of it were completely misused, becoming an overhead. Going back to the second project, I noticed the same mistake there. And, quite surprisingly in the first project also. I realized that one mistake, made by John, in using NH, was considered the right way to go by Michael and later by George resulting in much more code then it was actually supposed to be and the impression that it wasn’t a good technology.

I decided that I needed to do something about this, so I said to the entire team that the next day at 2pm everyone needs to be available for a meeting to sort out the problem; however I warned everyone that it wasn’t going to be a conventional meeting. When everyone came, I gave them a document, of about 40 pages that described in detail how NH really worked and I asked everyone to read it. While they were reading I made a list of questions to see if they understood the technology and we were supposed to discuss the responses in the end. When one finished reading I sent the questions by email expecting the answers in the same way. Of course we were all collocated and everyone had his computer. When all the answers came I was surprised that they were 99% right.

So, after 2.5 hours, that might be considered lost, because instead of working we read about a technology that was not used by everyone at the time, everyone started to understand it. If these 2.5 hours would have been done at the beginning of the first project, this might have saved days or maybe weeks of wasted resources because the technology wasn’t properly understood by someone and these misunderstandings were taken by the others as proper ways to use the technology.

We decided that this kind of “ school like sessions” could have tremendous potential also in our attempt to become more agile, so we started with Extreme Programming, reading, answering questions and discussing a few pages every day, having information and knowledge spread much faster than ever before, which later avoided many overheads and wasted resources.

Thursday, April 17, 2008

CHAPTER 3 (continued) : 3.4 Collaborating

3.4 Collaborating

Introduction

One of the values of the agile manifesto states: “Customer collaboration over following a contract” being completed then in the principles by: “Business people and developers must work together daily throughout the project”. It is very clear that day by day collaboration, between team members or between programmers and customers can deliver better software and, as a result, close collaboration stands at the base of all agile methodologies.

Why is collaboration important?

Building software is a continuous learning process between the customers that know the business constraints and the programmers who can develop the software. The customers must learn about software, about how software can be built, about what can be done and what can’t, about the cost of the different pieces of functionality because he is the one to “steer” the software direction to what he needs for his business. To build the right software, the programmers must learn about the business domain of the customer. This learning can only be done by working together daily.

Robert C. Martin said in “Agile Software Development, Principles, Practices and Patterns” [] that there is this tendency for managers to tell the programmers what needs to be done then go away for as long as they think it is necessary for the software to be built, then come back and find everything working. This tendency is in human nature, and it exists also in the case of the customers; however it was proven over and over that having everything written down in a functional specification document, signed off at the beginning can lead to misunderstanding the software’s purpose, from the client point of view.

Fear

Delivering software that fails to comply with the business needs of the customer contributes to building an atmosphere of distrust between software developers and the customers. This lack of trust is then tried to be compensated by very detailed contracts on what can and what cannot be done in future projects.

Customers are afraid that

• They won't get what they asked for.

• They'll ask for the wrong thing.

• They'll pay too much for too little.

• They must surrender control of their career to techies who don't care.

• They won't ever see a meaningful plan.

• The plans they do see will be fairy tales.

• They won't know what's going on.

• They'll be held to their first decisions and won't be able to react to changes in the business.

• No one will tell them the truth.

Developers are afraid, too. They fear that

• They will be told to do more than they know how to do.

• They will be told to do things that don't make sense.

• They are too stupid.

• They are falling behind technically.

• They will be given responsibility without authority.

• They won't be given clear definitions of what needs to be done.

• They'll have to sacrifice quality for deadlines.

• They'll have to solve hard problems without help.

• They won't have enough time to succeed.

Unacknowledged Fear Is the Source of All Software Project Failures

If these fears are not put on the table and dealt with, then developers and customer each try to protect themselves by building walls.

[Fowler , Beck – Planning Extreme Programming, 2001]

Contracts

Protecting by building walls, usually means contracts. Trying to replace trust and close collaboration with contracts is not solving the problem, but amplifying it. Mary and Tom Poppendieck describe why trust cannot be replaced very well with samples from car manufacturing and from software, enumerating the different types of contracts and showing the flaws they have when it comes to “enforcing” trust.

Can the parties involved in a software project as buyer and as vendor collaborate efficiently without each following their own interests? Because of this great fear, contracts are signed and expected later to replace trust between the companies involved on each side. If as quoted in Lean Software Development, trust means: “one party’s confidence that the other party … will fulfill its promises and will not exploit its vulnerabilities”, then contracts are considered by very many people, a way to enforce this.

Let’s study a little the contract types, used mostly between software companies and examine how trust can be enforced by them or how they can obtain exactly the opposite because of the contracts:

  1. Fixed price contracts: The most commonly used type of contract, seems to give the customer the faith that the cost won’t be bigger then the one planned, but this means that the burden is moved on the shoulders of the software vendor, who will try to find different ways to compensate its eventual losses (if any) by overcharging for changes. They tend to push an atmosphere of distrust between the parties, each trying to follow their interest and thus favoring the failure of the software projects
  2. Time and materials contracts: this type of contract deals better with unpredictability and uncertainty but simply shifts the risk from the vendor to the buyer. The longer the contract takes to complete the more the customer will pay, encouraging in a way the vendor to charge more for the work. The customer is always on the pressure that the things might be done faster and this favors ,just as the fixed price contract, an atmosphere of distrust
  3. Multistage contracts: these types of contracts try to merge together the fixed price and time and materials contract types benefits, minimizing the risks. Usually a big fixed priced contract is divided into a multiple succeeding stage contracts governed by another contract. There is a certain risk in this approach also: if after each small stage contract is delivered, the contract is fully renegotiated, then it can become very expensive and it will not bring the two parties close together.
  4. Target cost contracts: this type is the hardest to put in practice, but the most fair for both parties as well, which means that it favors trust. They are structured in such a way that the total cost, including changes – is a joined responsibility of the customer and vendor. This enforces them to collaborate and take decisions together, negotiating so that the target cost is met.

Although, some types of contracts can be seriously flawed when it comes to software development and to building programs that have value for the customers, it has been proven that they can be adapted to work well in software as long as they do not try to replace trust. Agile methodologies tend to favor the types of contracts that are aimed at building trust rather than building distrust. Robert C. Martin gives a very good example of an agile contract:

As an example of a successful contract, in 1994 I negotiated a contract for a large, multi-year, half-million-line project. We, the development team, were paid a relatively low monthly rate. Large payouts were made to us when we delivered certain large blocks of functionality. Those blocks were not specified in detail by the contract. Rather the contract stated that the payout would be made for a block when the block passed the customer’s acceptance test. The details of those acceptance tests were not specified in the contract.

During the course of this project we worked very closely with the customer. We released the software to him almost every Friday. By Monday of Tuesday of the following week he would have a list of changes for us to put into the software. We would prioritize those changes together, and then schedule them into subsequent weeks. The customer worked so closely with us that acceptance tests were never an issue. He knew when a block of functionality satisfied his needs because he watched it evolve from week to week.

The requirements for this project were in a constant state of flux. Major changes were not uncommon. There were whole blocks of functionality that were removed, and others that were inserted. And yet the contract, and the project, survived and succeeded. The key

to this success was the intense collaboration with the customer; and a contract that governed that collaboration rather than trying to specify the details of scope and schedule for a fixed cost.

[Robert C. Martin 2005]

The agile methodologies come with a series of practices that are aimed at building trust between the vendor and the buyer of the software, frequent delivery being the most important of them, because the customer can see the software, at small intervals, with the planned features, built and working. Risks are also addressed by having the most important features (from the client’s point of view) developed first and by allowing him to make mistakes, to change his mind, to figure out how things are really done later after he sees what the software would look and feel.

Customer and programmer rights

Ron Jeffries, in “Extreme Programming Installed” [] and Martin Fowler and Kent Beck in “Planning Extreme Programming” [], built a list of rights for all the three parties usually involved in a software project, which, if known and respected from the beginning, can enhance collaboration.

Customer Bill of Rights

• You have the right to an overall plan, to know what can be accomplished when and at what cost.

• You have the right to get the most possible value out of every programming week.

• You have the right to see progress in a running system, proven to work by passing repeatable tests that you specify.

• You have the right to change your mind, to substitute functionality, and to change priorities without paying exorbitant costs.

• You have the right to be informed of schedule changes, in time to choose how to reduce the scope to restore the original date. You can cancel at any time and be left with a useful working system reflecting investment to date.

Programmer Bill of Rights

• You have the right to know what is needed, with clear declarations of priority.

• You have the right to produce quality work at all times.

• You have the right to ask for and receive help from peers, managers, and customers.

• You have the right to make and update your own estimates.

• You have the right to accept your responsibilities instead of having them assigned to you.

Customer collaboration

In “Extreme Programming Explained: Embrace Change” [], Kent Beck says:

XP planning assumes that the customer is very much part of the team, even if the customer works for a different company and the rest of the team works for a contractor. The customer must be part of the team because his role is far too important to leave to an outsider. Any (XP) project will fail if the customer isn't able to steer.

So the customer's job is a huge responsibility. All the best talent and technology and process in the world will fail when the customer isn't up to scratch. Sadly, it's also a role on which we can't offer particularly sage advice. After all, we're nerds, not business people. But here's what we know for sure.

[Kent Beck, 1999]

This very much shows the role of the customer in an agile project, and how close collaboration is actually being done, with each party having their responsibilities and rights, and collaborating to “steer” and implement the project successfully.

The most obvious way in which the customers and the programmers collaborate, is agile planning, which is done together. SCRUM iteration or sprint planning summarizes in a way the whole concept behind agile planning that is also used in all the other agile “flavors”. The customers and the programmers sit together, starting with the customer explaining in the first part of their meeting where he wants to go, showing the “shopping” list he wants for the next sprint and explaining what each item means, so that the programmers can come up with the cost (estimated time) for those items in the second part of the meeting. In the case that the cost is over the budget (30 days in a sprint) then based on the priorities of the customer some of the low priority items are dropped, so that the cost matches the budget. In case the cost is under, then the customer is asked to come up with other items, that are the next most important to him, so the gap between cost and budget is filled.

One unwanted possibility (but, since agile methodologies are very pragmatic, it is taken into account) is when the team realizes that they won’t be finishing in time, with the next iteration. Since honesty sits at the base of agile principles, then the customer is informed right away and shown the situation. He is then asked to pick one or more of the planned features, and “drop” it, so that the remaining can be delivered successfully. In this way, the crisis is solved fast and together, whereas the alternative: lying would be much more costly. It is important to remember that in this “negotiating scope” session, for example , 8, 100% finished features will be delivered out of 10 planned, rather then 10, 80% finished features that would be unusable. The “dropped” features will be then planned for the next iteration.

The two methods described above are incredibly efficient at reducing the risk of a project failure since the top most important features are built and delivered first, thus showing how close collaboration between the customer and the programmers can lead to success.

Thursday, April 10, 2008

CHAPTER 3: Communicating and Collaborating

3.1 Introduction

Communication is considered to be the main factor in a project’s success or failure. Alistair Cockburn calls software development “a game of communication and invention”, in his book “Agile Software Development”, where a big part is dedicated to explaining communication problems and how communication influences the development of a software project. In all agile methodologies, communication and close collaboration with the customer is emphasized as a “must do” practice; in XP two of the five values are communication and feedback, in SCRUM’s values we can find communication, Crystal comes with osmotic communication between team members and with early access to expert users and so on.

Bad communication between the different people involved directly in a software project, can create a lot of overhead and waste important resources, and in many cases can cause the failure of the project. For this reason, all software methodologies have developed more standards for communicating, formal and informal, while working on a project, between the different stakeholders.

Communication can be divided in: communication inside the development team and communication outside the development team, with the customer and with the upper management.

3.2 Communicating with the customer

3.2.1 Requirements

Functional specification documents signed off at the beginning

Traditional software methodologies need to gather the client’s requirements at the beginning of the project, putting everything in a big functional specification document that needs to be signed off by the client before it can go into production. This approach seems fair and quite straightforward but practice over the years has shown that it can have some very serious flaws. The biggest problem with this approach is that due to the problems in understanding software and how it works, the customer cannot always tell what he wants from the beginning, and might miss some very important aspects when the functional specification document is signed off.

There have been numerous cases in the past when projects were developed within budget, delivered on time and as asked for, by the functional specification document, but when put into production they were completely useless for the customer. Yes, the customer could be blamed for not knowing what he wants when he needs to, but the pure fact is that he is unhappy about paying for unusable software. A customer that had such an experience will be very reluctant when needing to sign off another functional specification document and in many cases a lot of overhead will be generated in development because of his fear of being forced to pay for unusable software.

Although big functional specification documents seem very good to the untrained eye, they do have serious flaws:

- They are very costly to build (how much time do you need to write 100-600 pages of text?)

- They might miss important aspects of the program. Written text is not very good at communicating things. The writer cannot capture whatever he needs to capture and the one that reads tends to imagine the rest. Imagination is good, but not in this case because, in this case, it is very costly.

- They tend to push the customer proxy. The more indirection and steps trough which something goes from the customer to the actual developer building the software, the more misunderstandings can, and usually do occur. When the information needs several nodes to be transmitted from the ones that know the business to the one that builds the program, important time is lost, and important precision.

- Big documents are hard to read. Someone might say it is important to capture everything there otherwise programmers would complain about not being complete, but over completing it is just as bad.

- What if something changes? What if at the time the document was written there was one situation and it just changed? What do you do? Throw up the part or the entire document? If you wrote it in 1 month, and it cost you x, you have just lost a 10-20-30-...100% of x and need to pay again for the new one.

Big functional documents are written to replace trust between the parties involved. We need to write everything in the specification document and cast it in stone, so it can't change and we can't be held responsible by the customer later. Where there isn’t trust, there isn't good business. Lack of trust is usually compensated with enormous overhead in work and cost. But on the other hand, not everyone is to be trusted.

Agile requirements

Mike Cohn wrote in User Stories Applied []:

I felt guilty throughout much of the mid-1990s.[...]

I knew that what we were doing worked. Yet I had this nagging feeling that if we'd write big, lengthy requirements documents we could be even more successful. After all, that was what was being written in the books and articles I was reading at the time. If the successful software development teams were writing glorious requirements documents then it seemed like we should do the same. But, we never had the time. Our projects were always too important and were needed too soon for us to delay them at the start.

Because we never had the time to write a beautiful, lengthy requirements document, we settled on a way of working in which we would talk with our users. Rather than writing things down, passing them back and forth, and negotiating while the clock ran out, we talked. We'd draw screen samples on paper, sometimes we'd prototype, often we'd code a little and then show the intended users what we'd coded. At least once a month we'd grab a representative set of users and show them exactly what had been coded. By staying close to our users and by showing them progress in small pieces, we had found away to be successful without the beautiful requirements documents.

Agile methodologies have developed methods to capture requirements in such a way that the problems and risks associated with the methods presented above are very well addressed. Agile thinking works with the fact that requirements change in time and works with human nature, allowing the customer not to know exactly what he wants from the beginning. In every agile methodology, a very strong emphasis is put on close and direct communication with the customer, so the misunderstandings generated by customer proxies are eliminated. The most efficient methods of communication are used: verbal, real-time, face to face communication is pushed forward against written documentation, which is kept to a minimum.

Intermediate work products (documentation, use cases, UML diagrams, database schemas etc) are not important models of reality, nor do they have intrinsic value. They have value only as they help the team make a move in the game. Thus, there is no idea to measure intermediate work products for completeness or perfection. An intermediate work product is to be measured for sufficiency: Is it sufficient to remind or inspire the involved group?

[Alistair Cockburn, 2003]

User stories, backlog items, acceptance tests

Since the emphasis is put on close collaboration and face to face, real time communication with the customer, written requirements are kept as brief as possible. They usually act mostly like a reminder of a thing that needs to be discussed between the customer and the developers.

The most well known ways to capture requirements from the customer in agile methodologies are the user stories, originating from XP and the backlog items, originating from SCRUM. Both describe functionality that will be valuable to the customer and the users of the system.

Mike Cohn defines in ‘User Stories Applied’ [], the following characteristics of a good user story: independent, negotiable, valuable to users or customers, estimable, small and testable.

Because of their light nature, user stories and backlog items act more like an instrument used for planning, than for describing what is wanted. They give the directives on what is wanted and the details are mostly discussed with the customer and expressed as acceptance tests.

Acceptance tests are a feedback mechanism defined by the customers (with the help of programmers) to allow programmers to know if a feature has been finished and if that feature has been implemented exactly as the customer wants it. Instead of making the customer describe what he wants, acceptance tests are built by asking the customer: “how will I know that what we did is according to what you want?”. And he will start saying what needs to be done, for him to be able to know if what was requested was built and finished or not. Instead of heavy descriptions, two purposes are achieved by this question: you know what needs to be done and you know how you can test, at the same time. Also, ambiguity tends to be dissolved by acceptance tests, because the customer, in order to know how to test something, he must have a very intimate knowledge and understanding of that thing.

The user story mini-sample

Case 1: Requirements document

4.3 Outstanding contracts report

The system will allow the users to see a report of outstanding contracts. An outstanding contract is a contract that exceeds a predefined number of days, since it has been sent to the customer and no response has been received.

The outstanding contacts page:

Contract management system

My contracts (1) Reports (2)

Outstanding contract report

Choose the number of days: [ (3)] [Search] (4)

Results:

Customer (5)

Contract reference (6)

Number of days passed (7)

Customer #1

Ref #1

3

Customer #2

Ref #2

0

Customer #3

Ref #3

2

#

Element

Description

1

My contracts

Description: Menu item (-the) will allows navigation to the page where my contracts can be managed

2

Reports

Description: Allows user to navigate to the reports screen where all reports reside

3

Number of days

Description: Allows entry of the number of days that need to be exceeded so that the contract will be displayed.

Function: User types the number of days as an integer value

4

Search button

Description: Allows the query to be performed

Function: On click the system will search the database for the contracts specified and will display them in the table below the button on finish. If no results have been found then a message “No search results.” will be displayed

5

Customer

Description: Displays the customer name

6

Contract Reference

Description: Displays the contract reference number

7

Number of days passed

Description: Displays the number of days that have passed since the contract was sent to the customer

Case 2: User story and acceptance test

Outstanding contracts report

Report all contracts sent to the customer and no answer was received for a number of days above a given amount.

Acceptance test

For a list of contracts:

contract

customer

Sent date

status

NL001

IBM

2006.04.01

Sent

RL001

Coca Cola

-

Preparation

DF001

HP

2006.04.05

Accepted

NL002

BT

2006.04.09

Sent

Test case 1: Filtering at 2005.10.20, for contracts above 100 days would result in:

No results to display.

Test case 2: Filtering at 2006.04.20, for contracts above 15 days would result in:

Customer

Contract reference

No of days passed

IBM

NL001

19

Test case 3: At 2006.04.30 for 10 days:

Customer

Contract reference

No of days passed

IBM

NL001

19

BT

NL002

11

3.2.2 Set-based development

Communicating the requirements can be done in two ways: communicating the constraints, allowing multiple solutions to be developed by the programmers until one emerges or communicates the solution, and refining it until it works. Mary Poppendieck calls this: set based vs. point based development.

As a simple example, the customer can say: we need a desktop application that enables us to see our sales or we need a way to see our sales. The first thing enforces a desktop application solution, while the second allows the possibility to develop more solutions: web based, desktop based, mobile etc. If the second requirement is detailed as: we need to be able to see our orders real-time, as quickly as possible as some of them need a sales manager’s approval, and he needs to do that no matter where he is, then suddenly, the mobile solution might seem like a better solution, having the mobility constraint. Further defining the constraints, one solution will emerge. If we take the point based approach going directly on a desktop application, when the mobility constraints is revealed we might be forced to go back and rethink the desktop solution, throwing away the desktop solution code.

Agile methodologies have built in their practices ways to communicate and implement, using set based development like: developing multiple solutions in the early iterations and letting one emerge, communicating constraints instead of solutions , a very good example being acceptance tests which communicate testing constraints not solutions for implementation and design for change, where extensive refactorings, and fast changes and shifts based on constraints can let a solution emerge from a larger range of possibilities.

3.2.3 Feedback

Customer feedback

It's two in the morning and you are driving home. The traffic light is red, and there's not another car in sight. But the traffic light is red, so you stop. And wait. And wait. Finally, the light changes, after allowing time for lots of nonexistent cross-traffic. You think to yourself, it’s going to be a long drive home. And sure enough, the next light is also red. But as you approach the light, it turns green. Ah ha! you think, An automatic sensor. That light is smart enough to know I'm here and there's no one else around. I hope the rest of the lights are like that!

The difference between the two lights is feedback. The first light was preprogrammed.

[Poppendieck 2003]

Improvement can only be done as a result of feedback. The development team writes a piece of the system, the customer sees it and tells them if that program is good or not. He can also tell the developers what would be even more liable to improve the program’s quality.

The virtual nature of software makes it very hard for customers to understand how it’s build and done, so it is very hard for them to communicate you what they really want. To address this extremely important problem, software should be shown very often to the customer. This has two very important benefits:

- he can see where you are, the real progress, and this increases his trust that you’re doing what you were planning to do and that his money is not wasted

- he can see if something is not what he wanted and tell the development team, so they can fix it or after seeing it he can start to ‘feel’ the software and be able to give you much better information about what he wants. The smaller the delivery cycles, the better.

The small delivery cycles are incredibly important in a project’s communication. As previously stated they show one very good technique to avoid derailing the project and they embrace changing requirements.

When the first requirements are being gathered from the customer, the developers explain him how something can be done, but it is very easy for him to imagine a completely different thing. It is also very hard for him to understand what can and what cannot be done; why something costs more or what costs less. After the team delivers the first result of an iteration, he can see a computer program, and everything seems to take shape in his mind. He can use this as a basis for future requirements, and can see about how much time one thing or another takes to be implemented. The second iteration is even better and as the project progresses, the dark fog that the software seemed to be in the beginning is starting to become clearer, easier to control and he becomes less and less stressed. He starts to understand how things are done and he sees real progress. There is nothing more honest than showing the customer the real program from which he can see the progress.

Code feedback

If feedback is the base for all improvement, how can feedback help the internal quality of a project? What we discussed earlier about feedback is the external quality that can be improved, the part that the customer understands and helps improving, but what about internal quality. But what is internal quality in a software project?

A project is of high internal quality if it can be tested and debugged easily and it can change with very little effort. Being able to be changed easily assures the program a much longer life in production, which makes it cheaper. If the customer pays $1.000.000 for a software and the software is used for 5 years, it will cost $200.000 every year. If the same software can be fixed, readapted and maintained longer in usage, for instance for 10 years, it costs $100.000 per year. Twice cheaper, isn’t it?

But how can we make the software give us feedback about its health? In agile methodologies the best technique for receiving feedback from the code itself about its health are automated tests. They can detect problems very early and report them to the developers so they can act very fast on them. The automated tests become break detectors. If the developers can detect breaks in the existing functionality fast, they can fix them fast and that allows them a great flexibility. A programmer makes a change in the software, even in the code he didn’t write. Then he runs the tests. If they detect a break, he knows it and he can choose either to reverse the change or repair the affected part.

A big problem in a program’s flexibility is that if it becomes big, it is very rigid, and making a change can affect parts of it that cannot be easily predicted. So the developers are afraid to change it. So the project starts to be doomed. The hardest it is to be changed, the hardest it is for it to cope with the market requirements so the shorter its life will be. Having an army of break detectors as automated tests ensure great flexibility, diminishes fear of change, even in big and complex systems, because of the fact that they can give the developers feedback about their actions very fast.

3.2.4 Showing progress

Working software doesn’t lie. One of the agile manifesto principles states: “Working software is the primary measure of progress”. Showing the customer the product instead of reports after each iteration is completed (2-4 weeks), is a great way to communicate progress and to build a product of much bigger value to the customer. Putting that software into production every few months and seeing how it is used, collecting what the users think can improve the software, can build thrust between the client and the programmers, driving the software to success.

For communication inside the team or with upper management, big visible charts on a wall, showing very clearly the features implemented, and the features not implemented can be a very effective and silent technique to show everyone passing by that wall, the current status of a project.

3.3 Communicating inside the team

The project related information must go very fast inside the team. Crystal calls this osmotic communication and it is at the very core of the methodology. It says that people working on the same project need to be able to use the best communication technique: face to face communication, with and without a whiteboard. For this the best technique is to have the entire team collocated in the same room as much as possible , all facing each other, to be able to ask each other questions and to enable others to hear discussions etc. The team must also have a whiteboard in their proximity where they can design or use sketches on the whiteboard to communicate better.

Extreme Programming goes even further, addressing the communication problem mainly with user stories written on pieces of paper and stuck to the wall, and with writing all the business code by pair programming. This means that two programmers, work together at the same computer, understanding 100% of what’s done, and not 50% as if they were doing it separately.

The techniques above and others mainly address communication when time is crucial, but there are other problems of communication within the organization, where time is not that crucial. This is best described by a situation, where a team is developing a program for a few months, delivering it to the client in the end. Now the client wants to continue the development of the program, to add extensions to it, to improve certain parts etc, but the team that built it is not available anymore or it is partially available. How will the new programmers who come in contact with the program understand what was required, what was done, and how it was done?

Extreme Programming comes up and says that the best way to document a computer program is the code itself and the automated tests, it has and not documents describing what was done, as these documents need to be written by someone, which is costly and becomes obsolete very soon. In most cases, I find this approach very good, as I noticed that, recently, whenever I download an open source framework or look at a code written in the past, the first thing I instinctually do when I want to learn how to use it, is to look at the unit tests. They show me how the software can be used, and which the limitations are, in the same language I want to use it: code.

3.4 Improving communication: quantity vs. quality

If communication plays such an important role in all aspects then how can we improve it? For the sake of improving communication, many people fall into a very big trap, believing that improving communication means increasing quantity: more meetings, more documentation, more emails and more phone calls. This is profoundly wrong: communication can only be improved by quality and in many cases improving quantity means increasing the communication problem and not solving it.

Meetings are failures when participants leave the meeting feeling no productive results were achieved; or, that the results that were derived were accomplished without the full engagement of the participants. In short, these useless meetings do not engage collaboration and participative decision making.

[ Booch and Brown, Collaborative Development Environments]

In order to improve the quality of communication we must see which types of communication are better then others. Following this idea, Alistair Cockburn, makes a communication top in Agile Software Development, concluding that Interactive, face-to-face communication is the cheapest and fastest channel for exchanging information.

If verbal, face to face communication is not at hand but there are other great ways to deal with it, like visual communication, web based collaboration tools acting as whiteboards and allowing people to chat real-time, application sharing, instant messengers, etc.

As an example of visual communication, a single screenshot can show even the context in which a bug appeared and give the developers a great deal of information about the user actions. Screenshots or even small recorded movies of user actions, are very cheap, and communicate a lot of useful information, which in some cases might be missed just by sending a plain text email or document.

Another example of improving communication are customer improvement programs where the user is either asked to add suggestions on how he would like a program to be improved or when a bug appears the software automatically detects it and sends by email or other means, information (maybe even screenshots) about the problem to the developers to be analyzed and the problem solved.

Macromedia Flash recorded movies are becoming a more and more popular way to show how software can be used instead of plain text or “classical” help documents, because their visual nature enhances the experience the user has when learning about the program.

Table based communication is one of the most used at this time in businesses (mostly due to Microsoft Excel) because of its simplicity and concreteness. The same approach has been brought into software development by Ward Cunningham, who invented a brilliant communication, organization and testing tool based on tables called Fit (http://fit.c2.com ). Fit is a great framework for acceptance tests. His work is now continued by a wiki concepts based tool developed at ObjectMentor, being supervised by Robert C. Martin, called Fitnesse (www.fitnesse.org ).

New ways of enhancing communication are emerging, allowing people to communicate better, thus making them able to collaborate closely even if they are not situated in the same room, and obtaining better software.

Labels:

Wednesday, April 02, 2008

CHAPTER 2: Agile methodologies

2.1 Introduction

What is a methodology?


A methodology for software is a set of related rules, principles and practices that, once put in practice, can help deliver valuable software, to the client on time, over and over again.

Your methodology is everything you do regularly to get your software out. It includes who you hire, what you hire them for, how they work together, what they produce and how they share.

[Cockburn, 2004]

Characteristics of an agile methodology

Agile methodologies are characterized by close collaboration with the customer, and by delivering working, tested within fixed time intervals, called iterations, which usually lasts from one to four weeks. These practices help ensure that the software is developed according to the customer wishes, projects staying on track, and can also react well to changing requirements and priorities.

Working software is shown to the customer at the end of each iteration which provides a tangible mean to track project progress rather than with charts and reports. Written documentation is kept to a minimum, in favor of real-time, face to face verbal communication and close collaboration both within the team and with the customer. This close communication and frequent feedback loop with the client enables a continuous learning process in which the customer understands and participates in software development and the developers are kept close to the business domain of the customer.

2.2 Agile manifesto and principles

Throughout the 90’s several new “light weight” software methodologies emerged in reaction to the problems with the heavy methodologies used throughout the industry.

In 2001, Jim Highsmith and Robert C. Martin, organized a meeting of 17 people, many of them being founders of these “new” methodologies to discuss the similarities and differences of their methodologies, and establish a set of principles that were common to all. Thus the “agile” movement was born with the establishing of a manifesto and a set of 12 common practices that expressed the essence of what agile development is.

The agile manifesto

1. Individuals and interactions over processes and tools


The heavy, high ceremony processes with lots of process and documentation overhead, were found to produce less valuable software for the customers, than self organized teams of open minded individuals, who were interacting and focusing more on delivering software rather then strictly following the process.


2. Working software over comprehensive documentation

In many cases, vast amount of documentation was produced for different purposes, from gathering requirements, to tracking and showing progress to the client or to document what had been done, with people focusing on getting the right documents rather than the right software, for the customer, on time. They discovered that there is no better way to show progress, then showing the customer the software, because working, tested software does not leave room for misinterpretations.

Documentation can be helpful, but it is very important to do just enough of it for the needed purpose, staying focused on delivering software, instead of focusing on making the best documentation possible.

3. Customer collaboration over contract negotiation

In many cases, because of the virtual nature of software, clients cannot express their requirements very well at first, but they tend to become good at it as they see the software being built. This continuous learning of both the customer, about software, and for the developers about the customer’s business was proved to be a very good way to build software. By having everything negotiated and signed off from the beginning, the software’s purpose, from the client point of view, could be misunderstood. Collaborating directly with the client is usually a guarantee that the software that he needs is developed and that it is shaped as close to what he wants as possible.

4. Responding to change over following a plan

Plans are used to calm us down, to give us a direction to follow and as we go to let us know where we are by comparing the reality with the plan. But we need to be able to readapt the plan fast if the direction of the software being built has changed. Following a rigid plan, loses its calming purpose for both developers and customer, when it no longer reflects reality.

The principles

The principles of the agile manifesto are the ones that explain better, the practical side of agile manifesto. They show which principles are followed in all agile methodologies. They represent a more pragmatic approach to what must be done to become agile.


1. Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.
2. Welcome changing requirements, even late in development. Agile processes harness change for the customer's competitive advantage.
3. Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.
4. Business people and developers must work together daily throughout the project.
5. Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
6. The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.
7. Working software is the primary measure of progress.
8. Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.
9. Continuous attention to technical excellence and good design enhances agility.
10. Simplicity--the art of maximizing the amount of work not done--is essential.
11. The best architectures, requirements, and designs emerge from self-organizing teams.
12. At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

The agile alliance

The agile alliance defines itself as:

“a non-profit organization that supports individuals and organizations who use agile approaches to develop software. Driven by the simple priorities articulated in the agile manifesto, agile development approaches deliver value to organizations and end users faster and with higher quality”.

2.3 Agile methodologies, practices, properties and tools

There are, as Martin Fowler said, more “flavors” of agile methodologies.
- SCRUM
-XP - Extreme Programming
-Crystal Family
-Lean Software Development
-Adaptive Software Development
-AMDD - Agile Modeling Driven Development
-FDD – Feature Driven Development
-DSDM

All agile methodologies are based on a set of rules, values, principles and practices specific to each of them, or that have been influenced or evolved with practices from other agile methodologies. Each methodology has a set of “must do” and a set of “could try” practices and tools, thus showing what the core of the methodology is and how it could be customized and adapted.

Most of the authors invite practitioners to use practices from the other methodologies, when it comes to an area that is not specifically covered by the methodology they propose, or where they leave much flexibility.

SCRUM and XP dominate the market at the time, being the best known and the most used, but it is important to have an overview of the entire range of agile methodologies. Mixing practices from more agile methodologies can better adapt to one’s needs thus making his process more customized and more efficient.


2.4 XP

Extreme programming is probably the most known (and controversial) agile methodology, being defined by Kent Beck, in 1999 in “Extreme Programming Explained: Embrace Change, First Edition”, after being shaped along Ron Jeffries, Ward Cunningham, Martin Fowler or Robert C. Martin throughout the late 90’s, especially in a famous Chrysler project called C3, where the basis of it had been put into practice.

Extreme programming is based on a set of values, principles and practices, that are recommended to be followed, covering all aspects from communication, to organization, quality control and coding. It is the methodology that puts the highest accent on testing, and especially automated testing from all software disciplines known.

Values, Variables, Principles and Practices

XP has 5 values, on which it is based: communication, simplicity, feedback, courage and respect.

The most important practices of XP are:
- small releases
- the planning game
- refactoring
- test driven development
- pair programming
- sustainable peace
- team code ownership
- coding standard
- simple design
- metaphor
- continuous integration
- on-site customer

The key principles, on which XP is based, are: rapid feedback, assume simplicity, incremental change, embrace change and quality work

How do people work in XP?

In XP, projects are developed by collocated teams, usually with 4-10 developers, delivering the work to the client or onto the market, every 2 to 4 months, calling these timed units, releases. These releases are also divided in a set of iterations, each lasting from one to 4 weeks (most common are 2 and 3 week iterations) and at the end of which, a part of the entire product, is delivered. The end result of such an iteration should be a high quality piece of software, that could be potentially deployed into a production environment.

In XP, the client has to be collocated with the team, to be able to answer questions and “steer” the direction of the project all the time. The client is called “the customer” and the technique described above, is called “on site customer”. As a consequence of this collocation, feedback is very fast, so the project doesn’t derail, and the need for written functional specifications is less obvious. The unit for gathering requirements from the client that is also later used in planning is the user story and it usually represents a valuable feature for the client. It is not written in very much detail and most times it is very brief, acting more like a reminder for the customers and programmers to talk about it and be able to estimate and implement it.



In XP software is developed in cycles; every few months a release is being planned then built trough several succeeding iterations, then the product developed so far deployed to the customer finalizing one cycle and starting another if necessary. At the beginning, the project is planned for the next release (2-4 months in advance). The user stories are written with the customer, and then these user stories are estimated by the programmers, providing the client the “cost” for each of these pieces of functionality. Based on these costs the customer can then give the priorities, putting the most important one to be developed first, so the most valuable features for the client are being developed and delivered the fastest. The user stories in the plan, after being estimated and prioritized are now divided between the iterations in the planned release.

At the beginning of each iteration or release, the customer can change the plan and readapt it to his needs, re-prioritizing the list of user stories, being able to change the direction, by bringing forward user stories from other iterations, adding new ones or dropping some of them, then the programmers re-estimate the work, redefine the plan.

Going deeper into detail for user stories is done trough verbal communication between programmers and the customer. Programmers estimate the user stories by dividing them into programming tasks. The customer writes acceptance tests or customer tests as they are called in XP that will demonstrate by passing that what was requested was really implemented. Many times these acceptance tests become automated tests.

Once the iteration has been planned, the programmers divide the user stories or tasks among them and then write the code in pairs or two people (pair-programming) writing automated tests for anything that could possibly break, integrating the pieces of code that each pair delivers and building the system and running the suite of tests automatically as often as possible. The code is written after a coding standard document, and the pairs of programmers are changed often so that each programmer can work on more parts of the system and pairing with more colleagues throughout the project, thus knowing better what is happening in it.

In XP, each programmer can change every piece of code, if he needs to, as there is no individual code ownership, but all the developers own all the code, this technique is called collective ownership.

The architecture or design of the code is not built up front like in traditional software engineering models, although risks are being evaluated (especially by building prototypes called spikes, but not necessarily at the beginning) but is actually emerging from the code, as this code is continually refactored to be the simplest possible (one of XP values is simplicity) and using the YAGNI (You Ain’t Gonna Need It) technique, focusing on what the code needs to deliver now rather then what could be needed in the future. When the changes will be needed, the code will be refactored to accommodate them, as refactoring is easy because of the extensive automated test suites that can instantly say if a change has broken some existing functionality and secondly because rotating the programmers in the pairs facilitates better knowledge of the whole system for all the programmers.

A special case is when a customer wants software and has a deadline for it which cannot be negotiated, but the amount of features he wants clearly need more time, than the specified deadline. In such a scenario, the customer and the developers sit together and first get the list of user stories the customer wants and then the developers estimate the cost of each. The customer is then asked to choose from that list enough user stories to fill the time until the first deadline. The rest of the user stories will be developed in another release after the first release has been delivered. This special case exposes very well the practice called negotiating scope.

XP (and other practices) strongly believes in sustainable peace, where projects are developed at a sustainable and constant rhythm of work, doing as much as possible in 40 hour weeks, without lows and highs in the number of hours needed throughout the development of the project, and this can be achieved applying the practices described above.

2.5 SCRUM

SCRUM is an iterative and incremental methodology that was developed starting from project management problems, by three people: Ken Schwaber, Jeff Sutherland and Mike Beedle, since 1993, and it has been proven as a great way to produce successful software continuously with small and large projects on a wide range of companies.

SCRUM is based on 5 values: commitment, focus, openness, respect and courage.

How does a SCRUM team work?

SCRUM teams and key roles


A SCRUM team is usually of four to seven developers. All these developers work together, being self organized without any intervention from upper management on individual responsibilities (who does what, who designs, who tests), all these activities are decided and performed inside the team. The developers have no fancy job names like architect, tester, programmer, etc.

A SCRUM master, is the equivalent of a project manager in traditional software development processes, but the way he does his job is very different. He is more a leader than a manager, letting the team self organize and having the primary goal in removing whatever obstacles the team would have when trying to deliver valuable software to the client. The SCRUM master serves the team, rather than imposing directions to it.

In SCRUM, the role of the client or the customer is called, the product owner. He is working with the team in defining and refining requirements, which are kept in a product backlog, each feature or item in there being called backlog item. His job is to produce the backlog items and to prioritize them, so that the highest value can be delivered by the team first.

Planning sprints

The product backlog is the master list of all functionality desired in the product.

[Mike Cohn, 2004]

A project starts in SCRUM with gathering all the important features that the product owner thinks will be needed in the product and all of them are put in the product backlog. Unlike traditional requirements gathering techniques, it is not important to get all the features into the product backlog at the beginning because the product backlog can be added to, updated and priorities changed in the future as the product owner starts to see the product learning more about the software product while the developers are also learning more about the business. This allows the customer to drive the product according to the real needs he has at a certain time. It is important however to get as many features in the backlog at first, enough for the product owner to be able to prioritize the work and for the developers to develop in the first monthly iteration called sprint.

Projects are developed in SCRUM, using one month iterations called sprints. At the end of each sprint a potentially shippable product is delivered and presented to the product owner. Then another sprint is planned, built and delivered in the next 30 days and so on until the project is finished.

Each sprint starts with a sprint planning meeting where all the parties involved (the program owner, developers and SCRUM master) participate, but other interested parties like management or customer representatives can also be present. A meeting like this usually lasts up to an entire day, and is divided into two parts.

Part one of the planning meeting is when the product owner describes the most valuable items from the remaining features in the product backlog. This is done so that the features are described in more detail, so that later they can be estimated easier by the development team. When the team has something to clear up, this is done trough questions and direct conversations with the product owner. Not all remaining features are important to be described here by the customer, but enough from the product backlog, that can possibly fit in this sprint, choosing the most valuable first. The remaining items will be discussed in the future sprint planning meetings.

Trough this activity, the team and the product owner define where they want to get to when this sprint will be finished. Mike Cohn refers to this as defining the sprint goal. This is the expected and will be compared at the end of the iteration with the actual.

Part two of the sprint planning meeting is done to let the team see how much from the product backlog can they built in this sprint. For this the team discusses what they heard separately, seeing how much effort each item will need and seeing how many items fit into this sprint. Since the product backlog is sorted, by the product owner, descending on the basis of priority, the team can draw a line under the last item that can be included in the sprint. All these items will now be moved to the sprint backlog, in order to be built having the product owner approve the list. In some cases this list can be negotiated as some of the items might be more costly (in time) than others and based on this the product owner can reprioritize what needs to be done.

After the product backlog items are added to the sprint backlog, this list is sealed. Only in exceptional cases can it be modified, or items added to it, but this only with the explicit accept from the team.

The sprint backlog is different from the product backlog as in the sprint backlog, after the items have been moved from the product backlog, the sprint backlog items can be divided into programming tasks that are also items. The product backlog needs to be understood by the customer, but the sprint backlog can and should include tasks that can be understood only by the programmers and that help organize their work better.

Daily SCRUM meetings

At the beginning of each day, the team gets together for 15-30 minutes, to discuss the status of the project. This meeting goal cannot be derailed in any way, and is usually held with everyone standing in a circle, with each team member being asked the following questions by the SCRUM master:
- What did you do yesterday?
- What will you do until the tomorrow daily SCRUM?
- What prevents you from doing your work?

The daily meeting’s main purpose is for all to know where the project stands and for each to commit to something in front of the others, not the SCRUM master. The SCRUM master needs to do whatever possible to eliminate the obstacles raised by the answers to the 3rd question.

The daily meetings can be attended by other stake holders such as managers, even CEO to see progress; however they are not allowed to speak, just to hear. This is also known as the “pigs and chicken” technique, with the team being the pigs and the management being the chickens, being inspired from a short very relevant story:

A pig and a chicken discussed the name of their new restaurant. The chicken suggested Ham n' Eggs. "No thanks," said the pig, "I'd be committed, but you'd only be involved!"

[Larman, 2005]

Developing

SCRUM does not impose strict engineering practices like XP does, but it emphasizes the need for quality work, automated tests and daily builds of the system. Many teams do use TDD, Continuous Integration, even user stories and other practices from XP with great success, having a mixture of agile methodologies, as these agile methodologies have evolved together, XP planning game being influenced by SCRUM, and developing very successful projects that way.

Product presentation meeting or sprint review meeting

When a sprint has been finished (at the end of the 30 days) a sprint review meeting is held to compare the expected with the actual built, together with the entire team, the SCRUM master, the product owner being present and other stake holders. The meeting is very informal and PowerPoint slides and presentations are strictly being prohibited, the focus being on showing progress, by showing the software, going trough all newly developed backlog items from this sprint. After all, what better way to show progress than the product itself?

An emphasis is also put on getting feedback after seeing the product demo. Craig Larman says:

Feedback and brainstorming on future directions is encouraged, but no commitments are made during the meeting. Later at the next Sprint Planning meeting, stakeholders and the team make commitments

[Larman, 2005]

Doing it all over again

After the sprint has been finished and the actual result presented to the product owner and the other interested parties, it is time to take things from the beginning with the next sprint starting with the sprint planning meeting. This is done over and over again until the customer considers that the product is finished.



Scaling SCRUM

Usually a SCRUM team consists of four to seven team members. This does raise the question of how does SCRUM work when more then 7 developers are needed. The answer is in having more SCRUM teams, with daily meetings also being held across teams, each team sending a representative to these meetings.

Projects with several hundred developers have been developed using SCRUM, from small projects to large multi country teams with 330 to 600 developers involved, as the IDX project [Larman, 2005], [Cohn, 2004].

SCRUM is a project management method that exceeds the borders of software development being used in other domains as well. It is a “simple process for managing complex projects” in general, very well suited for software.

2.6 Crystal Clear

Introduction


Since 1990, methodology anthropologist Alistair Cockburn has studied all over the world how successful teams of developers build and deliver software, over and over again, and listed his findings in a methodology family called Crystal, which is composed of more methodologies, divided by the size of the team and also by the importance of the project, varying from the lightest: Crystal Clear to heavier methodologies, that get darker colors, such as yellow, Orange, Red etc, having the author believe that heavier processes are needed for larger projects, starting from the concept that one methodology cannot cover all aspects of software development.

What is Crystal Clear?

CC aims to be a simple and tolerant set of rules that puts the project on the safety zone. It is, if you will, the least methodology that could possibly work, because it shows much tolerance (Cockburn, 2005)

How do Crystal Clear teams work?

Properties, Tools and Practices

CC is based on a set of seven properties, which deeply influence development: frequent delivery, reflective improvement and close communication, personal safety, focus, early access to expert users and technical environment with automated tests, configuration management and frequent integration, but only the first 3 are a must.

Following CC the developers are organized in teams consisting of 2-8 members, with at least one level 3 developer, usually sitting in the same room, facing each other in order to facilitate verbal communication as much as possible. They sit side by side and collaborate often, this technique being called side-by-side programming. This is very similar with XP’s pair programming but differs from it as each team member has his own computer and can develop alone, or with the colleague on the right or on the left.

The development is divided into periods lasting from 1-4 months called deliveries, at the end of which the software will be deployed to the end users. Between these deliveries, at regular intervals, called iterations, the customer representatives are shown the working product and the feedback from them is gathered.

Requirements are obtained from the customer as “light” use cases and are obtained and prioritized together, with the customer and then a delivery plan is built for the next delivery.

CC teams constantly look back and improve the way they are working, both at the end of the iteration but also in the middle of it. This technique is put in practice by dividing actions done in 3 lists: things that worked and should be kept, things that didn’t work and should be dropped and things that could be tried next.

The design activity, which is continuous throughout the project, is done on a whiteboard, and if there’s need to keep a record of it, it is photographed and included into a document straight from the whiteboard.

The code being written is deliberately architected so that it can support a fully regression automated testing suite. These regression tests give them the possibility to do lots of changes and to adapt easily to shifts in direction of the product being developed, but the coding style is in the hand of the developers, they being the one that decide what best suites them. There are also as many integrations as possible putting together all the parts of the system and running the whole regression suite of tests.

Any team member can feel safe always telling what he thinks, like telling a manager that a schedule is unrealistic or a colleague that his design needs rework. Alistair Cockburn calls this the first step toward trust.

CC teams always focus on what’s the most important thing that needs to be taken care of now, and always have easy access to expert users or the client, that can always be asked to clear misunderstandings, to plan the next deliverable product or to receive feedback from them.

Besides the 7 properties of CC, it also comes with a series of recommended strategies and techniques, to be able to deliver value to the client fast. Some of them are very similar, inspired from or have evolved with practices from other agile methodologies.

There are 4 strategies: exploratory 360, walking skeleton, incremental rearchitecture and information radiators and 9 techniques: methodology shaping, reflection workshop, blitz planning, Delphi estimation using expertise rankings, daily stand up meetings, essential interaction design, process miniature, side by side programming and burn charts.

2.7 Lean Software Development

Lean software development is not a day to day strict practice methodology, but rather a set of 7 principles and 22 tools that can be used to successfully manage a project. Lean software development comes to complete the practices from other agile methodologies, with lessons learned in other industries, that are more advanced and mature that the software development branch. Jim Highsmith, said about lean software development that it presents a toolkit for project managers, team leaders, and technology managers who want to add value rather then become roadblocks to their project teams.

Origins

Much before the software industry, the auto industry had given up the waterfall model, in favor of a more lightweight but efficient model, that can produce results faster and in a concurrent manner. Mary and Tom Poppendieck published “Lean Software Development: An Agile Toolkit” in 2003,doing a wonderful job in adapting the lean principles, used in manufacturing, to software development. They have proved these practices, developing and managing software projects, demonstrating that not the inspiration from another industry was bad (some advocates of the agile methodologies have claimed that the inspiration in the 60-70’s from mechanical and construction engineering caused many problems in software), but that the mistake was not evolving with manufacturing and other industries when they dropped the waterfall model.

Mary and Tom also showed that some of the previous attempts to adapt lean principles to software failed because they were started wrong, without realizing the difference between development and product manufacturing.

The 7 principles

Eliminate waste – Taiichi Ohno’s (the father of Toyota Production System) said that anything that does not add value to a product, as perceived by the customer is waste. All agile methodologies have emerged as a response to chaos where the amount of wrongly used resources generates lots of overhead and waste , thus having a method to identify and cut unproductive activities, is considered, for software development as well, a very important tool.

In software development, the following are considered waste: partially done work, extra processes, extra features (never needed or used), task switching (people learning one system, then moving to another where another learning curve is needed), waiting, motion and defects.

Value stream mapping is the chart that enables you to simply see the periods that add value and the periods where time is wasted. Put in practice, this is a tremendous tool, showing huge gaps between value and waste.



[Value stream mapping in traditional processes, from “Lean Software Development: An Agile Toolkit”]

Amplify learning

Software development is a continuous learning and adapting activity between the customer and the developers, which learn from each other, communicate better and thus build better and more useful software. Feedback (tool 3) amplifies the learning process and because it is based

Synchronization (tool 5) allows concurrent development. Good synchronization is achieved with the customer through iterations (tool 4) and with the colleagues mostly with frequent code integration and reverse testing sessions. Synchronization is achieved better if we start from the interaction point first, from the interfaces of the different components.

Set based development (tool 6) is one of the greatest lessons we can learn about communication. Saying what the constrains of a system that needs to be built are allows the developer of the system to come up with more choices, with a set of solutions. Combined with further requirements, from that set of solutions the one that passes all constrains will emerge. If we ask specifically for a choice we might miss several alternatives and find ourselves stuck.

Decide as late as possible

Deciding for the future has been proved wrong as it can never predict changes and makes the cost of change enormous. Deciding later based on more information and keeping your options open (Options thinking – tool 7) is a better option. The last responsible moment (tool 8) enables you to take responsible decisions (making decisions – tool 9) late but not too late.

Deliver as fast as possible

Until recently rapid software development has not been valued; taking a careful, don’t make any mistakes approach has seemed to be more important

[Poppendieck and Poppendieck, 2003]

Lean product manufacturing and agile software development have proved that fast delivery is possible and leads to more satisfactory results for the customer. Recommended tools inspired from lean manufacturing are: Pull systems (tool 10), queuing theory (tool 11) and cost of change (tool 12)

Empower the team

Highly motivated, self organized teams, that have power to take decisions and put their ideas into practice, being lead by people with expertise, have always been a recipe for success (Self determination (tool 13), Motivation (tool 14), Leadership (tool 15), Expertise (tool 16))

Build integrity in

Perceived and conceptual integrity is what we understand by external and internal quality of a software product. If the integrity (tool 17) perceived by the customer is good, then the software that was asked for was built and is of high quality, and if the conceptual quality (tool 18) is goof, then the product’s internal quality is good, meaning that it can be extended, maintained and kept longer in use. The two fundamental practices at the base of integrity are testing (tool 20) and refactoring (tool 19).

See the whole

Making parts of a whole, at the highest quality does not necessary mean that when they are assembled together, the resulting system is at the highest quality and as required. Focusing on the whole system, helps making the parts better suited to work with each other and to compose a better system. The tools mentioned in achieving these are: Measurements (tool 21) and Contracts (tool 22)

Lean software development principles and tools should be in every agilist’s pocket no matter what methodology they follow, as they represent invaluable advice and proven practices to enhance efficiency.

2.8 AMDD – Agile Model Driven Development

AMDD is a light-weight approach for enhancing modeling and documentation efforts for other agile software processes such as XP and RUP [Ambler 2005], being extremely valuable in situations where written documentation and modeling are required. It is based on a set of principles, values and practices, which explain and enhance the role of modeling and documentation, in agile methodologies, based on the sufficiency principle, leaving unnecessary detail out.



Its author, Scott Ambler, a very active member of the agile community with great contributions especially on agile modeling, agile databases and database refactoring techniques, emphasizes in AMDD, that all agile methodologies include modeling, from the simple user stories and CRC cards to the automated tests as primary artifacts: acceptance tests as primary artifacts for requirements and unit tests as detailed design artifacts.

2.9 DSDM – Dynamic Systems Development Method

DSDM is an agile methodology, developed since 1994, and continuously improved by a non profit organization, called the DSDM consortium.

DSDM, breaks from traditional software methodologies, looking the work, from an entire different perspective:


DSDM is based on the following as core concepts: active user involvement, team empowered to make decisions, frequent releases, iterative development that are user feedback driven, reversible changes, requirements defined early at a high level, integrated testing, essential communication and collaboration, 20%/80% rule and having the goal to fit the business purpose.

2.10 FDD – Feature Driven Development

FDD is an agile methodology, developed by Jeff DeLuca and Peter Code, since around 1997, that puts bigger emphasize on modeling and offers good predictability in projects with more stable requirements, consisting of two main stages: discovering the features to implement and implementing them one by one.

The first stage, discovering the features, is done with the customers on site and marks the features to be implementing using UML.

The second stage develops the features, in 1-3 week iterations, in which more features to be done, are packaged. At the end of each iteration, the software produced is considered shippable.

2.11 Adaptive Software Development

Jim Highsmith is one of the most respected book authors and lightweight methodology advocates, in the agile community. He wrote a series of books on agile software development and agile software management, defining the Adaptive methodology, where he promotes the need for the continuous evolution and adaptation of the process used. He states that software development should be developed incrementally and iterative, trough repetitive cycles that include 3 stages: speculate, collaborate and learn.

Thursday, March 27, 2008

CHAPTER 1: Problems and causes with the way we develop software

Troughout this chapter I will try to show briefly how the software industry went from one extreme to another, in the processes used to develop software. If at first chaos was the main problem, then the software industry went straight into the other extreme adopting the extremely heavyweight "waterfall" process, where software was very hard to develop because there were too many rules. As an example at the beginning of Mary and Tom Poppendieck’s book “Lean Software Development: An Agile Toolkit” the following example is presented:

Jim Johnson, chairman of the Standish Group, told an attentive audience the story of how Florida and Minnesota each developed its Statewide Automated Child Welfare Information System (SACWIS). In Florida, system development started in 1990 and was estimated to take 8 years and to cost $32 million. As Johnson spoke in 2002, Florida had spent $170 million and the system was estimated to be completed in 2005 at the cost of $230 million. Meanwhile, Minnesota began developing essentially the same system in
1999 and completed it in early 2000 at the cost of $1.1 million. That's a productivity difference of over 200:1. Johnson credited Minnesota's success to a standardized infrastructure, minimized requirements, and a team of eight capable people.

In many organizations, the way the projects are organized and managed can determine very well the end result. The lack of good organization is the “cancer” in any business, ending sooner or later in failure. So what can we do as software developers?

History

At the beginning of the software development industry, due to lack of guidance and maturity, most projects were developed without any clear process applied. The difference was made by the people that developed the projects and their decisions, without any guidance from outside.

As the software industry started to develop, the number and the complexity of the projects started to increase, and soon enough, the need for a software process to be followed started to emerge. Many projects were developed in completely chaotic conditions and this made most of them end up as failures. The project managers wanted more visibility into their projects, and this need of predictability started to make them look in other engineering disciplines and adapt the management practices from there.

At the time, most industries had already developed and used, for decades, predictable processes where everything was carefully planned from the beginning and then designed, implemented and tested before being deployed.

In 1970, W. Royce writes a paper, where he exposes the so called “waterfall model”, where a project is developed in more stages, in a very clear order, no stage starting before the completion of the former one. At the time, the waterfall model started to be adopted by many software organizations, being a massive step ahead from the chaos that used to characterize the software industry.

The waterfall model

The waterfall model presumes four consecutive phases:
1. requirements & analysis,
2. design,
3. implementation
4. testing.

The process takes its followers from one phase to the next sequentially, each phase being needed to be finished before the next can be started.

The first phase presumes obtaining the requirements from the customers and is finished only after these requirements are analyzed and approved by the client, usually signing off a requirements specification document that needs to be carved in stone before the next phase can start: designing the software. This phase, presumes that the whole system is designed and architected in the smallest details before it goes into production. This process is often called, big design up front, and needs to find all the risks involved and solve all the problems before it can go to the next phase. The design is a very detailed plan of how the requirements should be implemented for the coders.

Following the detailed design the programmers implement the software. Usually the implementation is done in many different components that are integrated together after they have been built. When all the components have been build and integrated to form a whole, the next phase can start: testing and debugging.

The obtained system is being now thoroughly tested and the bugs found are now solved to be able to release the software. When this phase ends the software is ready and it can now be shipped and/or deployed to the client.

By the early 80’s many software developers realized that the waterfall model based processes have some very serious problems especially when predictability in a software development is hard, requiring lots of changes late in development, which were considered extremely expensive.

Risks and smells associated with the waterfall model

The waterfall model seems very good, predictive and easy to grasp and follow, but practice has proved it has some serious risks associated to it. The fundamental idea behind waterfall is that finding flaws earlier in the process is more economical and thus less risky. Finding a design flaw in the design phase is the least expensive, but finding it in a later phase like implementation or testing can generate serious problems and derail the project. Many times this is very hard, even for very experienced architects such as Martin Fowler who said:

Even skilled designers such as I consider myself to be, are often surprised when we turn such designs into software

[Martin Fowler, 2005].

Big design up front is driven by the enthusiasm that risks can be hunted down and eliminated early and a very good design produced. But …

…the designs produced, can in many cases look very good on paper, or as UML designs, but be seriously flawed when you actually have to program the thing

[Martin Fowler, 2005].

The most serious risk when it comes to the waterfall model is the fact that it is very change adverse. Since it is based on the presumption that everything can be predicted, changes can be very hard to do once the process was started, and extremely costly in later phases.

In many cases, there’s a lot of overhead associated with the process. Usually lots of documentation is produced, to plan, to track, to demonstrate progress, to test, to etc, and in many cases producing the documents becomes a purpose, having people produce very professional documents, very detailed plans, very eye capturing charts, that have a lot of time invested in them, but do not have direct business value for the client, or the value is under the cost.

In a business process, there are documents, reports and charts that can be very helpful to be able to organize and manage, but it is also very important to constantly keep an eye on the amount of documentation, on the amount of time spent in meetings, and basically, in doing anything else that doesn’t have direct value for the client or keeps the whole process together so that it can deliver running tested features to the client.

Being fundamentally a sequential process, which presumes that one phase much be completely finished before the next can be started, the waterfall model propagates delays from one phase to another, every delay adding to the overall length of the project.

Although the risks were being seen from the late 70’s and early 80’s, in the mid 80’s the US Department of Defense, adopted the waterfall processes as a standard to develop software. This was later extended to NATO, and most west European armies adopted it. If the military made the waterfall a standard, then the entire industry was influenced, so the waterfall model process found new heights in adoption and promotion.

The need to evolve

In the early ’90s, a lot of developers started individually, to develop a new process, which was a response to both chaos and to the flaws in waterfall processes.

In their quest to find an answer to the problems associated with chaos and the heavyweight processes used throughout the industry, the developers started to question the very base of the waterfall model, it’s inspiration from other industries. Martin Fowler, one of the most respected authors in the programming field, wrote in an article called “The New Methodology” [] :

When you build a bridge, the cost of the design effort is about 10% of the job, with the rest being construction. In software the amount of the time spent in coding is much, much less. McCornell suggests that for a large project, only 15% of the project is code and unit test, an almost perfect reversal of the build bridge ratios. Even if you lump all testing as part of the construction, the design is still 50% of the work. This raises a very important question about the nature of design in software compared to its role in other branches of engineering.

On the other hand, Craig Larman says that software development is more like new product development where there are lots of uncertainties, rather then product manufacturing which is much more, straight forward, because it means doing something that has been done before:

Mary and Tom Poppendieck, continue the idea that software is a development activity, very different from production environments in other industries, making the following comparison of development and production.

Think of development as creating a recipe and production as following the recipe. … Developing a recipe is a learning process involving trial and error. You would not expect an expert chef's first attempt at a new dish to be the last attempt. In fact, the whole idea of developing a recipe is to try many variations on a theme and discover the best dish

The idea that software, is by its nature, more a continuous learning and adapting process, then a predictive process, sits at the base of many new processes that started to be developed in the early 90’s and which in 2001, were named agile.

On the other hand, some people coming from manufacturing, showed that it was not the inspiration from other industries that was wrong, but the fact that the software industry did not see that the other industries dropped the waterfall based processes 10-20 years ago, in favor of concurrent and lean development. Mary Poppendieck states:

I had been out of the software development industry for a half dozen years, and I was appalled at what I found when I returned. Between PMI (Project Management Institute) and CMM (Capability Maturity Model) certification programs, a heavy emphasis on process definition and detailed, front-end planning seemed to dominate everyone's perception of best practices. Worse, the justification for these approaches was the lean manufacturing movement I knew so well.

I was keenly aware that the success of lean manufacturing rested on a deep understanding of what creates value, why rapid flow is essential, and how to release the brainpower of the people doing the work. In the prevailing focus on process and planning I detected a devaluation of these key principles. I heard, for example, that detailed process definitions were needed so that "anyone can program," while lean manufacturing focused on building skill in frontline people and having them define their own processes.

I heard that spending a lot of time and getting the requirements right upfront was the way to do things "right the first time." I found this curious. I knew that the only way that my code would work the first time I tried to control a machine was to build a complete simulation program and test the code to death. I knew that every product that was delivered to our plant came with a complete set of tests, and "right the first time" meant passing each test every step of the way. You could be sure that next month a new gizmo or tape length would be needed by marketing, so the idea of freezing a product configuration before manufacturing was simply unheard of.

Even worse, it was shown, that the paper of W. Royce from 1970, where the waterfall model was first defined was actually showing the risks associated with the waterfall model, and the author urged the software developers to use the spiral model, which he thought was better. However, the misunderstanding that he was actually saying that waterfall processes are the way to go in software is the biggest misunderstanding in software development.


Conclusion


Clearly good software cannot be developed on the long term in chaotic conditions, and at the same time, waterfall processes are too heavyweight, as in many cases they are an overkill. The new business world in which we live in, where dramatic changes happen very fast in the market, require that software development come up with a new, evolved method, where software can be delivered faster, on more unstable requirements, and where the direction can be changed if needed in the middle of the way.

Agile methodologies have the same goal as all the other processes: producing software. However, the problems that they aim to solve are very different from traditional processes: fast delivery in changing, unpredictable conditions. Adapting to changes rather then trying to predict the future.


http://en.wikipedia.org/wiki/Waterfall_process
http://www.martinfowler.com/articles/newMethodology.html

Friday, March 21, 2008

The agile mini book - a 6 week series

About 2 years, ago, I spoke with someone about writing an agile mini book. I wrote the book, but things changed, and it wasn't published. Now I decided, to publish it, chapter by chapter, week by week so for the next 6 weeks this is what can be expected:

CH1: Problems and causes
CH2: Agile methodologies
2.1 Introduction
2.2 Agile menifesto and principles
2.3 Agile methodologies, practices, properties and tools
2.4 XP
2.5 SCRUM
2.6 Crystal Clear
2.7 Lean Software Development
2.8 AMDD
2.9 DSDM
2.10 FDD
2.11 Adaptive Software Development
CH3: Communicating
3.1 Introduction
3.2 Communicating with the customer
3.2.1 Requirements
3.2.2 Set based development
3.2.3 Feedback
3.3.4 Showing progress
3.3 Communicating inside the team
3.4 Improving communication: quality vs quantity
3.5 Collaborating
CH4: Learning and adapting
4.1 Introduction
4.2 Circle of life - learning and adapting
4.3 Reflective improvement
CH5: Managing and organizing
5.1 A small agile process practice sample
5.2 Iterative and Incremental process
5.3 Adaptive planning strategy
5.4 Evolutionary design strategy
5.5 Fast delivery strategy
5.6 People first strategy

CH6: Quality and testing
6.1 Internal and external quality of a system
6.2 Automated tests and manual testing
6.3 Test Driven Development

I hope you'll enjoy reading the 80 pages. Each chapter will also be available for download for free, as a pdf.

Thanks,
Dan

Sunday, October 21, 2007

Lucene indexes as agile databases

Download Source code

Introduction

In product development, as opposed to bespoke project development where each client gets its own software, you deliver the same software to each client. This has some advantages: single development stream, with multiple sales but in reality each client will want to be able
to customize its own product. Each will divide its products differently, will have different fields and if your product is not flexible enough to allow these policies they will reject your product.

Relation databases are not agile enough

In an agile manner, when developing a software project, you plan for change. In Extreme Programming, they say a piece of code has a good internal quality if it can be easily maintained, changed and debugged. In product development, the data store changes from one version to another and this is often a big burden. Relational databases simply haven't been designed to be easy to change their structure. Once an ALTER deletes a column, the entire database becomes unstable, you have to check each select, update, insert, each statement to make sure it doesn't crash. Migration scripts are hard to create and very error prone.
There are many workarounds, but none of them is trivial work.

ActiveDocument: Indexes as truly dynamic databases

Indexes were designed, having in mind that they need to search large repositories, extremely fast. Look at Google. It indexes over a billion websites and it is FAST.

Could an index be better structured the just having large quantities if text documents, for instance having types and properties, relations between entities, pretty much what a common relational database would have, and beyond that a truly flexible infrastructure, where typescan be created, modified and destroyed on the fly, where their properies could be added, removed or their names changed withought fear? Something that in C# would be like:


As it can be easly seen we create a type (Product) on the fly, with no need to define a table or any kind of structure, and then we add properties to the instances of this type, which can differ. Structure is actually defined and changed dynamically at runtime. The two product instances above, both have a Name, but only one has a Category, and the query still works.

Ladies and gentelmen this technology is possible, and is called ActiveDocument, and the sources can be downloaded from here

Besides being able to store typed data, and retrieve it fast and easy, we can also relate data:



Conclusion

Is it a breaktrough? Will this kill the relation databases? Is this 100% safe? I have no idea. I am discovering the advantages and disadvantages as we go, and I am sure some others will certainly like to help me on this journey.

Pros and cons to using indexes instead of databases

-fast
-scalable
-they don't break
-...

Cons

-no joins
-no transactions
-no foreign keys
-...

Please feel free to add :)

Labels:

Wednesday, March 28, 2007

Testing drag'n'drop with WatiN

Many of the recent Web 2.0 applications require drag and drop functionality. Sometimes it is useful, sometimes it is just marketing, but if you have to do it and at the same time you want to write all your code test first (TDD), a new problem arises: how to write a functional test to test the drag drop?


Starting from a wonderful article on the 'Z Bar Zone' blog, I modified it to work with WatiN in C#. The code tests the wonderful scripta.aculo.us based drag'n'shop:




using System.Threading;
using mshtml;
using NUnit.Framework;
using WatiN.Core;

namespace TestDragDropWatiN
{

[TestFixture]
public class DragDropScriptaculousTests
{
IE ie = null;

[Test]
public void TestDragDrop()
{
ie = new IE("http://demo.script.aculo.us/shop");
ie.ShowWindow(NativeMethods.WindowShowStyle.Maximize);

//add some items to the cart
int[] ids = new int[] { 1, 1, 2, 1, 2 };
foreach (int id in ids)
{
string product = "product_" + id;
RunScript("document.blah = document.createEventObject(); document.blah.button = 1");//create event object
RunScript("document.getElementById('" + product + "').fireEvent('onmousedown', document.blah)");//click on product-fire mouse down on product_id div
RunScript("document.blah = document.createEventObject(); document.blah.clientX = document.getElementById('cart').offsetLeft; document.blah.clientY = document.getElementById('cart').offsetTop");//obtain position of the cart
RunScript("document.getElementById('" + product + "').fireEvent('onmousemove', document.blah)");//move the product div to te cart-fire onmousemove
RunScript("document.getElementById('" + product + "').fireEvent('onmouseup', document.blah)");//drop-fire onmouseup


Thread.Sleep(1000);
}

//remove some items from cart
string[] items = {"item_1_1","item_2_0"};
foreach(string item in items)
{
RunScript("document.blah = document.createEventObject(); document.blah.button = 1");//event object
RunScript("document.getElementById('"+item+"').fireEvent('onmousedown', document.blah)");//click on item in the shopping cart
RunScript("document.blah = document.createEventObject(); document.blah.clientX = document.getElementById('wastebin').offsetLeft; document.blah.clientY = document.getElementById('wastebin').offsetTop");//obrain position of the wastebin
RunScript("document.getElementById('"+item+"').fireEvent('onmousemove', document.blah)");//move item to the wastebin
RunScript("document.getElementById('"+item+"').fireEvent('onmouseup', document.blah)");//drop-fire onmouse up
Thread.Sleep(1000);
}

ie.Close();
}

private void RunScript(string js)
{
IHTMLWindow2 window = ((HTMLDocument)ie.HtmlDocument).parentWindow;
window.execScript(js, "javascript");
}

}

}




Enjoy :)

Friday, January 19, 2007

Test First Web Applications: TDDing a Castle MonoRail application with C# and Selenium

Published on InfoQ.com

Download Source code

Introduction

TDD samples are mostly based on very simple unit tests. But how could we do something like building a web application test first.

What we need to do

Let's say that we need to write test first the following feature for an application

-manage users (add new, delete, edit user details, list all).

Each user will have a Full Name, a Username , a Password and an Email all mandatory.

What is TDD

Following TDD steps:

1. write the test
2. make it fail
3. write the code to make the test succeed
4. refactor
5. go to 1

Our first test

The first test we could write would be the test to add a new user. Test Driven Development is a design technique rather then a testing technique, because when writing the test, we will define how the code/page will work, designing it.

In order to be able to add a new use we think that we will need a form like this:

so for our functional test we would need to open up the add page (prepare stage), fill the fields and save (action stage) and to verify if the user was actually saved (verification stage of the project). In order to do that, we would probably need to update our page and add a new list with the users on the left side, where we can later check if our user exists after clicking save.

Selenium comes into action

But in order to do something like this we need a tool that can actually do this action on behalf of us, in a browser. For this task there is an excellent open source tool called: Selenium , which can allow this kind of web based functional tests, and which also allows the tests to be written as simple html tests, having an interpretor that runs those actions for us:

The great news for people that want to integrate their tests on a continuous integration tool is that they can write the tests in their own preferred language like C#, Java, VB.NET, ruby, python, using an extention of Selenium called Selenium RC.

Using Selenium RC, .NET version our test would look like:


At this stage we haven't written any piece of code ar page, so our test should fail. Let's see...

First we start the Selenium RC server (a small java server that handles the selenium commands and transmits them to the browser):

java -jar selenium-server.jar

and running the test fails:

Yes it does. This is a good sign as this means that our test fails when it has to, otherwise our test wouln't really test anything and would be worthless.

On step 3 in our TDD steps, we need to start writing the code until we make it work. So we create the UsersController and the view and run the tests:


and we just create an empty add.vm and resun the test:

Selenium.SeleniumException: ERROR: Element link=Add new user not found

at Selenium.HttpCommandProcessor.DoCommand(String command, String[] args)
at Selenium.DefaultSelenium.Click(String locator)
at MRProjectTest.Functionals.Selenium.ManageUsersTests.TestAddNewUser() in ManageUsersTests.cs:line 34

Now since the error says that it couln't find the elements on the page, we add them in add.vm:

and retest:

.... error again since it submits the content on the form to create.aspx when clicking the button but that is not implemented yet. So we add the code to save the data:

but wait because we don't have the User class, the list action or the database.

TDD-ing the layers under the presentation layer

But in order to build this code we need to build it test first. Although in some cases this isn't really necessary since ActiveRecord is already quite well tested and since this thing is also covered by our functional test, we still do it, to show how for more complicated situations it should.

The test, which is not a functional but a integration tests (a unit test that also uses the database):


Test if it fails. In fact it doesn't compile so the first thing would be to create a User class, with empty methods to make the code compile:


Now, we run the test:

Castle.ActiveRecord.Framework.ActiveRecordException: An ActiveRecord class (UserManagement.Model.User) was used but the framework seems not properly initialized. Did you forget about ActiveRecordStarter.Initialize() ?

at Castle.ActiveRecord.ActiveRecordBase.EnsureInitialized(Type type)
at Castle.ActiveRecord.ActiveRecordBase.Save(Object instance)
at Castle.ActiveRecord.ActiveRecordBase.Save()
at MRProjectTest.Database.UsersDataAccessTests.TestSaveNewUser() in UserDataAccessTest.cs:line 23


We do not have the User class initialized in ActiveRecord, for that we adapt our test:

and also the User class, adding the appropiate attributes, for ActiveRecord and the constructors and by reruning the test, it tells us that we do not have the corresponding database table. By adding the following line in the test:

ActiveRecordStarter.CreateSchema();//create the database schema

Running the test, we see that the database table was created, but still we have a problem:

System.NotImplementedException: todo

at UserManagement.Model.User.Find(Int64 id) in User.cs:line 72
at MRProjectTest.Database.UsersDataAccessTests.TestSaveNewUser() in UserDataAccessTest.cs:line 41

We finish implementing the Find method in User class:

public static User Find(long id)
{
return (User) FindByPrimaryKey(typeof(User),id,false)
}

and finally we have a database test that works!

Top down TDD approach

Usually tests like this one aren't really required, for the two reasons mentioned earlier but it was done so that the flow is understood, in a test frist, vertical development, for a n-tier application.

Back to the functional test

Now that we know that the User class exists and the database access works, it is time to continue on the presentation layer.



We now implement the list action and view:

public void List()
{
PropertyBag["users"] = User.FindAll();
}

and create a list.vm:


For the view we could have used a GridComponent. By running the test we see that for the first time we have a UI test working :)



Edit functionality

Now we need to add to our site the edit user functionality. Basically the functionality will be like this: on the list of users page, each user will have an Edit link, which clicked upon will transfer the user to a editing for where he can modify the user details. When the form is saved the user is sent back to the list. Now let's write the test:

as you can see we added a User to the database, so when we open the list page, we have something to edit. But wait, we have a problem. If we run twice the test, the user will be inserted twice in the database. In order to avoid that we do the following:

Running all the tests, we see that the edit test fails:

Selenium.SeleniumException: ERROR: Element link=Edit not found

at Selenium.HttpCommandProcessor.DoCommand(String command, String[] args)
at Selenium.DefaultSelenium.Click(String locator)
at MRProjectTest.Functionals.Selenium.ManageUsersTests.TestEditUser() in ManageUsersTests.cs:line 28

we now add the Edit link in the list.vm:

and an Edit action in the controller:

public void Edit(long id)
{
PropertyBag["user"] = User.Find(id);
}

now the view for this action: edit.vm


and since the value will be saved in the update action we'll also have:

public void Update([DataBind("user")] User user)
{
user.Update();
RedirectToAction("list");
}


All tests passed. :)

All tests run. Refactoring

We can easily remark that there are a few refactorings that we can make. First, the TestAddNew and TestEdit methods are almost similar, so we can do:


having also:


We run the tests, they still work. Now we go further, into the views, which have the same problem: add.vm and edit.vm are almost identical. We'll separate the common part into _form.vm. Running the tests still confirms the fact that we haven't ruined anything we did before:


For the delete, we use the same priciple with the test first, until we make it work. To add validations or any other functionality the user will be able to use, we add new tests, then the code to make them pass.

Conclusion

We have shown an example of designing an application, with a method called incremental architecture, where the actual architecture of the system does not need a month to be thought in advance, but is constructed as the code is constructed, because changes are very easy to be made, continuously refactoring the code to make it better, all provided by our tests.

1. Selenium - www.openqa.org - open source web functional testing tools
2. Castle Project (MonoRail and ActiveRecord) - www.castleproject.org - open source lightweight ASP.NET/ADO.NET alternative

Labels:

Thursday, January 18, 2007

Ajax Scaffolding generator with Monorail: a VS.NET 2005 addin

Download the VS 2005 addin

In my previous article, I explained how by modifying Marc Andre Cournoyer's generator, we made it generate Ajax based, scaffolding code for Castle MonoRail. In the meantime, my colleague Gabi Munteanu, managed to put together a Visual Studio 2005 addin, exactly for this purpose.


1. Generate the model

Let's start from an generated ActiveRecord class called Project we had the last time, generating the ajax scaffolding code needed for the project:


obtaining:

using Castle.ActiveRecord;

namespace Models
{
///
/// An instance of this class represents a Project.
///
[ActiveRecord]
public class Project : ActiveRecordValidationBase {
#region Fields
private int _id;
private string _name;
private string _description;
#endregion

#region Persistent properties
[PrimaryKey]
public int Id {
get { return _id; }
set { _id = value; }
}
[Property]
public string Name {
get { return _name; }
set { _name = value; }
}
[Property]
public string Description {
get { return _description; }
set { _description = value; }
}
#endregion

}

}


Using the ActiveRecordStarter.CreateSchema we also create the corresponding database table.

2. Generate the scaffold


then


Unfortunetely, we'll still have to manually include the files in the project (still working on this):


3. Final adjustments

In order to make it work we need some adjustments to our Project class:

using System.Collections;
using Castle.ActiveRecord;
using NHibernate.Expression;

namespace Models
{
///
/// An instance of this class represents a Project.
///
[ActiveRecord]
public class Project : ActiveRecordValidationBase {
#region Fields
private int _id;
private string _name;
private string _description;
#endregion

internal static IList FindAll()
{
return FindAll(typeof(Project));
}

internal static IList FindAll(string property)
{
return property.Equals("") ? FindAll(typeof(Project), new Order[1] { Order.Desc("Id") }) : FindAll(typeof(Project), new Order[1] { Order.Asc(property) });
}

internal static Project Find(int id)
{
return FindByPrimaryKey(typeof(Project), id) as Project;
}

#region Persistent properties
[PrimaryKey]
public int Id {
get { return _id; }
set { _id = value; }
}
[Property]
public string Name {
get { return _name; }
set { _name = value; }
}
[Property]
public string Description {
get { return _description; }
set { _description = value; }
}
#endregion


}

}


Now we see the result:







Conclusion

The project is till in early stages, but it can still generate very good code and save a lot of time needed to generate the same all CRUD code, needed in any application.

Labels:

Monday, December 18, 2006

Ajax Scaffolding with Castle MonoRail and C#

Download Sources, and view demos

Goal

Let's say we need to write an application very fast, that can do the basic CRUD operations for a Product. Ruby on rails (www.rubyonrails.org) came up with the excellent idea of scaffolding, and the idea was ported into the Castle Monorail project (www.castleproject.org). However, the default generator both in ROR and in MR, do not generate ajax based code. For ROR the solution is at: www.ajaxscaffold.com but nothing so far for MR. So I decided to take matters in my own hands...

Where do we start from?

The excellent generator by Marc Andre Cournoyer can generate projects, controllers, migrations, model etc and the templates can be changed to suit one's needs extremely easy. Starting from Marc Andre's generator I configured the templates to generate AJAX based code.

Let's see how it works, step by step starting from nothing.

Step 1: we make a new MonoRail project

Using latest RC2, and VS.NET 2005, we generate the project using the wizard inside VS.NET.



resulting in:



Then we edit the web.config and we create a new database called Products.

Step 2: we generate the persistent activerecord class and the database table

Starting for a basic Castle Monorail/ActiveRecord project, we start by creating the Product class, and then generating the database table corresponding to it. In the application's root folder, we type: generate model Product Name Description Price and it generates the code for us:


obtaining the following code (click view all files on the web project, and include the new file in project)

///
/// An instance of this class represents a Product.
///

[ActiveRecord]
public class Product : ActiveRecordValidationBase {
#region Fields
private int _id;
private string _name;
private string _description;
private string _price;
#endregion

#region Persistent properties
[PrimaryKey]
public int Id {
get { return _id; }
set { _id = value; }
}
[Property]
public string Name {
get { return _name; }
set { _name = value; }
}
[Property]
public string Description {
get { return _description; }
set { _description = value; }
}
[Property]
public string Price
{
get { return _price; }
set { _price = value; }
}
#endregion

internal static IList FindAll()
{
return FindAll(typeof(Product));
}

internal static Product Find(int id)
{
return FindByPrimaryKey(typeof(Product), id) as Product;
}

}

To generate the database schema we just use:

ActiveRecordStarter.CreateSchema();

and we have the table in our database.

Step 3: we generate the Ajax Scaffolding code

We type in our command window: generate scaffold Product and it will generate all the needed code dor adding, listing, editing and deleting products, using Ajax:


now we include the generated files in our solution from Visual Studio 2005 (right click, Include in project):



Step 4: we run the code. It works!

We start the application:

then we add:


after adding two products:

now viewing in place:


and editing:


and the same with deleting.

What about validations?

Let's say that the name and the price are required. We modify the Product class, to add the validation attributes:

///
/// An instance of this class represents a Product.
///

[ActiveRecord]
public class Product : ActiveRecordValidationBase {
#region Fields
private int _id;
private string _name;
private string _description;
private string _price;
#endregion

#region Persistent properties
[PrimaryKey]
public int Id {
get { return _id; }
set { _id = value; }
}
[Property,ValidateNotEmpty("Name is not optional.")]
public string Name {
get { return _name; }
set { _name = value; }
}
[Property]
public string Description {
get { return _description; }
set { _description = value; }
}
[Property, ValidateNotEmpty("Price is not optional.")]
public string Price
{
get { return _price; }
set { _price = value; }
}
#endregion

internal static IList FindAll()
{
return FindAll(typeof(Product));
}

internal static Product Find(int id)
{
return FindByPrimaryKey(typeof(Product), id) as Product;
}

}

and restart the application:



How hard is it to extend the product?

Let's say that we've just found out that besides the Name, Description and Price, we also need to add to each product a serial number. We modify the Product class, adding the new field and property:

private string _serialNumber;

...

[Property]
public string SerialNumber
{
get { return _serialNumber; }
set { _serialNumber = value; }
}

Now, we recreate the table:

ActiveRecordStarter.CreateSchema();

and start the application:

and


so it doesn't need any modification in the code or views.

What about relationships?

Let's consider that we want each product to be part of a Category. Following the steps above we create a class Category:

[ActiveRecord]
public class Category : ActiveRecordValidationBase {
#region Fields
private int _id;
private string _name;
private IList products = new ArrayList();
#endregion

#region Persistent properties
[PrimaryKey]
public int Id {
get { return _id; }
set { _id = value; }
}
[Property]
public string Name {
get { return _name; }
set { _name = value; }
}

[HasMany(typeof(Product))]
public IList Products
{
get { return products; }
set { products = value; }
}

#endregion

public override string ToString()
{
return this.Name;
}

and modify the product to be part of a Category by adding:

private Category _category=null;
...
[BelongsTo("CategoryID")]
public Category Category
{
get { return _category; }
set { _category = value; }
}

we regenerate the database, obtaining:


Using the generator we also generate the ajax scaffolding code to add/edit/delete and list categories. Now we add two categories:


and going to add new products we'll also have the category combobox, without us making any modification in the code or the views:


Conclusion

As it can be seen above, with very little effort, in 10 minutes we can create an easy to extend ajax application (thanks to Castle Project and Marc Andre's generator). The code is quite clear and easy to debug and extend, and since it is ajax based it can be easily integrated in existing web applications.


Labels:

Tuesday, October 24, 2006

Agile Methodologies Presentation: from problems to agile solutions: iterations, TDD and reflective improvement

Download as ppt here


Problems


-information too late to managers - better tracking - solving it, increases profit by not losing lots of work and redoing it
-bad quality projects - solving it increases profits, by not debugging from our own pocket
-late projects, lack of time - solving it increases customer satisfaction and guarantees future contracts
-poor communication with the customer, management (already discussed), inside team and with the code - solving it increases the speed and trust in development

Solutions
the 3 core practices as a solution


-Iterations – projects get divided into short equal iterations, at the end of each some new functionality get shown to the client
-TDD – Test Driven Development, a design practice oriented at making development faster and changes late in development much easier
-Self improvement meetings – reflection workshops listing that activities divided as: to keep, to drop, to try


Information Too Late To Managers: Sow how can we manage?

Problem:

Manager need to know the information fast and very reliable, but it is not happening until it is usually very late and hard to cope with

Causes:

-the way information travels to managers is in many times flawed. Asking an engineer/programmer whether will he be ready on the planned date, is just like asking whether your new Armani suit looks good on you. In most cases the cannot tell you no, even if they are very well intentioned.
-a manager gets to see the actual software a few days before the delivery is scheduled, when in many cases is too late
-most times managers only get reports about the work, which as seen previously can be made more positive then the reality is, and if the status document travels upwards, it tends to be 'improved' by the ones that get their hands on it

Solution (Information Too Late To Managers: Sow how can we manage?)


2 managers (Ken Schwaber and Jeff Sutherland) running large companies, with lots of codebase and problems in the early 90s invented a methodology that allows them to get the REAL information ON TIME. It is called SCRUM, and it only has very few practices:


- Self managing, cross functional teams or max 6-8 people (for more a scrum of scrums is applied)
- Backlog (the list of things to be done)
- Sprints (One month iterations)
- Sprint planning meeting (at the beginning of the sprint)
- Product demo meeting (demo to the client at the end of the sprint)
- Daily meetings (each morning developers say what they do, and what the problems are if any)

A process outline

1. Build backlog (list of items/features etc needed in the application) and prioritize – the big plan with releases
2. Organize the first iteration/sprint, cutting from the prioritized backlog - a sprint=a project
3. Iteration/Sprint Planning meeting - detailing with the customer what needs to be done, no need for too many details before
4. Daily meetings throughout development - finding out what is going on
5. Product demo meeting - SEEING actually where the project really is
6. Go to step 1 or 2 for the second sprint


So the backlog is the plan to follow, the demo is when the manager sees if the team is on track or not. If it is not they can be fired, replaced etc instead of actually seeing the problems after 5 months on a 6 months project, when it is impossible to do something. In the daily meeting the manager can find out what are the problems in the team, especially if they are going to be late with the sprint delivery.

Process sample: building the backlog/list of requirements

A new client who wants a new software product to manage and track his sales and customers. System to go live in 2 months. We meet and establish what is required, then plan to meet the deadline. After the first meetings we come up with the following feature list, that he thinks he wants, that is afterwards estimated by us:

Client management (3p)
Product management (3p)
Sales leads management (4p)
Sales reports (3p)
Client activity management (3p)
User management (2p)
Sales workflow (3p)

Process sample: planning the releases

Now together with the customer, we make the first plan, dividing the work in two iterations:

Iteration #1: 10 p
Client management (3p)
Product management (3p)
Sales leads management (4p)
Iteration #2: 11p
Sales reports (3p)
Client activity management (3p)
User management (2p)
Sales workflow (3p)

After we have a plan to deliver the 21 points features in 2 months, we start working, by starting on the first iteration, at the end of which we deliver features 1,2 and 3.

Process sample: delivering and customer wants more



We now show the customer the first 3 features implemented, but he suddenly realizes that he needs more, then what was planned for the release. We start by adding what he wants to the list of features, which now becomes, after each of the new features are being estimated.

Client management (3p)
Product management (3p)
Sales leads management (4p)
Sales reports (3p)
Client activity management (3p)
User management (2p)
Sales workflow (3p)
Activity calendar (3p)
Forecast reports (3p)
Document templates and document merging (3p)


Process sample: changing/adapting the plan


We cannot deliver all in the 2 months term, but we make a delivery after the two months and we plan another delivery after that will include other features that will make the system more compete. The new plan looks like:

Release #1: 2 months
Iteration #1: 10p
Client management (3p)
Product management (3p)
Sales leads management (4p)
Iteration #2: 11p
Sales reports (3p)
Client activity management (3p)
User management (2p)
Forecast reports (3p)

Release #2 not defined fully yet
Iteration #3: 9p

Sales workflow (3p)
Activity calendar (3p)
Document templates and document merging (3p)

Process sample: new requirements/new plan

Release #1: 2 months
Iteration #1: 10 p

Client management (3p)
Product management (3p)
Sales leads management (4p)
Iteration #2: 11p
Sales reports (3p)
Client activity management (3p)
User management (2p)
Forecast reports (3p)

Release #2
Iteration #3 – 9p
Sales workflow (3p)
Activity calendar (3p)
Document templates and document merging (3p)
Iteration #4 – 10p
Contact communication management (3p)
Microsoft outlook integration (2p)
Sales processes (5p)


Iterations: benefits

-increase focus and the need to organize inside the team by give a near-term deadline Mark Twain: “Nothing focuses the mind like a noose”
-good instrument for planning, tracking progress
If the product is presented each time, it is easy to see where the project is
-minimize risks Agile thinking minimizes risks because it focuses on the most important and valuable features for the customer, and develops them first
-good instrument for managing changes in software At the end of an iteration, direction can be changed, and plans adapted to the new needs.
-good instrument to build trust By showing the customer the software after each iteration, he can see progress

Iterations: benefits (2)

-allow learning and adapting
Because the customer sees the results after an iteration, he can better express his needs, and he better understands what’s possible and what’s cost effective
-are a good instrument for development At the end of an iteration, a set of features must be shown as working. This transfers the focus of the developers, from developing a system horizontally, layer by layer, from data access, to business and presentation layers, assembling the whole system at the end. Instead the focus is on delivering working features, developing them vertically on all layers.
-build confidence and motivate in the team One very important aspect in development, especially in the early stages of a project is an early victory. By delivering the first iteration, the team starts to see something positive happening and starts to build confidence that it will win. With each new iteration a new battle is won, getting the team closer and closer to winning the war.
-bring honesty Since iterations are short the customer sees the product developed quickly, delays are surfaced very early, not allowing them to grow into serious problems.
-good instrument to increase quality At the end of each iteration, a potentially shippable product must be shown to the customer. This focuses the team on keeping the quality high, never letting bugs and quality problems perpetuate.

Bad quality increasing costs dramatically (debugging time)

What is quality?

In order to understand what quality is we must divide it into external quality of a system and internal quality, where external quality means what the customer thinks of the system, and internal quality is when the program is easy to change, extend and to maintain


External quality – whether the customer is happy by what he sees and feels
Problem: Poor external quality makes the customer send back the project for rework, and rework kills profits very fast.
Testing a system only at the end is not going to make the project deliverable faster, but in most cases it only shows it down. This does not mean that untested system should be delivered, but that testing should be started in min 1 of a project (acceptance tests, TDD, manual testing as the tools)
Solution: frequent feedback from the customer.
Tools:
Iterations and product presentation meetings. When each iteration is finished, the product’s planned features are demo-ed to the customer
Acceptance tests gathered from the customer, at the beginning of the iteration, to confirm at the end that what was asked for was implemented

Internal quality


Internal quality – whether the project can be easily changed, maintained and extended.
Problem: “Nothing kills speed more effectively than poor internal quality” Martin Fowler - Planning Extreme Programming
Solution: fast feedback from the code
Tool: TDD – Test Driven Development – by writing all code test first, you end up with all the production code backed up by a series of regression tests. When you want to change something by running the regression suite of automated suite of tests, you can find out very fast whether you’ve broken something that was already implemented. This is the feedback from the code itself


Test Driven Development


TDD explained:

1. Write a test (specification for what the code must do – TDD design method)
2. Make it fail
3. Write the code to make it work
4. Refactor (improve the code)
5. Go to step 1


Benefits of TDD:
- fast feedback from code as the project increases, people can move ahead faster – projects cost less. When a system grows, the biggest problem is whether when someone fixes a bug,
-debugging takes less, reducing costs. With TDD the number of bugs decreases, and also when bugs are fixed, they can be fixed faster (by making sure new ones are not introduced)
-tests as documentation of what the code actually does


TDD vs. code and fix

“To obtain good code, writing tests and code is faster then code alone” – Ron Jeffries, 2006

We tend to think adding automated tests the development time increases. Test+code time> code time. 1h+4h>4h
This thinking presumes that the code done in the 4 hours of development is bug free. That is bug free and will stay like that even if the system around it changes, gets bigger etc. Usually is not so 1h+4h>4h+x?

Sample
1 programmer paid 10£/week, needs to implement 1 feature estimated to 10 days
TDD: tests (15-25%) 2.5+10=12.5 days  25£
Code and fix: 10+5 debugging time =15  30£

Writing tests firsts focuses development, so many unneeded code is avoided so the additional 15-25% actually doesn’t exist


Not enough time, projects late - actually too much to do

Cause: In many cases, the problem with not enough time, is actually that one person has too many things to do in a limited amount of time.
Solution: eliminate waste and cutting overhead
By eliminating non crucial work, work that does not add immediate value to the customer, the people involved in a project will have more time, they will be able to be creative, focus on quality and deliver products at the customer on time.

What is waste in software development?
Taiichi Ohno’s (the father of Toyota Production System) said that anything that does not add value to a product, as perceived by the customer, is waste. Agile methodologies have emerged as a response to the chaos resulting from inappropriately used resources which waste time and energy.

Waste activities (from Lean Software Development-Mary, Tom Poppendieck)
partially done work
extra processes
extra features
switching tasks among workers (requiring additional learning curves)
waiting
motion and defects
Management activities
Not using the most productive tools

Waste activities (from Lean Software Development-Mary, Tom Poppendieck)

Partially done work
Code, documents, activities that get done partially and are not carried out until their end, only waste important resources without adding any value for the client

Extra processes
“Do you ever ask, Is all that paperwork really necessary? Paperwork consumes resources. Paperwork slows down response time. Paperwork hides quality problems. Paperwork gets lost. Paperwork degrades and becomes obsolete. Paperwork that no one cares to read adds no value.
Many software development processes require paperwork for customer sign-off, or to provide traceability, or to get approval for a change. Does your customer really find this makes the product more valuable to them? Just because paperwork is a required deliverable does not mean that it adds value. If you must produce paperwork that adds little customer value, there are three rules to remember: Keep it short. Keep it high level. Do it off line. “ – Lean Software Development


Waste activities (from Lean Software Development-Mary, Tom Poppendieck)

Extra features
66% of the features of a system are never or rarely used. Many customers spend fortunes on features never used. This is the most efficient method to cut costs.

Switching tasks
A developer moved from one project to another needs time to adjust to the new project: the learning curve. In many cases the times are either bigger then it takes t actually fix the bug or do the new feature, and in most cases because of lack of knowledge on the project he breaks something existing. When moved back to the project he will need time again to readjust to the system he was working on. This is the biggest problem we are facing.The fastest way to complete two projects that use the same resources is to do them one at a time. – Lean Software Development

Waiting
Using a traditional sequential development process, means that teams wait on each other. The delays are propagated and amplified though the whole project. Working as much as possible in parallel, is much more efficient. Sequential development pairs very well with switching tasks amplifying the problems.


Value stream mapping chart (wait time vs work time)


Value stream maps often show that non-development activities are the biggest bottlenecks in a software development value stream.

In 1970 Winston Royce (inventor of the waterfall model)"[While] many additional development steps are required, none contribute as directly to the final product as analysis and coding, and all drive up the development costs."

Communication problems

Three categories:
-customer representatives
-management
-developers

Problems:
Information too late, travelling too much
Too less or too much information (quantity vs. quality)

The specification document needs to much time to be built, and is over-complete in most cases (if the doc is big, the customer will read it later, adding to the amount of time unused)
It is hard to change and track changes in it
It is hard to actually see if the customer will accept it or not

Solution: replace documents with prioritized lists, details with acceptance tests
Send the list of items faster to the developers, and let them ask for more details – pull systems working in parallel

Reflective Improvement

CRUCIAL: Team looks back every iteration, and improves their process

Monday, June 19, 2006

To obtain good code, writing tests and code is faster then code alone

A few weeks ago on the TestDrivenDevelopment mailing list, Ron Jeffies, one of the XP gurus stated that "in order to obtain good code, writing tests and code is faster then just code". To find out if this is true or not let's make a small experiment.


The mini TDD experiment

We assume that we are programmers and we need to code a function that divides two positive numbers. For this experiment we will compare the traditional and the TDD approaches.

Approach #1. Code and fix

As programmers, for a simple division we will write the following “pseudo” code:

Function Divide(No1, No2)

Return No1/No2


For this very simple method, let’s assume we needed 5 seconds to write it. Now let’s test if it works. First we try 6 and 2, expecting 3. It works. Let’s try another combination: 1 and 2, expecting 0.5. It works. Now let’s try 8 and 0. An error just occurred. This means we need to modify the program to display a message to the user that the second number cannot be 0:

Function Divide(No1,No2)

If No2 = 0 then display message “Division by 0 cannot be performed”

Else Return No1/No2


Now let’s test our function again. 6 and 2, result 3, good, 1 and 2, 0.5 as expected, 8 and 0 and a message “Division by 0 cannot be performed” occurs as expected. Now, our program works fine.

Assuming that manual testing is slow and for each combination of numbers we need about 10 seconds, this means that a testing session takes 30 seconds. The total time in which we developed the code was: 5 seconds to write the function, 30 seconds to test and see it has problems with division by 0, then about another 5 to correct the function and 30 minutes to test it again and make sure it works: total 5+30+5+30=70 seconds, a minute and 10 seconds.


Approach #2: Test Driven development

In test driven development, there are a series of steps to write a piece of code, starting with and automated test written first and ending up making that test succeed, by writing the code that it tests. Let’s see how it goes:

Function TestNormalDivision()

Expect 3 as a result of Divide(6,2)


The code above compares the value expected and the value returned by our (yet unwritten code) and if they do not match it fails.

One very important step now is to make sure our test really tests something and it does not work every time, no matter what the code under test does. So for this we need to make sure that when it needs to fail, it fails. So we write the following function:

Function Divide(No1, No2)

Return 0


Now we run the test, and it fails saying: expected 3 but the result was 0. So now we modify the function to return pass the test.

Function Divide(No1, No2)

Return 3


Now we run the test again: 1 test succeeded. Excellent. Now let’s see if it works for 1 and 2, so we update the test:

Function TestNormalDivision()

Expect 3 as a result of Divide(6,2)

Expect 0.5 as a result of Divide(1,2)


We run the test. Failure. Oooh, we just realize the mistake we made (code always returns 3) and modify the Divide function:

Function Divide(No1, No2)

Return No1/No2


Running the test, now passes all our expectations. But now we think, what would happen if we used 8 and 0. Let’s add a new test to the test suite (now we have two) and make sure that if there is division by 0, the user is notified:

Function TestDivisionByZero()

Expect message “Division by 0 cannot be performed” displayed as a result of Divide(8,0)


We run the test. It fails. Now we modify our function to make it work:

Function Divide(No1,No2)

If No2 = 0 then display message “Division by 0 cannot be performed”

Else Return No1/No2


Running all our tests, we discover that they all succeed.

How much time did we need to write this code? We needed 5 seconds to write the first test, 5 seconds to make sure it fails, 1 second to run the test (now testing is done by the computer so we assume it should be at least 10 times faster then manual testing), 5 seconds to modify the code to make the test work, 1 second to run the test, another 5 seconds to extend the test to verify the 1,2 combination, 1 second to see that the test fails, 5 seconds to modify the function and 1 second to see it working, another 5 seconds to write the second test and 2 seconds to see the first test work but the second failing, and 5 seconds to complete the code and another two to run the 2 tests and make sure it works. Wow, a long way: 5+5+1+5+1+5+1+5+1+5+2+5+2 = 42 seconds.

Using both approaches, we ended up with the same code. The amount of code written for the second approach is bigger then for the first, having the code and the tests. The amount of time needed for the second approach was arguably smaller then the amount for the first approach, which leads us to Ron Jeffries’s conclusion: to obtain good code, writing tests and code is faster then code alone. The main advantage is that we use computer power to do the testing rather then human power, so we are much faster. Then we can run the automated tests over and over again and it will take 2 seconds to see if they work, manually it will take 30 to do the same thing.

Let’s go further with our experiment, assuming that now we need to extend the program to be able also to do addictions, subtractions and multiplications.

Approach #1. Code&Fix

Since all these operation are not affected by 0, but we test that anyway, the code written first will work, so it would take about 5 seconds to write each method, and testing each with 3 combinations of numbers would result in about 30 seconds to test each. The amount of time, needed would be 5+30+5+30+5+30 = 105 seconds, 1 minute and 45 seconds. Testing the whole program (the 3 new methods and the division method) would take us 4*30 = 120 seconds, which is 2 minutes.

Approach #2. TDD

Operations just as above will need only one test, checking 3 combinations. Let’s say it takes 10 seconds to write a test method like this:

Function TestMultiplication()

Expect 0 as a result of Multiply(6,0)

Expect 3 as a result of Multiply(3,1)

Expect -9 as a result of Multiply(3,-3)


Then we’d have to make sure it fails: 5 seconds, 1 second to run the test, then we’d write the code to make it work: 5 seconds and 1 second to make sure it works, so it takes about 10+5+1+5+1 = 22 seconds for each new function, resulting in 3*22 = 66 seconds or 1 minute and 6 seconds to write the new functions. Testing all the code would mean running 5 test methods (2 for division and 1 for the other three), which would be run in 5 seconds.

Tests and code, faster then just code

Comparing the times needed to test our incredibly simple system: 2 minutes vs. 5 seconds show us that not only the code is written faster (110+105=215 seconds vs 66+45=111 seconds), but making sure it works requires far less time for the TDD approach. And second big advantage, it can be done by a computer.

Using a continuous integration machine that downloads the program sources and runs the test suite, then sends us an email telling us what happened, means 5 seconds for the machine and 0 seconds on my side to test the whole system. Using the first approach, would take me 2 minutes to make sure the whole system works. I could delegate this responsibility of testing the whole system to the testing team, but the feedback times, telling me whether the system works as a whole or not, increase rapidly to days and weeks and by that time I should be doing something else.

Scalability

In the 3rd phase of our little experiment, we analyze what would happen if our system would have 400 functions instead of 4. Using the first approach it would need about 12000 seconds (that is over 3 hours) for a full test, while using the TDD and automated testing suite about 500 seconds or, better said, less then 10 minutes. This simple sample shows us scalability when it comes to TDD vs traditional coding approaches. The testing team could work, to some extent in parallel, but after, all I could set my integration machine to divide the tests and work in parallel.

After making this very small experiment, we showed how test driven development is, compared with just coding:

o faster to develop
o faster to test the whole system and give feedback
o scalable




Tests as documentation

Another advantage of the method described above is that, the automated tests can act as a very good documentation of the code written. In traditional approaches, just documenting things that can be very easily deduced from the automated tests, like how a function works, would increase even more the development time. After all, just reading:

Function TestDivisionByZero()

Expect message “Division by 0 cannot be performed” displayed as a result of Divide(8,0)


tells me or someone new in the project, that if you try to perform a division by 0, the system will display an error message on the screen.

Embrace change: how?

Having a system with 4, 400, 1000…100.000 methods, doesn’t really comfort me when it comes to making a change in it. If I change one tiny piece of code somewhere, could I break something in another part of the system? And if I do, how could I know fast enough, to be able to either correct it or reverse my changes?

To have the feedback from the code, telling me if and where I’ve broken some existing functionality, I would normally need to retest the whole system. For a 4 methods system, it would take 2 minutes, but for a more likely system, it might take hours, days or even weeks. So the courage to change decreases with the system getting bigger, thus is shortening the life of the system. When a system is too rigid and can no longer adapt to the changes on the market, it is bound to die.

Having a full regression automated test suite, that runs very fast and can be run very often, means fast feedback. Fast feedback means changes are less risky and can be done easier and faster, thus extending the life of a system.

Design advantages

Another advantage of writing automated tests for the code is that the code written tends to be very loosely coupled, thus better designed. Test driven development also tends to eliminate “partially completed code”, encouraging less code to be written, as the programmer is more focused on what is really needed, thus decreasing the amount of code and its complexity.

At a macro level, the fact that changes, even in the architecture are much easier to be performed, when using TDD combined with aggressive refactoring, allows the programmers to continuously upgrade the design and update the architecture. Since the changes are easy to do, the evolutionary design technique is encouraged, having a much smaller need to build a flexible architecture upfront, following the YAGNI principle from XP.

Saturday, May 20, 2006

Refactoring a legacy web application with Selenium

About two months ago, one of our clients decided, to change the way one java web application that we built for them a few years ago worked. The application is built to gather and process different kinds of measurements in a medical sector, building different charts and analysis reports on these measurements.

The requirements

When the application was first built, it was decided that each client (hospital etc) will have their own instance of the application installed at their location. That meant for instance that when a report is run, it is done on all the data from the database.

Now the client, after a market research decided that it was to hard to deploy and maintain a vast amount of applications in different locations, so they asked me if we could change the way the aplication working, so they could host the application, the application can have one database, but multiple clients can log into it and work. This would mean that the data in the database should be divided for each of their clients so they can only see their own data and now the other's.

The solution was to have a master table, I called it entities, which would now have a foreign key in all measurement tables. Although altering the database wasn't such a problem, I had to maintain the existing functionality as it was, and because of the domain there were some difficulties, especially because some complicated phisical methods of calculations were used troughout the software.

How can I change but keep existing functionality exactly the same?

If the application needs to stay the same, I had the idea of recording some testing scenarios using the great open source Selenium[1] and the Mozilla Firefox extention, called Selenium IDE [2], trough the web interface that worked for the legacy version, that would need to work with the new version also.

But if I record a database test, and want it to work after I change the internals of the project, this means that I need to have the same data into the database, when the test is rerun. For this first I created a servlet which I called CreateTestDatabaseServlet who's mission was to reset the entire data from a database to a known state. Based on that state I could record my tests, because I knew what should appear on the user interface. For instance, my servlet, cleared all FilmType rows from the database and added Film Type A, Film Type B and Film Type C. Now when going into the web application, I knew for sure that the combo on a screen , where I can choose a FilmType has the 3 values all the time:

The code of the servlet is like:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException{

this.session = HibernateUtil.getSession();
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("");
out.println("

The servlet has received a " + request.getMethod() +
". This is the reply.

");
out.println("

"+this.createTestDatabase()+"

");


try
{
out.println("

" + this.insertTestData() + "

");
}
catch(Exception Ex)
{
Ex.printStackTrace();
}
finally
{
try {
this.session.close();
} catch (HibernateException ex) {
ex.printStackTrace();
}
this.session = null;
}
out.println("");
out.println("");
out.close();
}

where:

private String createTestDatabase() {
new AECBO(this.session).deleteAll();
new TubeRoomBO(session).deleteAll();
new UserBO(session).deleteAll();
new EntityBO(session).deleteAll();
new SUMBO(session).deleteAll();

...

return "";
}

and

private String insertTestData() {

...

createFilmType("Film Type A");
createFilmType("Film Type B");
createFilmType("Film Type C");

...

createProjection("Left Crano-Caudal");
createProjection("Right Crano-Caudal");

....

createUnit("FFD","centimeters (cm)",1);
createUnit("TRC","centimeters (cm)",1);
createUnit("FSD","meters (m)",1);
createUnit("BT","centimeters (cm)",1);
createUnit("CIO","micro-Grays (µGy)",1);

...
}

Now when a Selenium test is run, the first thing it does it reset the database to the known state, then login (I already know I have a user created by the servlet, that has a/a as credentials) and do what is necessary:

|open|/app/CreateTestDatabaseServlet|
|open|/app/login/login.faces?random=734574375|
|type|loginForm:userName|a|
|type|loginForm:password |a|
|clickAndWait|link=Login|
|clickAndWait|link=Image Quality|
|type|_id1:main:dateinput||


With the method to reset the database in place, using Selenium IDE [2] I started recording tests for all parts of the application, following different scenarios, which I then saved and created a suite of selenium tests, and after I made sure all of them work, I started dissecting the code.



Then I took a test, refactored the code and database until I made that selenium test work. Then I took the next test, until it and the one before it worked. I looked if I could make some refectorings, I did them ensuring nothing is broken and moved to the next test, until one month later all tests were working.

Although it doesn't seem like very much, the selenium regression tests helped me a great deal, telling me in 7 minutes if the existing functionality of the application (which took more then a year to develop because there are some very complicated phisics formulas in it) is working exactly as it did before, but with the extentions added. One of the big refactorings I did also was to remove the built in data access layer and business objects, and replace everything with Hibernate [3].

So it proved that my plan of action
1. Reset state of the database
2. Record the tests
3. Refactor - test until the recorded tests works again

worked very well and very fast.

Conclusion

Without Selenium, Selenium IDE and Hibernate, the entire operation could have taken a lot more then a month, because of the constant fear that the existing functionality will be broken and would need tobe rebuilt, after more then a year was already invested in the project.

[1] Selenium - www.openqa.org/selenium
[2] Selenium IDE - www.openqa.org
[3] Hibernate - www.hibernate.org

Saturday, April 08, 2006

Agile adaptive planning and fast delivery sample

After seeing that there are very many people that find it hard to see how agile handles adaptive planning, letting the customer not know from the beginning what he wants, I wanted to develop a mini sample to show these concepts in practice.

A small agile process practice sample

Let’s consider that we have a new client who wants a new software product to manage and track his sales and customers. He wants the system to go live in 2 months. We meet and establish what is required, then plan to meet the deadline.

After the first meetings we come up with the following feature list, that he thinks he wants, that is afterwards estimated by us:

  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)

  4. Sales reports (3p)

  5. Client activity management (3p)

  6. User management (2p)

  7. Sales workflow (3p)

Now together with the customer, we make the first plan, dividing the work in two iterations:

Iteration #1: 10 p
  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)
Iteration #2: 11p
  1. Sales reports (3p)

  2. Client activity management (3p)

  3. User management (2p)

  4. Sales workflow (3p)

After we have a plan to deliver the 21 points features in 2 months, we start working, by starting on the first iteration, at the end of which we deliver features 1,2 and 3.

We now show the customer the first 3 features implemented, but he suddenly realizes that he needs more, then what was planned for the release. We start by adding what he wants to the list of features, which now becomes, after each of the new features are being estimated.

  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)

  4. Sales reports (3p)

  5. Client activity management (3p)

  6. User management (2p)

  7. Sales workflow (3p)

  8. Activity calendar (3p)

  9. Forecast reports (3p)

  10. Document templates and document merging (3p)

With the client we realize we cannot deliver all in the 2 months term, but we decide that we make a delivery after the two months and we plan another delivery after that will include other features that will make the system more compete. The new plan looks like:

Release #1: 2 months
Iteration #1: 10p
  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)
Iteration #2: 11p
  1. Sales reports (3p)

  2. Client activity management (3p)

  3. User management (2p)

  4. Forecast reports (3p)
Release #2
Iteration #3: 9p
  1. Sales workflow (3p)

  2. Activity calendar (3p)

  3. Document templates and document merging (3p)

As you can see, the customer considered that is more important to have the forecast reports in the first delivery so he moved the forecast report into the second iteration and the sales workflow to the 3rd iteration.

After the second iteration is over, we have the features 1-7 finished, in 2 1 month iterations, delivering on term what the customer wanted, and deploying it to be used by its end users.

At the beginning of the 3rd iteration, the customer realizes that he wants a few more things, and he would like to have the next delivery of the complete system, in another two months so he can fit his budget. He adds a few new features, having the following list now:

  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)

  4. Sales reports (3p)

  5. Client activity management (3p)

  6. User management (2p)

  7. Sales workflow (3p)

  8. Activity calendar (3p)

  9. Forecast reports (3p)

  10. Document templates and document merging (3p)

  11. Contact communication management (3p)

  12. Microsoft Outlook integration (2p)


The plan now becomes:

Release #1: 2 months
Iteration #1: 10p
  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)
Iteration #2: 11p
  1. Sales reports (3p)

  2. Client activity management (3p)

  3. User management (2p)

  4. Forecast reports (3p)
Release #2
Iteration #3: 9p
  1. Sales workflow (3p)

  2. Activity calendar (3p)

  3. Document templates and document merging (3p)
Iteration #4: 5p
  1. Contact communication management (3p)

  2. Microsoft outlook integration (2p)

After finishing and showing to the client the resulting product having now 10 features out of 12 implemented, he realizes that there is one more feature he’d like to have, and that can be implemented in the last iteration: sales processes. The list of feature becomes:

  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)

  4. Sales reports (3p)

  5. Client activity management (3p)

  6. User management (2p)

  7. Sales workflow (3p)

  8. Activity calendar (3p)

  9. Forecast reports (3p)

  10. Document templates and document merging (3p)

  11. Contact communication management (3p)

  12. Microsoft Outlook integration (2p)

  13. Sales Processes (5p)

And the updated plan:

Release #1: 2 months
Iteration #1: 10 p
  1. Client management (3p)

  2. Product management (3p)

  3. Sales leads management (4p)
Iteration #2: 11p
  1. Sales reports (3p)

  2. Client activity management (3p)

  3. User management (2p)

  4. Forecast reports (3p)
Release #2
Iteration #3 – 9p
  1. Sales workflow (3p)

  2. Activity calendar (3p)

  3. Document templates and document merging (3p)
Iteration #4 – 10p
  1. Contact communication management (3p)

  2. Microsoft outlook integration (2p)

  3. Sales processes (5p)

At the beginning of the 4th iteration the client says he’d like one more feature that is estimated by the team to be of 3 points. Adding that feature would mean not meeting the second release target, so after balancing the options he decides to drop it.

After the 4th iteration the final product is delivered. The sample above cannot show by any means how any project can be developed, but it shows the agile process at work, iteration by iteration, planning, adapting and delivering incrementally a product to the end customer.

The evolutive process of gathering the client requirements and a burn down chart, showing iteration by iteration the number of remaining features to be implemented would be like:



So after this very small sample do you think it could be useful for you?

Monday, December 19, 2005

TDDing the sales report

Download: Sources

You're starting a new project. You are talking with the customer, defining a few user stories, to make a release plan, when he says the most important thing for him would be a weekly sales report. Your immediate reaction is to say: you can't have the sales report before, you actually can put data into the system, the data entry forms should be developed first. Then he says, no, I need that first, and the data needs to come from our old system, and I will get one of my IT employees to write a data transformation code that transfers the data into your system, so that I can have the report after the first iteration.

Ok, then...so lets do that first. After a few more discussions, you and the customer write down a few acceptance tests for the sales reports as:

I have, 3 orders from 2 customers (one makes two orders as in the first forgets something).

|| order id || product || qty || unit price || customer || order total ||
|| order #123 || xxy mobile phone || 2 || 200 || company #1 limited || 400 ||
|| order #123 || xxy mobile charger || 2 || 15 || company #1 limited || 430 ||
|| order #124 || xxy mobile charger || 1 || 15 || company #1 limited || 15 ||
|| order #125 || bluetooth adapter || 1 || 20 || company #2 limited || 20 ||
|| order #125 || xxy mobile charger || 3 || 15 || company #2 limited || 65 ||

so, seeing my sales report, I would like to see how much has been sold of each product I have (sorted by product):

|| product name || qty || total ||
|| bluetooth adapter || 1 || 20 ||
|| product #no name || 0 || 0 ||
|| xxy mobile charger || 6 || 90 ||
|| xxy mobile phone || 2 || 400 ||

If I also want to include the customer I would get:

|| product name || qty || total || customer ||
|| bluetooth adapter || 1 || 20 || company #2 limited ||
|| product #no name || 0 || 0 || - ||
|| xxy mobile charger || 3 || 45 || company #1 limited ||
|| xxy mobile charger || 3 || 45 || company #2 limited ||
|| xxy mobile phone || 2 || 200 || company #1 limited ||

Ok, now let's make it work. TDD with a database. Testing with a database is not considered unit testing (Michael Feathers [1] ), but there are situations when this kind of tests could prove very good to have.

Over the years I discovered that there are three techniques that can be applied when testing code that interacts with a database:
  • mock testing

  • rollback changes technique

  • reset database technique.

The best technique is to avoid direct interaction with the database, by using mock objects. That can be a very good technique in many cases, as mock objects are very fast, and quite easy to use, but in this case using mock objects, might mean that out tests could cover very little of our actual functionality, so we can leave mock objects for a better situation.

Now if we really need to touch the database, and the automated tests need to be independent from one another, it is important that the state (data) of a database is the same before running each tests. For this there are two techniques: either you recreate the database in a specific state before each test is run, or any eventual changes made by a test when being run are rolled back after its execution. For the latter technique, you could use database or application transactions that can facilitate it. See Roy Osherove's: ....

The reset database technique, can be done in several ways, however speed in TDD is essential as the faster you get feedback from you tests the faster you learn what decisions to take next, so the most common technique is an in memory database, like HypersonicSQL or Cloudscape for Java, or SqlLite or Firebird for everyone. However this technique can be just as misleading as the mocking of the database in some cases, as database engines are different, and you could end up with your tests working but deployed on the real server the code to fail. In order to avoid this, you can write your tests directly against the database engine you will deploy, sacrificing speed for safety.

In order to recreate a database's state, you can clean/re-create the database and populate it from code (using an ORM/ DataSets etc) or using a sql script that does all this. The second approach might prove faster but, it is even less maintainable then the first so great caution must be imposed. However, there is a tool, that can really help us with this latter technique, who's usage in this context will be proven today.

Back to work

In TDD the first step is to write a test, make it fail then make it work (red/green factor - see: ....). Let's write the test:

[TestFixture]
public class TestSalesReport
{
SalesReportDAO dao = new SalesReportDAO();

[SetUp]
public void ResetDatabase()
{
}

[Test]
public void TestProductsAndQtySold()
{
DataSet reportDataSet = dao.GetSalesReport();
DataTable report = reportDataSet.Tables[0];

Assert.AreEqual(4, report.Rows.Count, "we should have 4 rows");
}
}
As you can see we will need to add the code to the test that resets the database state. Now let's create the database and put data the test data into it, then using the amazing Tychotic Database Scripter [2] we will export the whole database state as a stored procedure that can be run in our test's setup.



and put the values in the acceptance test into it (OrderLines table):



Now let's export the script with the database scripter and create the stored procedure. The stored procedure's code is:


if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SETUP]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SETUP]
GO

CREATE PROCEDURE [dbo].[SETUP]
AS

BEGIN

-- DELETES
DELETE FROM [dbo].[OrderLines];
DELETE FROM [dbo].[Orders];
DELETE FROM [dbo].[Customers];
DELETE FROM [dbo].[Products];

-- Products
SET IDENTITY_INSERT [dbo].[Products] ON;
INSERT INTO [dbo].[Products]
(
ID
,Name
,Price
)
SELECT 1,'xxy mobile phone',200.0000 UNION
SELECT 2,'xxy mobile charger',15.0000 UNION
SELECT 3,'bluetooth adapter ',20.0000 UNION
SELECT 4,'product #no name ',50.0000
SET IDENTITY_INSERT [dbo].[Products] OFF;

-- Customers
SET IDENTITY_INSERT [dbo].[Customers] ON;
INSERT INTO [dbo].[Customers]
(
ID
,Name
,Address
)
SELECT 1,'company #1 limited',NULL UNION
SELECT 2,'company #2 limited',NULL
SET IDENTITY_INSERT [dbo].[Customers] OFF;

-- Orders
SET IDENTITY_INSERT [dbo].[Orders] ON;
INSERT INTO [dbo].[Orders]
(
ID
,CustomerID
,OrderNo
,Total
)
SELECT 1,1,'order #123',430.0000 UNION
SELECT 2,1,'order #124',15.0000 UNION
SELECT 3,2,'order #125',65.0000
SET IDENTITY_INSERT [dbo].[Orders] OFF;

-- OrderLines
SET IDENTITY_INSERT [dbo].[OrderLines] ON;
INSERT INTO [dbo].[OrderLines]
(
ID
,OrderID
,ProductID
,UnitPrice
,Quantity
,Total
)
SELECT 1,1,1,200.0000,2,400.0000 UNION
SELECT 2,1,2,15.0000,2,30.0000 UNION
SELECT 3,2,2,15.0000,1,15.0000 UNION
SELECT 4,3,3,20.0000,1,20.0000 UNION
SELECT 5,3,2,15.0000,3,45.0000
SET IDENTITY_INSERT [dbo].[OrderLines] OFF;

END;
GO

As you can see the scripter preserves the original primary key values in the database, thus making testing easier. If you run it manually you will notice that it is very fast. Now it is time to add the code to our test that runs this stored procedure and resets the database state.

[TestFixture]
public class TestSalesReport
{
SalesReportDAO dao = new SalesReportDAO();


[SetUp]
public void ResetDatabase()
{
//we run the clean and populate with data, stored procedure
using (SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["connection_string"]))
{
SqlCommand command = new SqlCommand("SETUP", conn);
command.CommandType = CommandType.StoredProcedure;

conn.Open();
command.ExecuteNonQuery();
}
}


[Test]
public void TestProductsAndQtySold()
{
DataSet reportDataSet = dao.GetSalesReport();
DataTable report = reportDataSet.Tables[0];

Assert.AreEqual(4, report.Rows.Count, "we should have 4 rows");
Assert.AreEqual("bluetooth adapter", report.Rows[0]["product_name"].ToString().Trim(), "the first product should be a bluetooth adapter");
Assert.AreEqual(DBNull.Value, report.Rows[1]["qty"], "no product #no name has been sold");
Assert.AreEqual("90.0000", report.Rows[2]["total"].ToString(), "6 xxy mobile charger sold results in 90");
}
}

To make it compile we need:

public class SalesReportDAO
{
public DataSet GetSalesReport()
{
return null;
}
}

Now we need to see if our code fails as it should since the data is not extracted from the database at this time:

------ Test started: Assembly: TDDSalesReport.dll ------

TestCase 'TDDSalesReport.Tests.TestSalesReport.TestProductsAndQtySold' failed: System.NullReferenceException : Object reference not set to an instance of an object.
D:\Projects\Dan Bunea\TDDSalesReport\TDDSalesReport\TDDSalesReport\Tests\TestSalesReport.cs(37,0): at TDDSalesReport.Tests.TestSalesReport.TestProductsAndQtySold()


0 succeeded, 1 failed, 0 skipped, took 1.02 seconds.



---------------------- Done ----------------------

Running the code will make it fail, but if we alter the database's state then rerun the test we notice that it is in the previous state, so our stored procedure works. Now all we need to do is write the code to pass the test:

public class SalesReportDAO
{
public DataSet GetSalesReport()
{
DataSet results = new DataSet();
results.Tables.Add("SalesReport");
using (SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["connection_string"]))
{
SqlDataAdapter adapter = new SqlDataAdapter(GetCommandByProduct(), conn);
adapter.Fill(results.Tables[0]);
}
return results;
}

private string GetCommandByProduct()
{
StringBuilder builder = new StringBuilder();
builder.Append("select ");
builder.Append(" Products.Name as product_name,");
builder.Append(" Sum(OrderLines.Quantity) as qty,");
builder.Append(" Sum(OrderLines.Total) as total ");
builder.Append("from Products ");
builder.Append("left outer join OrderLines ");
builder.Append(" on Products.Id = OrderLines.ProductID ");
builder.Append("group by Products.Name");
return builder.ToString();
}
}

And running it:

------ Test started: Assembly: TDDSalesReport.dll ------


1 succeeded, 0 failed, 0 skipped, took 1.19 seconds.



---------------------- Done ----------------------

Excellent, we have written a report that is accompanied by an automated test that is independent and fast enough (unfortunately my computer is rather degenerated, but on a more powerful computer the times might be decreased dramatically).

Now we could improve o by adding a few more asserts but in my opinion asserts should be handled with care, as if their number increases, they become harder to maintain so there should always be a balance between the number of asserts and the coverage a test should do, as I tried to show above.

For the second test, exactly the same approach will be used, writing the test, making it compile, making it fail, and then developing the code to make it work as in any TDD scenario. So we start with this test:

[TestFixture]
public class TestSalesReport
{
SalesReportDAO dao = new SalesReportDAO();


[SetUp]
public void ResetDatabase()
{
//we run the clean and populate with data stored procedure
using (SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["connection_string"]))
{
SqlCommand command = new SqlCommand("SETUP", conn);
command.CommandType = CommandType.StoredProcedure;

conn.Open();
command.ExecuteNonQuery();
}
}


[Test]
public void TestProductsAndQtySold()
{
DataSet reportDataSet = dao.GetSalesReportByProduct();
DataTable report = reportDataSet.Tables[0];

Assert.AreEqual(4, report.Rows.Count, "we should have 4 rows");
Assert.AreEqual("bluetooth adapter", report.Rows[0]["product_name"].ToString().Trim(), "the first product should be a bluetooth adapter");
Assert.AreEqual(DBNull.Value, report.Rows[1]["qty"], "no product #no name has been sold");
Assert.AreEqual("90.0000", report.Rows[2]["total"].ToString(), "6 xxy mobile charger sold results in 90");
}

[Test]
public void TestProductsQtySoldAndCustomer()
{
DataSet reportDataSet = dao.GetSalesReportByProductAndCustomer();
DataTable report = reportDataSet.Tables[0];

Assert.AreEqual(5, report.Rows.Count, "we should have 5 rows");
Assert.AreEqual("bluetooth adapter", report.Rows[0]["product_name"].ToString().Trim(), "the first product should be a bluetooth adapter");
Assert.AreEqual(DBNull.Value, report.Rows[1]["qty"], "no product #no name has been sold");
Assert.AreEqual("45.0000", report.Rows[2]["total"].ToString(), "3 xxy mobile charger sold to company #1 limited results in 45");
Assert.AreEqual("company #2 limited", report.Rows[3]["customer"].ToString().Trim(), "company #2 limited bought these");
}
}

Doing a small refactoring to the names of the methods that extract the report data from the database. Of course it doesn’t compile, but we fix that:

public class SalesReportDAO
{
public DataSet GetSalesReportByProduct()
{
DataSet results = new DataSet();
results.Tables.Add("SalesReport");
using (SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["connection_string"]))
{
SqlDataAdapter adapter = new SqlDataAdapter(GetCommandByProduct(), conn);
adapter.Fill(results.Tables[0]);
}
return results;
}

public DataSet GetSalesReportByProductAndCustomer()
{
throw new Exception("The method or operation is not implemented.");
}

private string GetCommandByProduct()
{
StringBuilder builder = new StringBuilder();
builder.Append("select ");
builder.Append(" Products.Name as product_name,");
builder.Append(" Sum(OrderLines.Quantity) as qty,");
builder.Append(" Sum(OrderLines.Total) as total ");
builder.Append("from Products ");
builder.Append("left outer join OrderLines ");
builder.Append(" on Products.Id = OrderLines.ProductID ");
builder.Append("group by Products.Name");
return builder.ToString();
}

}

then we start by running all the tests and making sure the second test fails:

------ Test started: Assembly: TDDSalesReport.dll ------

TestCase 'TDDSalesReport.Tests.TestSalesReport.TestProductsQtySoldAndCustomer' failed: System.Exception : The method or operation is not implemented.
D:\Projects\Dan Bunea\TDDSalesReport\TDDSalesReport\TDDSalesReport\DataLayer\SalesReportDAO.cs(26,0): at TDDSalesReport.DataLayer.SalesReportDAO.GetSalesReportByProductAndCustomer()
D:\Projects\Dan Bunea\TDDSalesReport\TDDSalesReport\TDDSalesReport\Tests\TestSalesReport.cs(48,0): at TDDSalesReport.Tests.TestSalesReport.TestProductsQtySoldAndCustomer()


1 succeeded, 1 failed, 0 skipped, took 1.85 seconds.



---------------------- Done ----------------------

Now let’s write the proper code to make it run:

public class SalesReportDAO
{
public DataSet GetSalesReportByProduct()
{
return GetReportResults(GetCommandByProduct());
}



public DataSet GetSalesReportByProductAndCustomer()
{
return GetReportResults(GetCommandByProductAndCustomer());
}

private DataSet GetReportResults(string sql)
{
DataSet results = new DataSet();
results.Tables.Add("SalesReport");
using (SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["connection_string"]))
{
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
adapter.Fill(results.Tables[0]);
}
return results;
}

private string GetCommandByProduct()
{
StringBuilder builder = new StringBuilder();
builder.Append("select ");
builder.Append(" Products.Name as product_name,");
builder.Append(" Sum(OrderLines.Quantity) as qty,");
builder.Append(" Sum(OrderLines.Total) as total ");
builder.Append("from Products ");
builder.Append("left outer join OrderLines ");
builder.Append(" on Products.Id = OrderLines.ProductID ");
builder.Append("group by Products.Name");
return builder.ToString();
}


private string GetCommandByProductAndCustomer()
{
StringBuilder builder = new StringBuilder();
builder.Append("select ");
builder.Append(" Products.Name as product_name, ");
builder.Append(" Sum(OrderLines.Quantity) as qty, ");
builder.Append(" Sum(OrderLines.Total) as total, ");
builder.Append(" Customers.Name as customer ");
builder.Append("from Products ");
builder.Append("left outer join OrderLines ");
builder.Append(" on Products.Id = OrderLines.ProductID ");
builder.Append("left outer join Orders ");
builder.Append(" on Orders.Id = OrderLines.OrderID ");
builder.Append("left outer join Customers ");
builder.Append(" on Orders.CustomerId = Customers.Id ");
builder.Append("group by Products.Name,Customers.Name ");
builder.Append("order by Products.Name ");
return builder.ToString();
}

As you may see several refactorings have been made but let’s see what happens when we run it:

------ Test started: Assembly: TDDSalesReport.dll ------


2 succeeded, 0 failed, 0 skipped, took 1.32 seconds.



---------------------- Done ----------------------


I guess, we can call our customer now (. Although it might not be the most optimized code, the code does what the customer wants, backed up by automated tests that prove it and if there is need for optimizations and refactorings it is always easier to do them protected by the automated tests then without.

Conclusion

By writing just a few lines of code and with the help of a brilliant tool we managed to TDD our sales report as requested by the client, fast and in a convenient way. However, there should be caution in using this technique, as the database script might become rapidly a test maintenance nightmare if the database structure changes, so having as few scripts like this as possible as well as combining this technique with other database testing techniques, will make this maintenance work easier.

[1] Michael Feathers – A Set of Unit Testing Rules http://www.artima.com/weblogs/viewpost.jsp?thread=126923
[2] Thycotic DatabaseScripter - http://www.thycotic.com/dotnet_dbscripter.html

Thursday, December 08, 2005

Test a little, code a little - a practical introduction to TDD

Introduction

Test Driven Development is one of the most well known practices in and outside agile communities. However, the level of understanding is in my opinion low as the term seems to be surrounded by lots of misunderstanding and misuse.

Biggest confusions regarding TDD

Many people that do not know too many things about agile practices, or beginners tend to think that test driven development, means having written automated test for your code or even worse that test driven development is a method to test the code, rather then develop it.

1. Test Driven Development is for testers

A lot of confusion comes from the name: Test Driven Development, which to some developers means a method of writing automated tests for software, something that should be the QA team’s responsibility. Having the test word in the name tends to confuse a lot of developers, who presume as explain above that TDD should be ignored as it is a practice for the QA. This comes from a partial read of the title, imagining the rest. The title was intended to be quite clear: automated tests that drive the development of the code

2. I do TDD because I have automated tests that test my code

Beginners in agile practices, have the tendency to believe that having automated tests that cover parts of the whole code, means they are doing TDD. In fact it is right, only of those tests were developed before the code was developed and not after. If the test code did not influence the development of the code, then it is not TDD, it is just having automated tests, which is a good thing, anyway.Having automated tests can say that is partially TDD even if the tests were not developed before the code, at a high or better said project level, as the biggest purpose of the tests in a project as a whole is detecting when something is broken by a change a developer makes, which influences the decisions he makes later in the design and in the code he writes, thus driving the way the software is written.

Theory

Test Driven development is a software development technique, targeted for software developers, and not software testers, that uses automated tests that are written at first, to influence and drive the code that is being written. In the end the code passes the tests, which means that it has been driven towards passing a specific number of tests.

The technique has been widely described, so I will try to keep my introduction as simple as possible. The technique is also called red-green factor, test a little, code a little or test, fail, code , pass and consists from a list of steps that are followed in order to obtain the code we want.

So it is a coding technique, one a little bit different, as it presumes the following steps:

- Test: Write a small test (one, not more)
- Compile: Make the code compile, and make the test fail
- Fail: running the test will show it failing (red)
- Code: write the code, just enough to make the test pass, not more
- Pass: run the test , it should pass. If it doesn’t code a little more (step 4). If it passes, you get the red (red-green factor)
- Refactor: refactor the code written so far (both test and code)
- Pass again. If it doesn’t go to step 4.
- Repeat: Go to step 1 and do it again, until you have the desired code, passing all the tests it should pass.

This would be the simplified list of steps that need to be done in test driven development. In fact, the list is a little bit longer as the first step is always think: about what you need and then the second is to think about making a simple test, then following the 1-8 steps and going back sufficient times to make the code good. This is an iterative process that presumes making a test (test a little) and building the code that passes it (code a little), and repeating this step as much as needed.

Practice

Suppose we have a order processing system, requested by the customer and I am asked to write the part where the clients are given a discount if the order total is over a certain limit. In Extreme Programming, this would be a programming task of a user story .

At this time, I have absolutely no code written. First I think I should have an Order class and maybe also an OrderLine class. Let me write a test about that (step 1):

[TestFixture]
public class OrderTests
{
[Test]
public void EmptyOrder()
{
Order order = new Order();
Assert.AreEqual(0,order.Total);
}
}


I have no such class Order. So at step 2 I should make the code compile and them and at the same time make the test fail. So I write the following code:

public class Order
{
public decimal Total
{
get{throw new NotImplementedException();}
}
}

I can compile the code now, so I should see if the code fails:



It seems steps 1-3 were simple, let’s move on and add the code that passes the test. You might be surprised:

public class Order
{
public decimal Total
{
get{return 0;}
}
}

The fact that I intentionally wrote return 0, makes the code be bad but still pass the test. However this is very good way of understanding that the code needs to pass the tests, as they are influencing the development and that it is important not to write code I advance.And now let’s if it passes as it should (step 5):




Wow, now we have implemented a passing test, we should see if any refactoring is needed. So far I don’t see any so since the code still passes the test, I can consider the first cycle completed. Back to the first step, adding a new test, for a few order lines.

[TestFixture]
public class OrderTests
{
[Test]
public void EmptyOrder()
{
Order order = new Order();
Assert.AreEqual(0,order.Total);
}

[Test]
public void TwoOrderLinesTotal()
{
Order order = new Order();

OrderLine ol1 = new OrderLine();
ol1.Product = "Laptop";
ol1.Quantity = 1.0;
ol1.Price = 1000.0;

OrderLine ol2 = new OrderLine();
ol2.Product = "Monitor";
ol2.Quantity = 2.0;
ol2.Price = 200.0;

order.AddOrderLine(ol1);
order.AddOrderLine(ol2);

Assert.AreEqual(1400.0, order.Total);
}
}

Let’s make it compile and fail, by adding the OrderLine class and AddOrderLine method:

public class OrderLine
{
public string Product
{
get {throw new NotImplementedException();}
set { }
}
public decimal Quantity
{
get { throw new NotImplementedException(); }
set { }
}
public decimal Price
{
get { throw new NotImplementedException(); }
set { }
}
}

And:

public class Order
{
public decimal Total
{
get{return 0;}
}

public void AddOrderLine(OrderLine ol)
{
}
}

Let’s see if it fails (we run all the tests):



Now it is time to code to make the test pass.We add a little code, then if it compiles, run the tests. If it fails, then we need to code some more, and run again and so on until the code passes the tests. The code becomes:

public class Order
{
private IList orderLines = new ArrayList();

public decimal Total
{
get
{
decimal sum = (decimal)0;
foreach(OrderLine ol in this.orderLines)
{
sum += ol.Total;
}
return sum;
}
}

public void AddOrderLine(OrderLine ol)
{
this.orderLines.Add(ol);
}
}

And OrderLine:

public class OrderLine
{
private decimal quantity;
private decimal price;
private string product;

public string Product
{
get { return product; }
set { product = value; }
}
public decimal Quantity
{
get { return quantity; }
set { quantity = value; }
}
public decimal Price
{
get { return price; }
set { price = value; }
}

public decimal Total
{
get
{
return this.quantity * this.price;
}
}
}



Wow, this is the second time in the last 10 minutes, now let’s look for some refactoring possibilities. The code seems ok, but maybe we can do something about the test, as it seems the order initialization code is duplicated. We move it into the SetUp method, as it is run before every method is run, then the OrderLine initialization code could be moved to another method:

[TestFixture]
public class OrderTests
{
Order order = null;

[SetUp]
public void SetUp()
{
order = new Order();
}

[Test]
public void EmptyOrder()
{
Assert.AreEqual(0,order.Total);
}

[Test]
public void TwoOrderLinesTotal()
{
OrderLine ol1 = CreateOrderLine("Laptop",1,1000);
OrderLine ol2 = CreateOrderLine("Monitor", 2, 200);

order.AddOrderLine(ol1);
order.AddOrderLine(ol2);

Assert.AreEqual(1400.0, order.Total);
}

private OrderLine CreateOrderLine(string product, decimal quantity, decimal price)
{
OrderLine ol1 = new OrderLine();
ol1.Product = product;
ol1.Quantity = quantity;
ol1.Price = price;
return ol1;
}
}

Now see if it still passes:



It does, so we have just finished the second cycle, and we have an almost good code, pretty much tested if it works ok. Now let’s add the part with the discount, using another “test a little, code a little” cycle. First we add the test:

[TestFixture]
public class OrderTests
{
Order order = null;

[SetUp]
public void SetUp()
{
order = new Order();
}

[Test]
public void EmptyOrder()
{
Assert.AreEqual(0,order.Total);
}

[Test]
public void TwoOrderLinesTotal()
{
OrderLine ol1 = CreateOrderLine("Laptop",1,1000);
OrderLine ol2 = CreateOrderLine("Monitor", 2, 200);

order.AddOrderLine(ol1);
order.AddOrderLine(ol2);

Assert.AreEqual(1400.0, order.Total);
}

[Test]
public void Discount10PercentOver2000()
{
IRule discountRule = new DiscountRule(10, 2000);

OrderLine ol1 = CreateOrderLine("Laptop", 1, 1000);
OrderLine ol2 = CreateOrderLine("Monitor", 2, 200);
OrderLine ol3 = CreateOrderLine("MimiMac", 2, 500);

order.AddOrderLine(ol1);
order.AddOrderLine(ol2);

order.ApplyBusinessRule(discountRule);

Assert.AreEqual(2400.0, order.Total);
Assert.AreEqual(2160.0, order.TotalAfterDiscount);

}

private OrderLine CreateOrderLine(string product, decimal quantity, decimal price)
{
OrderLine ol1 = new OrderLine();
ol1.Product = product;
ol1.Quantity = quantity;
ol1.Price = price;
return ol1;
}
}


We ensure everything is compilable and then that the test fails, then we struggle to make it pass, fixing the code, then we realize something very ugly: the test should work but it doesn’t.





We have a bug in the test. Now we see that in the test we forgot to add the order line #3 at the order (totals 1400), so we add it, then rerun the test. It seems the relationship between tests and code makes the bugs easy to find in both parts of the code:



Well, it seems that we have a few simple tests that helped us build a piece of code. Now these tests helped us so far, and by adding them to a test suite on the project, and running them regularly, can really tell us when they have been broken and where.

Hopefully, the above lines will clear a little the "fog" around what TDD means and how it can be applied practically.

Sunday, November 27, 2005

Model View Presenter - is testing the presenter enough?

Source code: Download


Lately, I have noticed that the Humble Dialog Box or Model View Presenter are gaining more and more acceptance among software developers, especially in agile communities, because of its benefits regarding the very good separation between the view and the behavior and because it can be very easily unit tested, on a problematic field: user interface.

Let's meet Model View Presenter

In model view presenter just as Martin Fowler or Michael Feathers [2] say, the logic of the UI is separated into a class called presenter, that handles all the input from the user and that tells the "dumb" view what and when to display. The special testability of the pattern comes from the fact that the entire view can be replaced with a mock object and in this way the presenter, which is the most important part, can be easily unit tested in isolation. Let's take a small sample:

A client writes in a user story:

User management

The system will support managing users. Each user can have a username and a password. The system will present a list of user and when one is selected, it can be edited. Also there will be functionality to add new users and to be able to select a user from the list and delete it.


Ok, now let's get to work:

Our view should need the following data, which will be put into an interface:



The UsersList represents the list of users, and the User is the current user selected at a certain time.

When the UI is displayed, we want to be able to see the list of available users, and by default the first in the list to be selected. Let’s write a small test for that. Having no view, we will make a simple implementation of the IUsersView, called UsersMockView. Using it we will be able to see if the presenter when it is initialized sets the needed list and the first is selected in it.



where we have:



And for the data we use a separate model class, like:



If I want to make my test compile, I must write my presenter, see the test failing then keep working on it until the test is working:



and now it is time for a new test, and a small refactoring in the test code:




Now we can go further and add the missing code ... until it works. We then follow the same procedure unti