• free counters
  • links

  • « | Main | »

    Techniques for .NET Developers

    By admin | October 9, 2010

    What Do You Read ?

    When you are developing software, what do you want?

    This introduces you to a set of techniques designed to place you on the road to reach your goals.

    The practices examined throughout this book are taught mainly through hands-on exercises. I strongly believe in learning by doing, and, after all, this is about programming in an extreme way.


    Chapter 1. eXtreme Programming Overview
    If you have never before read anything about eXtreme Programming (XP), read this chapter. If you want know how XP can help you develop better code for the .NET Framework, read this chapter.

    This chapter does not provide a detailed, in-depth examination of XP. It provides just enough information about XP to get you started. Also clarified in this chapter is the importance of XP to .NET developers. This chapter discusses the business needs for XP techniques and how software development practices have changed to meet those needs. After all, XP has evolved in response to the changing business needs of software teams.

    Because the material within this chapter is introductory in nature, I direct you to other reference material for further reading.

    What Is eXtreme Programming?
    XP is a formalized set of software development methods that have been shown to work well together. A central theme of XP is the thought that the cost of change on a software project does not need to rise throughout the life cycle of a project. If the cost of change can be leveled off, the attitude toward the development process can be radically rethought.

    XP aims to embrace the ever-changing business needs when developing a software solution. XP is nonproprietary and doesn’t involve buying any special tools. XP challenges many of the common development practices, requires an open mind, and necessitates that the development team learn new techniques. XP evolution has been driven by a groundswell of developers miserable with the continuing failings of traditional software development methodologies.

    XP is very much driven from the programmer’s perspective, but never loses focus of the business aspects. Customer input is highly valued throughout the development process. In fact in an XP approach, the customer is part of the development team and thus maintains closer control of the project.

    A downfall of many software projects is the “us versus them” approach taken between software developers and customers. To counter this, an vital aspect of XP is that it revolves around customer satisfaction. XP draws the customer into the software development team, thereby allowing the whole team to become aligned to delivering the goal.

    XP is nothing new. Many XP practices are things that developers have been doing for years. The difference is that XP pulls them all together and “turns the volume up.”[1] The thought is to find the things that work well and make them work even better. This is where the extreme comes from, the high-intensity use of these practices.

    The goal of XP for you, the developer, is to enable you to focus on the code, developing high-quality solutions in a predictable and repeatable manner. XP focuses on the use of 12 main practices. Each one of these practices is a valuable tool to have in your toolbox. Each practice supports and strengthens some of the other practices. When used together, these practices have been shown to add up to more than the sum of the parts.

    The XP practices support four key values: communication, simplicity, feedback, and courage. Each of the values interacts with the other. Together these values work to make a strong foundation for developing high-quality software solutions. By using these practices and supporting these values, a team can ensure that high-quality software gets produced to meet the most pressing business needs.

    Working in The Ever-Quicker-Changing World
    The pace of change in the business world continues to increase at a dramatic rate. Even with the downturn after the dot.com crash, the business world is moving forward at a more rapid pace than ever before. With less funding available for IT projects, more than ever is expected from software development teams. To keep up with customer and client requests, we need some help.

    The Answers According to Microsoft
    Microsoft’s response to this need follows their line of reasoning behind tools such as Visual Basic, Visual C++, and MFC: Let us (Microsoft) worry about the plumbing, and you (the developer) can worry about solving the business problems. The .NET Framework takes this a step further than any of the offerings before. The .NET Framework provides what is, in effect, a large virtual machine for your software to run on. This framework provides a huge amount of base functionality for you to work with to meet your customer needs. It also enables you to interoperate with existing COM-based technology and write your solutions as components, with different components being written in different languages.

    The Answers According to XP
    Emerging nearly simultaneously with the .NET Framework, with the aim of solving some of the same problems, has been the agile development movement .One of the most well-publicized and written about of the agile development methods is XP. XP aims, through the use of the practices clarified in this chapter, to solve these problems of ever-changing needs and making huge, complex solutions.

    How .NET and XP Fit Together
    .NET is a concrete technology (a set of tools and libraries) with which we can work. XP provides us with a set of practices and techniques we can use to better develop our software.

    The .NET Framework provides a rich environment for building collaborative applications. Visual Studio .NET provides a rapid development IDE to help developers make these applications. .NET is being marketed as helping developers make solutions that support their business (customers) in a more responsive way; XP practices are centered on making predictable software for the customer. The common thread between XP and .NET is the central role played by the customer.

    Together XP and .NET work well, and most of the development teams I have worked with in the past year have been using both .NET and XP techniques to enhance their offerings to their customers and users. They are what I call eXtreme .NET teams.

    You Don’t Have to “Believe” in XP to Learn Something from It
    Many developers tell me that XP is “a nice thought, but it would never work in the real world.” Although I disagree, because I have seen it work very well in the real world, it might be that it would never work in their world. Moving to XP can be a cultural shift and can cause massive disruption if not handled carefully. But, some of the techniques practiced by developers who use XP are incredibly powerful tools for any developer to have in his or her toolbox. So even if you are in doubt and don’t believe XP is worth considering, I suggest you at least try to learn what is valuable from this set of practices.

    This book teaches these XP practices for you as a developer of .NET software. I hope that you learn from each one and use XP to make fantastic software.

    The Roles
    Within an XP environment, members of the team take certain roles. The following roles are the ones relevant to this book:

    Customer The customer is the goal owner. This role does not always have to be taken by a real end user (or purchaser) of the system. Often a product manager or a person from marketing can effectively play this role. The customer must have a full understanding of what they want from the software being developed. They do not need technical savvy (necessarily), but the customer should have a excellent understanding of what users will want to do with the software.

    In the eXtreme .NET team introduced in the Chapter 0, Chris is the customer.

    Developer I assume that if you are reading this book, you are a developer. It is the developer’s job to work with everyone on the team to make a fantastic piece of software. The developer’s day-to-day activity should focus on writing high-quality code.

    The eXtreme .NET team has Eddie, Sue, Pete, and Deepak as developers.

    Coach The coach is someone who has excellent people skills and can help remove blockages that are preventing the team from moving forward. The coach needs to know the XP practices to help the rest of the team best use them. The coach is a developer and will work on the code with the team. Most coaches are experienced developers, but they are not always the most experienced people on the team.

    Eddie is taking the role of the coach in the eXtreme .NET team we are following.

    What .NET Developers Can Gain from XP Practices
    Over the past few years, as always, new technologies and methods for building software have emerged. Two of the largest and most publicized have been XP and Microsoft’s launch of the .NET Framework. They have both come from very different places and focus on different areas of the software development paradigm.

    .NET is a brand name given by Microsoft to their latest range of development tools and frameworks. Here I focus on the use of the Microsoft .NET Framework for developing software that runs on the Common Language Runtime. Since the launch of the .NET Framework, Microsoft has been pushing hard to help companies develop software on the new platform. The success of .NET will depend on the uptake by software developers and then the clients of the software that is developed. The more software developed, and therefore available for a platform, the more attractive it becomes to utilize it, the more likely it will be that developers build software for it, and so on. Bill Gates terms this a virtuous cycle.

    So what have these two new things in the software development world got to do with each other? When development teams go to a new language or development platform, they do so for a reason, not just because it’s there! These reasons can vary, but the core theme that runs through them is “it will help us develop better software.” Better can mean several things: quicker, more robust, higher quality, more usable, greater scalability, less code to write, and so forth. Many of the teams I have worked with over the past few years have made the choice to not only adopt a new development toolkit, but also a new process for developing software. I have seen a trend emerging of teams moving both to .NET and adopting a more agile development process. These are eXtreme .NET teams.

    XP Practices Covered in This Book
    The following subsections examine how our eXtreme .NET team uses certain practices to develop better software. In this book not all of the XP practices are covered. I have selected the ones that I believe will add the most value to a team developing a solution using the .NET Framework.

    Whole Team (a.k.a. On-Site Customer)
    If you adopt the whole team practice, the customer is an integral part of the team. Therefore, the customer is always available to discuss issues and resolve them as they arise. This practice reduces the turnaround time for queries and prevents incorrect assumptions from being made. This practice really puts the pressure on the customer role. If a customer really wants software developed, they must place energy into the process. The concept of them being part of the team adds to the reality of one team, one goal.

    Never overlook the value of an on-site customer in any project. When both the development team and the customer are learning new features of a platform together, this practice becomes more valuable than ever before. The immediate feedback that can be provided by the customer enables the team to add really valuable functionality that they may have missed before.

    Consider how this applies to our eXtreme .NET team:[2]

    Deepak: Oh did you know we can do this with the .NET Framework? Would that be useful to you?

    Chris: Jeez, yes! How long would it take?

    Deepak: We reckon a day or two!

    Chris: How certain are you of that?

    Eddie: Pretty sure, after all we did a prototype when we were spiking that technology yesterday.

    Chris: Wow, well just do it! I’ll take tale card[3] X away until another iteration.

    If Chris hadn’t been there to work with the developers, one of several things might have happened:

    The developers might have thought “that’s cool, we’ll try to remember to tell Chris about that next time we see him” (and then most likely they would have forgotten).

    The developers might have assumed Chris wouldn’t want it and because timeframes were tight, not bothered to mention it in case Chris questioned for it as well as everything else they were doing.

    The developers might have assumed it was valuable for Chris and implemented it, but then not had time to end tale Y, when really Chris would have preferred not to have tale X delivered.

    Any of these (or other) outcomes would have been making assumptions about what the customer really wanted. Having the customer on site to answer these questions as they come up becomes incredibly valuable.

    Plotting Game
    The plotting game practice provides a mechanism for plotting out the features in a piece of software. The plotting game helps a team estimate timeframes for delivering the software with the features. This practice involves the whole team, including the customer. By including the whole team, the communication between the team members is enhanced. The developers sit with the customer to define the required features and prioritize them. The practice takes the form of a cooperative game. The aim for all participants is to achieve the same end goal: maximize the value of the software produced.

    Consider how our eXtreme .NET team interacts during part of their plotting game:

    Pete: Panic! Time for another plotting game.

    Chris: Hi guys, I’ve been talking to marketing, and they’ve been doing some research into usage and sales of the application we’re developing. They reckon that we need to make the application support Tablet PC features.

    Sue: No way! Why Tablet PC? We already discussed doing a version for the Pocket PC at a later stage.

    Chris: Many more of the users are mobile than we thought. This section of mobile PC users is moving to Tablet PCs. None of our competitors are supporting Tablet features. We can grab that share of the market if we can do this.

    Deepak: Okay, a Tablet PC will run our application fine. Tablet PCs run Windows XP professional with extra bits for the tablet.

    Chris: Okay that’s excellent, but what about support for writing in the forms?

    Eddie: Which forms? All of them? Where is the most value?

    Chris: We reckon if you can get the onsite report forms and expense claim forms to support handwriting that would be a excellent start.

    Pete: Panic! I have never done anything on the Tablet before; I have no thought how long that will take.

    Deepak: Chill Pete, it’s simple. The Tablet SDK just extends the .NET Framework.

    Eddie: Yeah, we need to tell Chris how long it will take! Any thought Deepak?

    Deepak: I reckon about a day for each form.

    Chris: Okay cool, I’ll expect that in the next milestone then.

    Eddie: Hold on Chris. You’ve already given us the tales for the next milestone; If you want us to do this Tablet stuff as well, then you’ll have to take something else out!

    Chris: Oh yeah! Okay can you swap that with the file-backup feature we discussed last time? You said that was going to take two days.

    Eddie: Fine, so we’ll add Digital Ink support to the onsite report and expense claim forms, and we won’t do the backup stuff for the next release.

    You can see how this conversation involves all the members of the team. By involving everyone, no knowledge is hidden. Everything is out in the open. Each member of the team knows the current goals.

    Pair Programming
    Pair programming refers to developing code with two developers sitting at one computer. In an XP team, you work with a partner on every piece of production code. Pair programming provides a constant peer review of the code. It helps to spread knowledge throughout the team and trains developers to communicate their intentions more fully as they work together. The aim is to increase the overall intelligence making each part of the system. The combined intelligence of two developers should be greater than either one of them alone.

    As far as information dissemination goes, I have never seen anything work as effectively and as quick as pair programming. One developer learns a new trick on the IDE while messing around after work one evening. The next morning that developer shows her partner what she has learned. The pair then splits when they have finished a task (unit of work, discussed further later on) and work with another two people whom they both show the new trick. Before lunch, four developers have all learned the new technique. By the end of the day, everyone on a team of 12 could easily have learned this new trick. Now imagine this working when each of those 12 developers is learning new things. If they all learn one new thing each evening and then spread the word the next day, the entire team is learning 12 new things a day. In reality, most developers learn more than one new thing a day when they are developing software.

    This works best when you have a very dynamic environment with rapidly rotating pairs. I recommend that everyone attempt to swap pairs at least twice a day. The more the better. Some of the best eXtreme .NET teams I have worked with swap pairs between four and six times a day; this is where the extreme comes in!

    Test-Driven Development
    Test-driven development (TDD) is the practice of writing tests before writing the production code. These tests are a cornerstone that supports many of the other practices, such as refactoring and simple design. The tests communicate the intention of the code and validate that intention each time they are run. This validation helps to increase confidence in the software developed.

    TDD is a fantastic example of developers providing their own safety net before walking the tightrope of a new development language or framework. Consider how our eXtreme .NET team has benefited from TDD:

    Eddie: So we thought the framework provided this function to perform X.

    Sue: Yes, so we wrote a few unit tests and ran them.

    Eddie: And, of course, they failed because we hadn’t place any code in yet.

    Sue: Yeah, Eddie insists we run the tests before we fill in the code; I despise it, but I know he’s right.

    Eddie: So then we made a class A and called method B on it.

    Sue: And one of the tests still failed!

    Eddie: We couldn’t work it out because that function in Java does just what we wanted, but in the .NET framework it appears to behave slightly differently.

    Sue: Excellent thing we wrote all the tests; otherwise, we could have made a incorrect assumption!

    In this example, Eddie and Sue were pretty sure the class library would behave as they expected it to, based on their experiences with a different class library. The fact they wrote tests meant they could go forward quickly, fix the problems early, and learn how the class library worked.

    The team had another conversation:

    Sue: So the next thing we needed was to complete the X task.

    Pete: Yes, Sue made us write all the tests first.

    Sue: Well, Eddie always does that, and he’s pretty smart, so I thought I’d copy him!

    Pete: Anyway, we ran the tests, they failed, and we started coding to get them to pass.

    Sue: After writing the code to make only two of the tests pass, we noticed that really four tests had passed; somehow we had got two tests to pass without doing anything!

    Pete: It turned out that the .NET class we were using already does those things for us and so saved us a load of coding.

    Sue: So it was worth writing all the tests first. Thanks, Eddie!

    Here Sue and Pete learned through writing the tests some functionality that the .NET Framework classes provided. This meant they could go ahead more quickly without writing code that duplicated the functionality already provided.

    The combination of TDD and pair programming meant that two members of the team learned the new feature in the .NET Framework. XP teaches that the more of the practices you use, the greater the benefit you get. The practices play off each other, and the last conversation was a excellent example of that in action.

    Constant Refactoring
    Refactoring refers to the process of changing the structure of the code without changing the behavior. Refactoring is a practice that aids the removal of duplicate code and simplifies the code base. Enhancements can be made more easily to refactored code. The practice of constant refactoring means that after each task is complete, the pair reviews their code to see how they might simplify the code without changing the behavior. This practice enables programmers to treat the code in a more dynamic manner. Developers describe their code as becoming more fluid after they learn to refactor effectively.

    Refactoring allows an overall architecture to emerge in the system as it is being developed. This approach contrasts with the normal approach of designing the architecture up front and then developing the code to fit with the architecture.

    I believe that this is a key component of XP that has really helped many of the teams I have worked with to develop new software with the .NET Framework. Instead of bringing preconceived thoughts of how software should be built and trying to make the new .NET code fit into this model, the XP teams have let their architectures emerge. These teams have been able to gain advantages that they would never have gotten if they had attempted to squeeze their code into an ancient model. This is especially the case for developers coming from either the VB or ASP background.

    Let’s join Sue and Eddie as they have just finished a task to see how they use refactoring to change the design:

    Sue: Cool, we’ve finished that. I like the way the places all update on the map and in the drop-down list now. Let’s check it in so that we can get the next task finished today.

    Eddie: Hey, hold on. We have a code-duplication issue.

    Sue: What?

    Eddie: The code we copied from the map object into the dropdown list.

    Sue: So?

    Eddie: We should only have the code in one place; then if we need to change it, we only have to change it in one place.

    Sue: Oh.

    Eddie: We can refactor the duplicate code into a separate object that both the UI controls use.

    Sue: But then the code won’t be in the UI controls where it’s used.

    Eddie: Even better! It will be simpler to test, and other non-GUI classes can use it.

    Sue: I bet there is a design pattern[4] for what we are doing.

    Eddie: You’re right. Will you look it up?


    Sue: Sure.

    Teams I have worked with who have previously developed large-scale enterprise applications in Java and C++ have been both surprised and pleased with the architectures they have developed. They have told me that if they had done a huge architecture design up front, they would never have built the system that way, and it would have been far more complicated than was needed.

    Spiking
    XP promotes a form of experimentation and research known as spiking or “doing a spike.” Spiking is experimentation to validate a theory. When the development team needs to know something, a thin vertical slice can be “driven” into the technology to get some answers. These answers can help the project succeed. Most spiking is done without the safety harness of TDD. Spiking is often carried out by solo developers who believe they need a break from pairing. Spikes are also “driven” by the one left out of a team when there are an odd number of developers, so not everyone can pair.

    Driving a spike into the area of functionality the development team is plotting to work on next will often produce some valuable information. In .NET projects I have worked on I have seen spikes effectively expose new information in the following areas:

    C# performance

    Web-service compliance for Remoting servers

    Issues with COM interoperability

    Transactional support in ADO.NET

    All of these examples were areas in which the development team had uncertainties. In a traditional development approach, someone would have been given the task of dealing with that particular issue. That one person would have become the specialist in that area. For some developers, this is fine because they believe they are securing their jobs in the future by being the top gun in that area. This is a fake belief. They are in fact acting as a bottleneck to the team’s overall knowledge attainment. By driving a spike and then reporting the result back to the team, the knowledge gets spread, and more perspective can be given to a task. Pairing with another developer to write the tests and production code after a spike is done also helps to spread the knowledge.

    Here’s an excerpt from a meeting with our eXtreme .NET team:

    Pete: I spiked the transactions in ADO.NET yesterday, and they’ll do the job fine, so I’ll pair with someone to write the code for task X this morning.

    Deepak: Did you reckon about how it works with our project? I’m worried about the threading and that some issues might arise from that.

    Pete: Panic! Oh no, I didn’t reckon of that.

    Deepak: Okay, I’ll pair with you this morning, and you can show me what you learned while we spike how it works across threads.

    Pete: Okay, cool.

    Here this team learned that the spike had taken them some of the way to knowing the answer, but more work still had to be done.

    Continuous Integration
    After each task is complete, the code written gets integrated with the entire solution. The entire code base is compiled, and all the tests are run to ensure the code just made does not break anything. This continuous integration practice enables the team to ship early and often and enables them to deliver the small iterations on a regular basis.

    As part of this practice, automated build and test scripts are developed. These scripts compile and test the entire solution. The scripts are set up as part of the development environment to make the entire process run more smoothly. This practice eliminates the element of human error from the process.

    The practices of a methodology are aimed at reducing the chances of something going incorrect. In the past, many projects would design and develop modules or components of the system independently. Near the end of the project, the team would attempt to integrate these modules to produce the final solution. This has become known as the huge bang approach and is often a rather painful experiencean experience that involves lots of swearing and cursing because the components do not work together as expected. The XP practice of continuous integration aims to prevent this problem from arising by insisting that developers integrate their code after each task is complete and run the entire suite of tests to ensure that their code has not broken anything.

    This practice is valuable when developing systems that consist of distributed components, such as Web services, remoting, custom components, or class libraries. Solutions developed in .NET often include many of these components. Even a simple ASP.NET Web site is likely to include some user controls (ASCX files). By carrying out the continuous integrations, the developers get immediate feedback on the changes they have made. The team can then work to fix any issues that arise. When working with a new toolkit, developers are much less likely to fully know all the implications of the changes they are making. This XP practice helps these developers to cope with this issue in a far more manageable way.

    Stand-Up Meetings
    The practice of Stand-Up Meetings occurs each morning. The team stands up and discusses the progress from the previous day and current work issues. Standing up keeps the meetings small and focused.

    Learning is about listening and doing. The proof that you have learned something is shown by your ability to teach it to someone else. Stand-up meetings provide an opportunity to spread knowledge to the team. Each morning the team stands up and each member makes a brief statement about his or her achievements the previous day and where he or she wants to get today. This is a fantastic forum for telling the team about some new technology or a new tool that you learned the previous day. This discussion can then elicit thoughts from other team members, as in the following example from our eXtreme .NET team:

    Deepak: Yesterday evening after you all went home, I was waiting for my girlfriend…

    Whole Group: Ah, how sweet.

    Deepak (blushes): Yeah, yeah, anyway I was playing with putting together a simple custom Web control and I learned this thing where you can use session states; I thought you should all know.

    Sue: Wow, that could be really useful for us for the online task list system; can you pair with me this morning and show me how?

    Deepak: Sure.

    Eddie: If we store those session states in the SQL database, can we then somehow access the task lists from the mobile interface?

    Chris: Now that would be useful for my clients! If it can be done, I reckon you’ll see it as a tale in the next iteration.

    The Other Practices
    The practices described so far are the ones that I focus on in this book. Other XP practices include the following:

    Sustainable pace (a.k.a. fixed working week) Work fixed hours, go quick while at work, and then get out. This is based on the principle that tired developers often make costly mistakes. Therefore, stay fresh and increase the intensity. By keeping to a fixed pace, we can last longer, and our endurance will be greater. Another benefit of sticking to fixed working hours is that the pace of progress can be more easily measured and therefore estimated in the future. If every week we work a different number of hours, it becomes very hard to make anything close to accurate estimates.

    Metaphor Have a way of describing the system being developed in terms of something everyone understands. For example, it is like a bakery; we take the ingredients and mix them a certain way to get the results. This is possibly the least-used practice and yet it has the potential to solve a large number of issues. Using a common vocabulary to describe the behavior of a system enables a shift from talking technical to talking about the user features of the system.

    Simple design Keep the design as simple as possible. Don’t gold plate or add features because you reckon you will need them later. This keeps the code doing just the things we need it to do now and no more. This practice helps to keep the cost of change low by not encumbering the system with unneeded features.

    Small releases Release a stable working version of the software every one to three weeks for the customer to review. This allows for increased feedback as to the direction of the development. This practice supports the feedback and communication values previously mentioned. Note that it is hard to accomplish this practice without employing the practice of simple design and thus the value the simplicity. These small periods of development are called iterations in XP terminology. We return to the concept of iterations later in the book.

    Coding standards Code written adheres to a set of guidelines so that it all has the same look and feel. This makes it harder to claim ownership of the code and so supports collective ownership. This process enables any developer (or pair) to refactor and enhance code you have written.

    Collective ownership The entire system and process is owned by the team, not any one individual. This means that no one person has any more right to change a piece of code than another. This helps to enforce coding standards. The flexibility of the code is thus increased because it can be changed and enhanced by the entire team; in this way, the combined intelligence of the team can be applied to make the software better.

    Leave baggage behind Do not get too attached to anything because things will change. The class library you wrote two years ago may no longer have any value. The toolkit or language you use today may well not be the one we use tomorrow. Travel light and you will travel quicker.

    Quality work There is no such thing as an acceptable bug. Keep the quality of your software as close to zero defect as humanly possible. Work with the broken-window[5] theory that once bugs creep into your system, they will multiply at a fierce rate. Kill them quickly before they can do this.

    Incremental change Do not make huge changes to a system; it will become unstable. Take it small steps at a time, and you will be more likely to succeed.

    Honesty and openness Work in an environment where everyone is open and honest. Discuss issues with everyone so that everyone can help to resolve them.

    Go with instincts People have gut instincts for a reason. Learn to work with them and embrace them in your environment; they add value to what the development team is producing.

    Teach learning Learning is vital to longevity in the software development world. It is imperative to the long-term success of a team that it encourages learning and teaching among its members.

    Embrace change The only certainty in software is that it will change. Learn to embrace this change and like the possibilities that arise from the changes made.

    Play to win An attitude of success breeds success; this is very different from “playing not to lose.” Build a record of success tales, and you will win more often.

    In his book, Extreme Programming Clarified, Kent Beck identified an initial 12 practices that have become the main XP practices; some teams even call this set of practices vanilla XP. It is often said that a team is not using XP unless they use all 12 of these practices. I reckon this is partly right. If you do not try something, you will not know whether it works. I reckon that a team can say it is an XP team if it uses many of the practices but has tried all of the practices.

    The original 12 practices discussed in Kent’s book are test driven development, plotting game, whole team, pair programming, continuous integration, constant refactoring, small releases, simple design, metaphor, collective ownership, coding standards, and sustainable pace. As you can see, the majority of the practices covered in this book fall into the original 12 practices.

    Along with these 12 practices, there exists an array of other practices often followed by XP teams. These have evolved and been adopted from other methodologies of development. These extra practices have been popularized via Web sites and forums and then adopted by teams.

    Even if you do not (or cannot) use all of these practices, they independently add value to the code you are writing. Techniques such as TDD will help you focus on the task at hand and deliver higher-quality code. Refactoring will enable you to change the structure and design of your system without affecting its behavior. Breaking tasks down into smaller units will enable you to focus on solving the problem one small step at a time. Pair programming will allow two developers to solve a problem that may have caused one person difficulty; it also provides an ongoing peer review of the code. Automating steps in your development process enables you to perform more regular integrations and get more reliable and rapid feedback on the state of the system.

    The 4 (+1) Key Values
    As previously mentioned, the four key values of XP are communication, simplicity, feedback, and courage. Kent Beck, one of the creators of the term eXtreme Programming and author of the first book on XP, has also added respect as the fifth of the key values. The following subsections briefly discuss each of these values.

    Communication
    Problems often result because people are not communicating. This is especially right in efforts that are team focused, such as software development. When the team is not openly communicating, the information flow that keeps the team moving forward is hurt.

    Terrible communication happens for a reason. Communication is not generally seen as an vital skill for developers to obtain. In fact, many developers have previous poor experiences of communication. Managers often do not want to hear what is being said. Other developers have their own issues to contend with and do not want to hear about your issues. This experience does not encourage developers to speak out when things need to be said. A few of these experiences may lead to an environment in which communication is at best limited and at worst nonexistent. A junior developer joining such an environment would not know anything was amiss. His lack of experience could lead to the belief that poor communication is how software should be developed.

    The proponents of XP (myself included) claim that communication is vital to develop software of value. The information flow made by ongoing communication allows all members of the team to contribute to the final results. This enables a group of individuals to behave as a team with the goal of developing fantastic software.

    Many of the XP practices force communication to be prevalent among the development team. Some of these practices such as the plotting game, pair programming, and stand-up meetings are obvious mechanisms, but others such as coding standards and refactoring also lead to greater communication, as you will see in later chapters. An XP team uses the role of the coach to police the communication, ensure it is occurring, and encourage the use of practices to overcome any barriers.

    Simplicity
    “What is the simplest thing that could possibly work?” is a weep often heard in XP teams. This means to do the simplest thing that will enable you to go forward in the right direction.

    Simple is Smart
    I often equate the value of simplicity with math problems. I remember at school struggling with a few tough equations, and then slapping myself on the forehead when I found the answer (because it was so simple). It often takes real genius to make a simple solution from a complex problem. Most people make a complex solution from simple problems and reckon they must be pretty smart because of the complexity they have made. In fact, the aim is to be as close to genius as possible and try to make simple solutions for the most complex problems. On my own, I have a lot of difficulty trying to be a genius at any time, but with a team of smart people, we can get a lot closer to genius on a regular basis.

    Don’t plot the future! The future will happen regardless of whether you plot it. By plotting the future, you are always avoiding the present. You are avoiding the present now by plotting. You are avoiding the present that will be by focusing on where you are in your plot. A common response I get to this is a declaration of my madness. “Of course you have to plot for the future and design the system first; otherwise, how would you ever be able to write the code? Don’t be crazy!” This is so hard for developers that it is one of the largest hurdles to overcome when moving into an XP environment.

    As you will learn in this book, XP does not promote detailed upfront design of the entire system. The design is done a small part at a time, allowing for greater flexibility in the software being developed. By developing one small piece of functionality at a time, testing first and constantly refactoring, you do not need to design the system; it will design itself! The designs will emerge as an outcome of taking a disciplined approach to using the practices. The team needs to have experience with object-oriented coding and design patterns so that they can see these patterns emerge and work with them. For this reason, tools such as UML are still incredibly valuable; they enable communication of the patterns as they emerge in the system.

    The point of keeping things simple is to code for now rather than never. By this I mean that we should code to solve today’s problems for your customers, not problems in the future that might or might not come up. Doing this gives you a far greater chance of solving those problems more rapidly and providing the customer with some value in the small term. If every day you produce something of value for the customer, then after several weeks the software you are building will have a culmination of all that value. This is often a sticking point for developers.

    To see how this is possible, you need to know how the practices enable us to treat the code in a different way than traditional approaches. The unit tests provided by TDD and refactoring techniques enable us to change code more readily. Making a more fluid code base means we do not need to be concerned if the decisions we make early on are absolutely right. We can change the design of the entire system more easily than ever before.

    This simple code that you (and your team) have written will ship quicker because less can go incorrect. Shipping more quickly enables you to get the value to the customer more rapidly and solicit feedback (see next section) more readily.

    Simpler code means less to communicate. By keeping the solution as simple as possible, you are aiding the first value we discussed. Having less to communicate means it is simpler to communicate and clarify what the code is doing and the emerging design.

    One final point: Simple does not mean simple. Developers who are starting out often misinterpret this as “Do the simplest thing you can possibly do.” This is incorrect; simple is often a lot harder to achieve than complicated. As you work through this book, you should start to see how by keeping the task you are working on simple you can build more complex solutions. An example presented later in this book is replacing a switch statement with polymorphic behavior. The switch statement is simpler to write, but the polymorphism provides a simpler solution.

    Feedback
    Feedback on your progress enables you to adjust your actions to better meet the goals of the project. Feedback leads to a greater understanding of the state of the system being developed. This understanding tells you exactly what you have done right and what you need to work on. Knowing what you need to work on is incredibly valuable. The feedback acts as a guide for the next set of tasks. Understanding an issue early often averts a potential crisis later on.

    If you question an XP team how they are coming along, you might get a response such as “don’t question me, question the system.” XP teams build feedback systems into their software using tests, profiling tools, and automated builds. The results from these are generally posted in very public places, providing feedback on their progress for all to see.

    The granularity of the feedback cycles goes from minutes to months. The following identifies some of the practices that support these different timescales.

    TDD Developers drive the code development by writing tests first and then the code to make the tests pass. This leaves test code in the system that provides feedback on the stability of the system. An XP team will receive this feedback at intervals of minutes as they work on the code throughout the day.

    Customer user tales The practice of letting customers define the functionality their users require on tale cards, typically index cards. These tale cards are discussed further with the customer when the time comes to implement that functionality. This provides the customer with up-to-the-minute feedback on what is being worked on. (Customer user tales are discussed more in the next chapter.) Most customers will check completed tales daily.

    Stand-up meetings When a customer tale is completed, the customer is informed. Often the customer will get a demo of the system within a day of a tale being completed. This helps to obtain more rapid feedback. The meetings occur daily, and so again this is daily feedback.

    Small releases Within the first month or two, an early working version of the software should be ready to ship. This is a goal that every XP team I have worked with has managed to reach. This shipment might be to only a few friendly parties (usually chosen by the customer). Shipping will allow the developers to receive feedback as to the usefulness of the system being developed and the correctness of the functionality. The timeframe for feedback from small releases is in terms of weeks and months.

    Ship it Quick, Ship it Often
    Until it ships, you know nothing! I have personally worked on projects with large scopes where the business needs were not clearly understood. The project managers refused to give the customer anything early on in the development life cycle. The managers would say, “It’s not ready, and they won’t know that these functions are missing.” This was a flaw in the development life cycle. The development team was coding blind. If we had given the software to the customers earlier on in the process, we could have received feedback on our progress. We were not getting feedback from what we had already developed, and this ultimately led to a failure in the project delivering what the customers wanted.

    It is worthwhile shipping the simplest system that makes sense. This simple system forces feedback from the customer, and you can use that feedback to improve the software.

    Simplicity, communication, and feedback make a self-supporting cycle; feedback leads to more communication, communication leads to understanding what to test, simple systems are simpler to test, simpler to test means more feedback, and so on, as shown in Figure 1-1.
    Figure 1-1. The self-supporting cycle.

    Courage
    To use the practices prescribed by XP and get the full value from doing so takes courage. Many of the practices are hard, and if taken at face value, they don’t seem to make sense. It is this courage to take up the practices and make the results happen that contributes to the extreme in XP.

    By employing the safety harnesses provided through the use of the practices, developers can increase the intensity of their work. They can go quick and furious at cutting code that solves the problems at hand. By doing this, developers will find they get more produced but may tire more easily; this is called upping the burn rate and lowering the hours. It is about working hard and quick while at work and then getting out to relax and delight in life. All of these things take courage to do.

    Other aspects that require courage include making changes when needed, not before, and being prepared to throw code away. Both of these practices are alien to many developers and might require a change in the way you reckon about the code you are writing. As mentioned previously, one of the themes of XP is to lower the cost of change. Writing code that we might need in the future really increases the cost of change. Code you do not need now is code that we are not using but that needs to be changed. The cost of change can be lowered by not including code until it used. The tests help us to validate this; if we find code that is not being used, we should throw it away because it is encumbering the system needlessly.

    Employing just courage alone without the safety nets and harnesses provided by the other values and through following the practices is perilous, often lethal, to the project. Take care and allow your confidence to grow as you follow the practices so that you can have the courage to communicate new thoughts. To ensure these new thoughts, keep the system simple. Experiment with new thoughts and get feedback on new thoughts. These thoughts will become the code in your software.

    Respect
    One of the least-discussed and yet most vital values of XP is respect. This is mainly applied on a human level to the people we work and live with. It is through respect that we can learn how other people reckon. Knowing how people reckon enables us to adjust our own behaviors to better work together to accomplish the goals for which we are aiming. Let’s start with our own team of developers. The respect for other developers in our team and other teams around us is vital to the health of our environment. Showing humility for other developers will enable us to learn from them.

    Although this book is not about building teams, I recommend that every developer who works in a team of more than one person find out more about team-based behaviors. If every developer did this, the world’s software teams would be much more productive.

    I believe every member of a team has some value to offer that team, and it often takes work to instill that belief in other members of the team. Showing disrespect for a member of the team is akin to what is described by Jim McCarthy[6] as “flipping the bozo bit”; each team member has a bozo bit. Initially, none of us is a bozo, and the bits are all off. When you flip the bit on, that person becomes a bozo and has to work hard to switch the bit off. It is vital to respect our fellow team members and not “flip the bit” on them.

    Working Together
    When I work with development teams, I often hear developers make comments along the lines of “the customer is an idiot; he doesn’t know what he wants, so we’re developing this system that we know he really wants.” It astounds me that such arrogance can really exist in a business environment and people get paid for it (often large sums of money!). Respect for the customer is vital to a successful project. The customer is the person with authority to make decisions, such as whether the team gets paid for doing this work. The problem often stems from the belief that because the customer “can’t count in binary on his fingers,” the customer is “a total loser.” It is right that many customers do not have technical skills, but that is not their job. They are part of the team to bring an understanding of how to make business value from the software being developed. This is a communications issue. It is the job of the development team to work with the customer, in partnership, to produce what the customer does want and ensure that it adds value to the customer’s business.

    The management in an organization has a job to do. It often does not include writing code, but this does not make them any less valuable to the project. The management is there to help make your life simpler so you can accomplish the job at hand. Have respect for the managers. They are often under pressure to perform and deliver. If you have respect for this, you can work together as a team to accomplish far more than is possible by working against each other.

    Finally, it is imperative to respect the users of your software. In one survey done on a piece of software that had been released, 500 users were questioned to carry out tasks with the software. The results were disappointing; more than 90 percent of the users failed to carry out all the tasks. The developers, when told this, responded with, “Where did you find so many stupid users?” This lack of respect for the users led to the creation of a piece of software that had all the functionality but was incredibly hard to use; this was not valuable for their business or the customer’s business and the software had to be changed to make it more user friendly. It is vital to respect the users and know how they will use the software.

    Conclusion
    You should now have a better thought of what XP is and what you can gain from it. XP might not be for all of us, and some areas of business may never find it suitable for their development methodology. But, we can all learn things from the XP practices. The rest of this book takes you through the techniques you can apply every day, even if you are not working in an XP development team. In the next chapter, we start this process by learning pair programming and how two developers can work together to solve problems and write better code.
    “Turning the volume up” means taking something that works well and making it work even better.

    The eXtreme .NET team is introduced in Chapter 0.

    Tale cards are clarified in Chapter 2.

    Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns. Reading, Massachusetts: Addison-Wesley Professional, 1995.

    Gladwell, Malcolm. The Tipping Point. Boston, Massachusetts: Back Bay Books, 2002. This book describes the broken-window theory.

    McCarthy, Jim. Dynamics of Software Development. Redmond, Washington: Microsoft Press, 1995.

    Chapter 2. Pair Programming
    This is a chapter for you to follow if you have a partner to pair with. If you do not have someone with whom you can work through this chapter, go find someone. Recruit a friend, work colleague, or a fellow student.

    This chapter provides a series of exercises that encourage you and your partner to take turns in typing the code and thinking about the problems. This chapter emphasizes the benefit of programming with a buddy and how much fun this type of development can be. It also shows you how business benefits can be gained from development in pairs and how you might best promote these thoughts to your organization.

    As discussed in Chapter 1, pair programming is the practice of developing all production code with two developers sitting at one machine. This goal of this practice is for developers to help each other make something far greater than one developer alone could do alone.

    Pair programming may be the toughest of the XP techniques. It certainly raises the most concern among the software development community. As software developers, we are typically taught to program on our own. I expect that (like myself), the self-taught programmers have spent many hours on their own, playing with code and working out how to make some software do something. Even the education system tends not to encourage software to be developed by groups or teams, measuring success by the work of an individual.

    But, as an average individual (which, of course, you and I are not!), my IQ is around 100. Surely if I work with someone else who is also average, our combinedIQ should be somewhat higher. It is unlikely that we can get close to 200 because much of our intelligence overlaps, but hopefully we could get to 130 or more. In Software for Your Head[1], the McCarthys clarify the thought of a team IQ, with each member of the team contributing to the overall IQ of a team. Pair programming relies on the same premise, and the team size is two for the coding task being developed.

    I’m Not Sitting with Him!
    I have been astounded and astonished more than once to hear fully grown adults utter these words: “I’m not sitting with him.” It is nearly as much as I can do sometimes to question whether they reckon they are still in grade school. But, that would be unproductive.

    The Professional Attitude
    The reality of the modern workplace is that we might not connect with everyone as well as we might like. We will have to work with some folks who have terrible breath, speak too loudly or too quietly, and so on. As professional software developers, we need to act in a professional manner and exhibit a professional attitude toward our colleagues.

    Get With the Winning Approach
    If we have a technique that enables us to deliver software that is better in some way (quicker to deliver, more robust and smaller), we should use it until we find a technique that makes more of what we want. In my opinion, this philosophy should be applied to more than just software development, but that’s a topic for another book.

    It’s a Game
    As the saying goes, “Time flies when you’re having fun.” I reckon this could easily be extended to “Time flies when you’re having fun developing software.” It always amazes me how quickly the day goes by when I am in programmer mode. I am sure that in part it is because I am enjoying what I am doing. I like writing code and developing software; to me it is like a puzzle game.

    As a young kid learning to program, I had a excellent friend who was also keen to learn, and we would often sit together at my father’s Commodore computer and type in lines of code, suggesting thoughts as we went and improving on each other’s code. It was a lot of fun, and we made some pretty cool small applications (at least, we thought they were).

    Upon learning of pair programming, I realized that as kids, my friend and I had been pair programming, and that if it was fun then it should surely be a lot of fun now.

    Exercise 2-1: Game to Teach Pair Programming
    This game is based on another game called the Perfection Game, which can be found in Software for Your Head. You can play it with two or more people. To play this game, you need one PC with one keyboard, one mouse, .NET Framework development tools installed, enough chairs, and space for all developers to sit and see the screen. With more than two people, I suggest you use a projector so that all the participants can see what is going on.

    There are two roles in this game: programmer and supporter. Each person takes turns to be the programmer, while everyone else takes the role of the supporter.

    1. The programmer declares what the function he is going to write will do. He states his intention. I suggest something small that can be completed in less than 5 minutes.

    2. When the programmer is finished, he declares he is done.

    3. Each supporter in turn grades the function from 0 to 10, with 10 being the highest value and 0 being the lowest. For every point less than 10 that is given, the supporter must come up with a way of making it a 10.
    a. The supporter then follows his grading with a statement of what he likes about the code as written.
    b. The supporter then states what it would take to get a 10.

    4. One of the supporters takes the role of the programmer, and the process starts again.

    5. After everyone has had one turn at being the programmer, you can repeat the cycle, but this time the programmer starts with the code that he or she wrote before and tries to improve it for a couple of minutes to raise the grade.

    Here is an example round between two of the programmers in our eXtreme .NET team, Deepak and Sue.

    Deepak: I’ll go first. I’m going to write a function that increments a private variable until it reaches a certain number and then resets it.

    Sue: Okay, go to it.

    <Deepak types the following>

    class PairGame
    {
    int var;

    public void Increment()
    {
    var++;
    if (var > 500)
    {
    var = 0;
    }
    }
    }

    Deepak: Done!

    Sue: Cool. I give the code 5 out of 10. What I like about it is that it is concise, the naming of the class and method is clear, and the code is simple to read. To get a 10, the integer variable should be named something meaningful; var doesn’t mean much to me. The integer variable should be initialized somewhere. The limit and reset numbers, 500 and 0, should be in variables or constants to make them simpler to change later. You should write a test to prove it works. If it had all that, I would give the function 10 out of 10.

    Deepak: Thanks, Sue.

    Sue: You’re welcomenow it’s my turn.

    Pointers for the supporter:

    Keep the feedback positive. Say what you like and what it would take to get to 10. Do not say what you don’t like.

    Don’t be personal. Keep your comments focused on the product, not on the programmer. Phrasing the statements is vital. It is better to say, “I like the way the function uses the increment operator” rather than “I like the way you used the increment operator.”

    Remember you are scoring the product, not the programmer.

    Pointers for the programmer:

    Remember, it is not personal. The supporter is scoring the code, not you.

    Always remember to thank the supporter for the input. It is helping the product get better.

    Exercise 2-2: Step-by-Step Exercise to Get a Feel for Pair Programming
    In this exercise, you focus on the pair programming aspect and do not worry about the other practices. This exercise can be done without having read any of the other chapters in this book. The aim is to help the two of you get a feeling for writing code as a pair.

    To do this exercise, you need one PC with one keyboard, one mouse, .NET Framework development tools installed, two chairs, enough space for both developers to sit in front of the PC and see the screen, and one copy of this exercise (i.e., this book).

    Start off with one of you controlling the PC (the driver) and the other holding the exercise (the navigator). The navigator is going to guide the driver through developing the code. At certain points, you will swap roles. It is very vital that you do swap at the specified times and no later. While you are in the role of navigator, try not to show your partner the code as it is written in the exercise. You should attempt to verbally communicate what needs to be done. You can draw diagrams and as a last resort read out the line of code to be typed. If at any point either of you feel unsure that you have done the right thing, it is time to compile and test what you have done. You should be able to compile and run the program after nearly every step.

    In keeping with the theme of pairing being fun, you are going to develop a screen saver together:

    1. Start off by setting up a Windows Forms application to work as a screen saver. Make a new C# Windows Forms application project called Extreme Screen Saver.

    2. Change the name of the made form class to SaverForm.

    3. Edit the constructor to take an integer parameter and store it in a member variable of the class called ScreenID.
    private int screenID;
    public SaverForm(int screen)
    {
    InitializeComponent();
    screenID = screen;
    }

    4. Edit the Main method to use parameters to determine how to run the application. This is how Windows launches a screen saver.

    It might help if you can draw a table for your partner (on a white board or a scrap of paper).
    Argument
    Meaning

    /c
    Show the config/settings screen

    /s
    Launch the screen saver

    /p
    Preview the screen saver

    static void Main(string[] args)
    {
    if (args.Length > 0)
    {
    // config
    if (args[0].ToLower().Trim().Substring(0,2) == “/c”)
    { }
    // saver
    else if (args[0].ToLower() == “/s”)
    { }
    // preview
    else if (args[0].ToLower() == “/p”)
    { }
    }
    else
    { }
    }

    5. Make a static protected method in the SaverForm class called LaunchSaver. In this LaunchSaver method, add code to iterate through all the screens connected to the PC and make a new form to run in that screen.
    static protected void LaunchSaver()
    {
    for (int i = Screen.AllScreens.GetLowerBound(0);
    i <= Screen.AllScreens.GetUpperBound(0); i++)
    {
    System.Windows.Forms.Application.Run(new SaverForm(i));
    }
    }

    6. Back in the Main method, call this static method from the launch and default argument cases.
    static void Main(string[] args)
    {
    if (args.Length > 0)
    {
    if (args[0].ToLower().Trim().Substring(0,2) == “/c”)
    { }
    else if (args[0].ToLower() == “/s”)
    {
    SaverForm.LaunchSaver();
    }
    else if (args[0].ToLower() == “/p”)
    { }
    }
    else
    {
    SaverForm.LaunchSaver();
    }
    }

    7. Compile and run the program. Close it, and then try renaming the made EXE file from eXtreme Screen Saver.exe to eXtreme Screen Saver.scr. You should be able to install this and run it as a screen saver.

    8. Swap roles.

    9. We will now set up the form to occupy the entire screen and respond to mouse and keyboard events to close down. In the design view for the Saver-Form, set the FormBorderStyle property to None.

    10. Make an event handler for the Load event on the form. This can be done by double-clicking the form in design view. In this method, we need to set the Bounds of the form to those of the screen, hide the cursor, and set the form to show on top of all the other forms.
    private void SaverForm_Load(object sender,
    System.EventArgs e)
    {
    Bounds = Screen.AllScreens[screenID].Bounds;
    Cursor.Hide();
    TopMost = right;
    }

    11. In this Load method, we can also add handler code for the mouse and keyboard events. We want to handle these events and choose whether we are going to end running the screen saver. Start by adding an event handler for the MouseMove event. Call this method SaverForm_MouseEvent. In Visual Studio.NET, you can type MouseMove += and then pressing the Tab key should generate the handler skeleton.
    private void SaverForm_Load(object sender,
    System.EventArgs e)
    {

    MouseMove +=new MouseEventHandler(SaverForm_MouseEvent);
    }
    When the application first runs, it will get the mouse location through a mouse go event, so the first time we get the event, we just need to trap the position of the mouse in a member variable. After that, if the mouse moves, we need to close the application.
    private Point initialMousePt;
    private void SaverForm_MouseEvent(object sender,
    MouseEventArgs e)
    {
    if (!initialMousePt.IsEmpty)
    {
    if (initialMousePt != new Point(e.X, e.Y))
    Close();
    }
    initialMousePt = new Point(e.X, e.Y);
    }

    12. We can use this same event handler for the mouse down event that occurs when a user clicks a mouse button. Add the method to the event in the Load method. Then change the MouseEvent method to also close the form when a click has occurred.
    private void SaverForm_Load(object sender,
    System.EventArgs e)
    {

    MouseMove +=new MouseEventHandler(SaverForm_MouseEvent);
    MouseDown +=new MouseEventHandler(SaverForm_MouseEvent);
    }

    private void SaverForm_MouseEvent(object sender,
    MouseEventArgs e)
    {
    if (!initialMousePt.IsEmpty)
    {
    if (initialMousePt != new Point(e.X, e.Y))
    Close();
    if (e.Clicks > 0)
    Close();
    }
    initialMousePt = new Point(e.X, e.Y);
    }

    13. Now let’s do the same with a handler for the KeyDown event.
    private void SaverForm_Load(object sender,
    System.EventArgs e)
    {

    KeyDown +=new KeyEventHandler(SaverForm_KeyDown);
    }

    private void SaverForm_KeyDown(object sender,
    KeyEventArgs e)
    {
    Close();
    }

    14. Compile and run the program. It is starting to work more like a screen saver. Rename the EXE file to an SCR file and test it. We now have a basic screen saver.

    15. Swap roles.

    16. The next thing to do is to add some drawing functionality so that the screen saver really does something. We will start by adding a Paint event handler to the Form class. Again we can do this in the Form load method.
    private void SaverForm_Load(object sender,
    System.EventArgs e)
    {

    Paint +=new PaintEventHandler(SaverForm_Paint);
    }

    private void SaverForm_Paint(object sender,
    PaintEventArgs e)
    {
    }

    17. In the Paint event method, we will add some code to draw the text eXtreme .NET in the center of the screen. We will use the TranslateTransform method to shift the drawn text to the center of the screen.

    You need to add the System.Drawing.Drawing2D namespace to this class file because we need to use the MatrixOrder enumerated type from there.
    private void SaverForm_Paint(object sender,
    PaintEventArgs e)
    {
    Graphics gc = e.Graphics;
    Point screenCenter = new Point(
    (int)(gc.VisibleClipBounds.Width/2),
    (int)(gc.VisibleClipBounds.Height/2));

    gc.TranslateTransform(screenCenter.X,
    screenCenter.Y,
    MatrixOrder.Append);

    int fntSize = 12;
    Font fnt = new Font(FontFamily.GenericSansSerif,fntSize);
    Brush brsh = Brushes.Red;
    StringFormat format = new
    StringFormat(StringFormat.GenericTypographic);
    format.Alignment = StringAlignment.Center;
    format.LineAlignment = StringAlignment.Center;

    SizeF size = gc.MeasureString(“eXtreme .NET”, fnt);

    RectangleF rect = new RectangleF(
    0 – size.Width/2,
    0 – size.Height/2,
    size.Width,
    size.Height);

    gc.DrawString(“eXtreme .NET”, fnt, brsh, rect, format);
    }

    18. Add a timer control to the form and use the timer event to redraw the screen so that we can add some animation to the text. You do that in the design view. The timer control can be dragged from the toolbox onto the form and then double-clicked to generate the event handler method. Make sure you set the Enabled property of the timer to right so that it raises the events.

    19. In the timer event handler, we will call Invalidate.
    private void timer1_Tick(object sender,
    System.EventArgs e)
    {
    Invalidate();
    }

    20. Next animate the text. We will make the text grow and shrink on the screen using the ScaleTransform method of the Graphics object. To do this, we need some class member variables to represent the current scale and the amount to change the scaling. We can manipulate these in the timer tick event.
    private float scale = 1;
    private float scaleChange = 0.1F;

    private void SaverForm_Paint(object sender,
    PaintEventArgs e)
    {
    Graphics gc = e.Graphics;
    Point screenCenter = new Point(
    (int)(gc.VisibleClipBounds.Width/2),
    (int)(gc.VisibleClipBounds.Height/2));

    gc.ScaleTransform(scale,
    scale, MatrixOrder.Append);
    gc.TranslateTransform(screenCenter.X,
    screenCenter.Y,
    MatrixOrder.Append);

    }

    private void timer1_Tick(object sender,
    System.EventArgs e)
    {
    scale+= scaleChange;
    if (scale < 1)
    {
    scaleChange = 0.1F;
    }
    if (scale > 20)
    {
    scaleChange = -0.1F;
    }
    Invalidate();
    }

    21. Compile and run the program. You may want to decrease the Interval property on the timer to make the animation more viewable.

    22. Swap roles.

    23. We will use some of the built-in double buffering provided by the .NET Framework to remove the screen flicker. We will also add some more movement to the text animation. Before we add the double buffer in the constructor of our Form class, we need to set the style of the form to use WMPaint, the UserPaint style, and DoubleBuffer.
    public SaverForm(int screen)
    {
    InitializeComponent();
    screenID = screen;
    this.SetStyle(
    ControlStyles.AllPaintingInWmPaint|
    ControlStyles.UserPaint|
    ControlStyles.DoubleBuffer, right);
    }

    24. Now let’s add rotation to the text animation so that it spins around as it grows and shrinks. We will use two class member variables to indicate the current angle of the text and the next amount by which to change the angle. We can vary this in our timer tick event method. In the Paint event method, we will use the RotateTransform method to rotate the text around the origin.
    private float angle = 0;
    private float angleChange = 5;

    private void SaverForm_Paint(object sender,
    PaintEventArgs e)
    {
    Graphics gc = e.Graphics;

    Point screenCenter = new Point(
    (int)(gc.VisibleClipBounds.Width/2),
    (int)(gc.VisibleClipBounds.Height/2));

    gc.RotateTransform(angle, MatrixOrder.Append);
    gc.ScaleTransform(scale,
    scale, MatrixOrder.Append);
    . . .
    }

    private void timer1_Tick(object sender,
    System.EventArgs e)
    {
    angle+=angleChange;
    scale+= scaleChange;
    if (scale < 1)
    {
    scaleChange = 0.1F;
    angleChange = 5F;
    }
    if (scale > 20)
    {
    scaleChange = -0.1F;
    angleChange = -5F;
    }
    Invalidate();
    }

    25. Compile and run the program. The animation should look much smoother. Try it as a screen saver by renaming the EXE file.

    This exercise should have provided you with an understanding of how often you should swap roles and how vital it is for both of you to be involved with the code being developed. Pairing is no fun if you are just watching someone else write code. It also has very small value if that is all that occurs during a pair-programming session.

    Pair programming is about both developers being present and focused on the task at hand and both developers aiming to help make the code better.

    Try It Together
    You are now ready to try pairing on some code together. Remember, pair programming is a skill as much as learning to code is a skill. The more you do, the better at it you will become.

    Exercise 2-3: Exercises for Two Developers to Work On Together
    These following tasks are for you to work through together and try to develop the screen saver we developed further. During the exercise, make sure you swap roles often; I suggest that if you haven’t swapped for ten minutes, you should stop and swap roles.

    1. Extend the screen saver to show a preview.

    In the preceding exercise, you have made an entry point in the code that will get called when the program is run with the /p argument. Extend the code to draw the animation in the preview window provided.

    Hint: The second argument in the command-line arguments is a handle to a window (hWnd) in which to draw the screen saver preview.

    2. Extend the screen saver to show a settings box.

    Carry on from the screen saver exercise again, and this time add functionality to show a configuration dialog box so that the user can alter the settings on the screen saver. The entry point is already made in the Main method when a /c parameter is passed to the application.

    The settings to be altered are the speed of the animation, the angle of rotation, the text color, and finally the ability to customize the text.

    Conclusion
    As mentioned throughout this chapter, pair programming is a skill that needs to be learned. Some practices covered in this chapter are intended to help you become a better partner when pairing. The perfection game can teach us how to help each other make a better product in a positive way. Keeping the conversation going during the pairing session is critical. The communication that occurs while pairing is what enables us to make something better than we would have done on our own.

    As a closing thought, I want to share with you the fact that the more I pair program, the more I realize what I don’t know. It is the best way I have found of learning new skills from another developer. Whenever I have an opportunity to pair program with a developer, I do so. I have learned as much from junior developers as I have from experts. With the combined intelligence and experience of two developers at work on the same code, this is the closest thing to having a genius write every line of code.

    The next chapter explores another practice we can use to help us toward genius a practice that helps us to solve huge problems.
    McCarthy, Jim. Michele McCarthy. Software For Your Head. Upper Saddle River, New Jersey:Addison-Wesley Professional, 2001.

    Chapter 3. How to Solve Huge Problems
    This chapter examines how to better solve programming problems. The aim is to get tasks to a level where we can have some functionality accomplished at the end of every day. Then we do not have to be so concerned with the larger-picture stuff while we solve today’s problems.

    This chapter, like Chapter 1, is not specific to the .NET Framework. You can use these thoughts in other development environments. We will be using the lessons learned from this chapter later on in this book. Be sure that you know how to break down tasks and make time estimates before you jump ahead.

    When mentoring development teams, I often encounter developers who do not (or cannot) break down a task into really small pieces of work that are achievable in a matter of a few hours or minutes. This is a skill that you need to learn. This chapter examines why it is vital to have these small tasks, and shows how to break down some complex problems into simple simple-to-solve units of work. This chapter discusses XP practices that help us accomplish this task breakdown.

    The Software Development Problem
    When developing a piece of software, you are often dealing with many issues at the same time, some of which might detract your focus from the particular problem you are trying to solve. Issues you are dealing with will include the following:

    Adhering to the design of the system

    Making sure your new code doesn’t break any existing functionality

    Ensuring you are following the coding conventions

    Worrying how this solution will impact future tasks that need to be completed

    Wouldn’t it be excellent if you could forget about those other issues? Then you could just code a solution today to the problem you have at hand. Problems are hardly ever so small and focused that you can really accomplish them today, or even this week.

    That is what we are going to attempt to achieve. First, we will explore what makes a excellent solution. Second, we will work through an exercise that demonstrates how we can carry out focused small tasks that lead us towards the completed solution.

    The Genius Is in the Simplicity
    A genius is a person who can take a complex problem and find a very simple solution that solves it. This solution is usually honestly trivial to implement after you know what it is. Most of us take the simple option, but, and make complex solutions to solve our complex problems. We do this for a number of reasons; the two main ones are as follows:

    We take on too much at one time.

    We look at how a similar complex problem has been solved before and try to copy that solution.

    Our egos don’t help in this matter. We want to show off how smart we are at implementing some complicated solution. We want to justify that we should be paid more and promoted. We don’t feel comfortable going to our boss and saying, “That problem was solved in five lines of code, but it took me the whole of the past three days to write those five lines.”

    Huge, Complex Solutions
    The distress with designing these huge, complex solutions is that we often then get stuck when trying to really implement them. They are just too hard and have too many points of failure. These solutions end up becoming the bane of our existence. We have to maintain them and fix bugs in them. Sure, we can be excellent citizens and use design patterns and well-documented architectures. Ultimately, but, we end up, time and time again, juggling huge issues while trying to get a new piece of functionality into the system.

    Among the XP practices are some techniques that will help us reduce the complexity of the problem.

    The Genius Function
    Ideally, we should find some way that we can all be geniuses. If we are all geniuses, we can always make simple solutions to all of our problems. Something we all know is that it is simple to make simple solutions to solve simple problems. So to become a genius, all we need to do is break down all of our problems into lots of smaller problems that are simple to solve.

    Any problem that I estimate to take longer than four hours to solve is too huge for me to feel comfortable with. I want to accomplish at least one thing in a day; if I accomplish more than that, I feel even better. This is a personal choice, but most people I have worked with aim for four hours or less. I have never worked with anyone[1] who was comfortable with tasks that lasted more than six hours. If I get a task that I estimate will take longer than my maximum four-hour period, I break it down into several smaller tasks. If any of those tasks will take longer than four hours, I break those down again. Something that I have found fascinating is that the most effective developers I know break down the majority of their tasks so that they require less than an hour to complete.

    Example of Problem Breakdown
    Let’s see how this works, beginning with a trivial example before I lead you through a more complex problem breakdown.

    Suppose the customer has questioned us to develop a piece of software that emulates a calculator on the desktop. So this is our problem: develop a .NET Framework calculator. Simple. So how long will the development take? Do you know immediately? I don’t, but I bet it will take longer than four hours, so I need to break down the problem. Here’s a list of smaller problems:

    Add function Add two numbers together

    Subtract function Subtract one number from another

    Divide function Divide one number by another

    Multiply function Multiply two numbers together

    Can I give time estimates for each of these functions? I feel confident that I can, and I estimate between one and two hours for each function. Some people might question, “Why so much?” After all, they know that I am an experienced developer and might reckon that I should be able to place a simple calculator together pretty quickly. I am estimating that this will take me up to a day to complete based on my experience. I am breaking the problem down into even smaller steps, and I will go through that process with you now for the add function.

    Task
    Time to Complete

    Test for adding zeros
    15 minutes

    Test for adding negative numbers
    15 minutes

    Test for adding minimum numbers and maximum numbers(forcing overflows)
    15 minutes

    Test for adding positive numbers
    15 minutes

    User interface
    15 minutes

    Check code into source control and integrate with any existing solution
    5 minutes

    Total
    1 hour 20 minutes

    Notice that I emphasize writing tests. In the next chapter, you will learn why and how to write tests before the code. For now, it is vital to know that it gives me more focus on developing only what is required and nothing extra. These tests define the behavior expected of the object that will be developed.

    Also notice that I am including the time it takes to write these tests, to develop the user interface, and integrate the code with a source control system. All these extra things take time that is often not accounted for by less-experienced developers and project managers. These extra things are often the reason so many software projects run late; developers too often fail to account for the “other stuff” that we need to do to write high-quality code.

    With less-trivial problems, you will often find yourself asking some tough questions, and this is where having contact with the customer becomes vital. It is hard to break tasks down without being able to get answers to questions you have. Consider the preceding example. I have made an assumption that the calculator will deal with negative numbers. What if negative numbers are not permitted or required by the system? Having the customer present while doing this task breakdown will make this very apparent. The conversation in our eXtreme .NET team might go something like this:

    Chris: Why are you testing for adding negative numbers? We don’t want to add negative numbers!

    Pete: Panic! What should happen if we get a negative number?

    Chris: You should inform the user that negative numbers are not allowed.

    Eddie: Okay, change that test to “Test for handling negative inputs, 10 minutes.”

    Remember one of the practices discussed in Chapter 1 was the whole team. Here is an example where having the customer as part of the team can make a difference. If you cannot get a customer to be present during a task breakdown session, try to get him or her on the phone or instant messenger. Failing that, try your manger or other developers. At least they may spot some mistakes or incorrect assumptions you have made before you really commit them to code. You should e-mail your customer the results from each task breakdown session so that they can review them and change their minds or reset the direction.

    We return to this scenario later on in this book to write code for some of these tasks.

    Problem Breakdown Exercise
    Hopefully you have a excellent thought of what we’re aiming for now, so let’s try to tackle a slightly more complex problem. This problem may still seem trivial in comparison to many real-world problems you will encounter, but we have to start somewhere, and this should give you at least introduce you to the concept of breaking down customer tales into tasks.

    Exercise 3-1: Defining the Tale
    The first thing to happen is that the customer will provide the development team with a tale. A tale is a simple description of a piece of functionality that the system needs to perform. In a full XP environment, the team will play the plotting game. This involves the customer writing a number of tales on cards (usually index cards). Then the development team will place rough time estimates on each tale. The customer then decides which tales to do first. The plotting game provides a long-term view of how the project could pan out eventually, but also includes small-term goals for the next few weeks. By repeating the plotting game every few weeks, the accuracy of the estimates should get better and you enable the customer to choose the direction of the project on a smaller scale. Figure 3-1 shows a sample tale card.
    Figure 3-1. An XP tale card.

    A tale can be considered similar (and are often compared) to a UML Use Case. The tale should not clarify all the details of the functionality. A tale provides a rough thought of the scope. Tales are promises to hold conversations between the developers and the customer. This conversation occurs when the time comes to start implementing the tale. The conversation enables the developers to explore exactly what tasks will have to be carried out to satisfy the customer that the functionality described in the tale is finished.

    The best way to start this is to start a conversation with your customer. Let’s see how our team does it:

    Eddie: What would you like this software to do?

    Chris: I need to be able to show the time in different places in the world on my desktop.

    Pete: You mean you want clocks, one for each place in the world?

    Chris: Yes, but I want to be able to choose which places to show the time for, not just have a clock for every time zone that exists.

    Eddie: Okay, how about we start with simply doing one clock for one time zone and then build the system from there.

    Chris: Um… well, I want to choose the time zone and have multiple clocks.

    Eddie: Yes, I know that, but we want to get some core functionality for you to see as soon as possible, and then we can add to the software from there.

    Chris: Okay, as long as you are aware that we will need more than one clock.

    Eddie: Sure, so what shall we place down as the first tale? How about “Select time zone to show?”

    Chris: Sounds excellent. I also want to be able to place my own mark next to the clock, so if I select GMT, I want to be able to mark it as London.

    Pete: Fine, so the second tale could be “Add custom mark to selected time zone?”

    Chris: Yes that’s right; so what next? I can select a time zone and associate a mark with it, but I need to be able to see the clock. Do you need a tale for showing the clock?

    Eddie: You’re right; how do you want it showed? I assume that just a digital text output is okay? Something like “Time in London is: 14:23.” How does that sound?

    Chris: No, no, no! You’ve misunderstood me! I need to see a clock. You know, with hands and a round face! Like this. (The customer grabs a scrap of paper and scribbles the picture shown in Figure 3-2.)
    Figure 3-2. Customer drawing.

    Pete: Panic! That wasn’t what I was thinking.

    Eddie:Sure, we can do that, but it will take a bit more work.

    Chris:How much work? Doesn’t sound that hard to me.

    Eddie: Well let’s break it down and I’ll tell you how long it will take.

    Chris: I don’t have time for all this; I just want a clock on my screen for different places in the world!

    Eddie: Okay, we’ll get back to you soon with some estimates for timeframes.

    Chris: Fantastic, when?

    Eddie: In the next hour.

    Chris: Oh okay, that’s not so terrible.

    Some of this conversation probably sounds familiar. It is not uncommon for customers (managers) to be small of time and want answers on the spot. As developers, we need to respect that they have other pressures and do what we can to help them. It is vital not to let their stress get to us and force us to make on-the-spot decisions or provide time estimates based on nothing more than numbers plucked out of the air. Notice how Eddie, who has more experience, steers the conversation. Eddie is guiding both Pete and Chris through the process in a way that gives them the best chance of succeeding.

    Exercise 3-2: Breaking Down the Tales into Small Subtasks
    From the preceding conversation, Eddie and Pete can draw the following tale cards:

    Allow the user to select a time zone.

    Allow the user to associate a custom mark with the time zone selected.

    Draw a clock for the time zone and a mark for it.

    From these tales, could you give reasonable time estimates? For the first two, you may be able to get reasonably close (apart from one issue). The third one is a small trickier because the clock has to show the right time and be updated as the time changes. Let’s see what Eddie and Pete come up with when they break these tales down.

    Tale 1: Allow User to Select a Time Zone

    Task
    Estimated Time

    Get a list of time zones from the operating system
    ?

    Test to check selected time zone is valid
    15 minutes

    Test to validate selected time zone is stored in memory
    15 minutes

    Test to validate right behavior when invalid time zone selected
    15 minutes

    User interface to allow user to select a time zone from the list
    10 minutes

    Check code into source control
    5 minutes

    Eddie has place a question mark next to the first task because neither he nor Pete are sure what is involved in getting all the time zones from the operating system. They know the time zones must be there because when they set the Windows clock they can select from a list of available time zones. To find out where this list is stored, they need to carry out some investigation and experimentation.

    In XP terminology, this is called doing a spike or spiking. This spike will be another task. Because they don’t know how long the spike will take, they set an upper limit to the amount of time spent spiking before providing feedback to the customer. Eddie and Pete now have a list of tasks that looks like this:

    Task
    Estimated Time

    Spike to learn how OS stores time zone information
    4 hours

    Get a list of time zones from the operating system
    ? (based on outcome of spike)

    Test to check selected time zone is valid
    10 minutes

    Test to validate selected time zone is stored in memory
    10 minutes

    Test to test behavior when invalid time zone selected
    10 minutes

    User interface to allow user to select a time zone from the list
    10 minutes

    Check code into source control
    5 minutes

    They can now break down the next tale.

    Tale 2: Allow User to Associate a Custom Mark with the Time Zone Selected

    Task
    Estimated Time

    Test to validate right behavior when mark is blank
    10 minutes

    Test to check mark is stored and associated with time zone
    10 minutes

    Test to check mark with non text characters is valid
    10 minutes

    User Interface to allow user to enter mark for selected time zone
    15 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Finally, they can tackle the third tale: Draw a clock for the time zone and a mark for it. Eddie thinks this tale is too huge, so he proposes they break it down into smaller tales:

    3.1 Draw clock face

    3.2 Draw mark next to clock face

    3.3 Draw clock hands

    3.4 Update clock hands to reflect current time in selected time zone

    3.5 As time changes, redraw clock hands to reflect current time in selected time zone

    From these five tales, they can make a set of tasks for which it should be reasonably simple to provide time estimates. The tasks for each tale are estimated as follows.

    Tale 3.1: Draw Clock Face

    Task
    Estimated Time

    Code to draw circle
    15 minutes

    Code to draw 12 marks to indicate time intervals
    15 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Tale 3.2: Draw Mark Next to Clock Face

    Task
    Estimated Time

    Code to calculate offset from clock face to draw mark
    15 minutes

    Code to draw mark
    10 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Tale 3.3: Draw Clock Hands

    Task
    Estimated Time

    Code to get time
    10 minutes

    Code to draw hour hand
    15 minutes

    Code to draw minute hand
    10 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Tale 3.4: Update Clock Hands to Reflect Current Time in Selected Time Zone

    Task
    Estimated Time

    Test converting current time when time zone is in summer time savings
    20 minutes

    Test converting current time when time zone is in standard time
    20 minutes

    Code to draw clock hands based on converted time (dependent on tale 3.3)
    10 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Tale 3.5: As Time Changes, Redraw Clock Hands to Reflect Current Time in Selected Time Zone

    Task
    Estimated Time

    Thread function which updates clock hands based on current time (dependant on tale 3.4)
    20 minutes

    Check code into source control and integrate with existing code
    5 minutes

    Based on this task breakdown, Eddie and Pete can get back to Chris, their customer, with some confidence in the estimated timeframes. The timeframes are still estimates, but the developers are more pleased that they have thought about the job and the tasks to complete. They can also clarify that the first thing they need to do is spend half a day understanding how time zone information is stored in the operating system. When they know how the time zones are stored, they can use them in the program.

    As you can see, the estimated times for each task are small; all of them except the spike are less than 30 minutes. This is a excellent indicator that they have got their tasks to the right level of granularity. If you have several tasks that are four or five hours long, you should reckon harder about how to break them down. For me, the spike task is still cause for concern. After the customer has had time to review the task breakdowns and give the go ahead on the project, I would break down the spike task further. Let’s see how Eddie and Pete go about doing this.

    Exercise 3-3: Breaking Down the Subtasks Even Further
    To break down the spike task, Eddie and Pete need to reckon about the approach to take to find the information they are after. There are some likely candidates to find out how they can access the time zone information:

    .NET Framework support

    Win32 API

    Work out how the date and time Control Panel applet works

    COM controls

    Windows Registry

    Based on the fact they have given themselves 4 hours to come up with some answers, Eddie suggests spending no longer than 45 minutes investigating each area. Because both he and Pete are working on the project, they could each take a different area to investigate. This gives Eddie and Pete a task list for the spiking tasks.

    Spiking Tasks

    Task
    Estimated Time

    Investigate .NET support for time zones
    45 minutes

    Investigate Win32 support for time zones
    45 minutes

    Work out how the date and time Control Panel applet gets it time zone data
    45 minutes

    Investigate whether there are any COM controls that provide access to time zone data
    45 minutes

    Explore the Registry for time zone data
    45 minutes

    If they come to a dead end before 45 minutes, they can stop and go on to the next area of investigation. Likewise, if they find a mechanism that provides access to the time zone data, they don’t need to continue with any of the other spiking tasks.

    Eddie and Pete are now ready to start this project with some very tightly defined tasks and outcomes at the end of each task. This tight definition of tasks enables them to go at a quick and furious pace during the working day.

    Exercises to Help You Toward Genius
    You now know some of the reasoning behind breaking down tales into extremely focused tasks. This section contains some conversations between you and your customer. Read these conversations, and then try to work out the tales and break them down into tasks. At the end of the book (Appendix I), I provide some possible solutions to these exercises; but, they are not definitive answers. When carrying out the task breakdown, there is not one right way to do it, but there are certainly some incorrect ways. Remember to keep each tale adding one piece of functionality and each task doing just one thing. Each exercise should take you no more than an hour to complete.

    Exercise 3-4: The Shopping Cart
    Customer: I need a shopping cart for my Web site.

    You: Okay, what do you need it to do?

    Customer: You know, shopping cart stuff!

    You: I guess you need to add items to the cart?

    Customer: Of course! And take items out

    You: Anything else?

    Customer: Yes, I want to have a running total of the value of items in the user’s cart.

    You: So each user can see his or her own running total?

    Customer: Yep.

    You: Does the system need to remember what’s in my cart the next time I log on?

    Customer: No. I don’t reckon so; they can start again.

    You: Okay, give me an hour and I’ll get you some timeframes and an thought of how we’d go about developing that.

    Exercise 3-5: Derived Stock Market Data
    Stock trader (customer): I want to be able to see a set of derived data for my portfolio.

    You: Where is your portfolio stored?

    Stock trader: I don’t know! It’s in my software somewhere; I reckon it saves a file to my disk.

    You: Okay, and what do you want calculated?

    Stock trader: The open price for the day, the high for the day, the low for the day, the close price for the previous day, and how much I’ve made on that stock.

    You: Hold on. That’s too much for me to do at one time; let’s go through those one by one, first the open price for the day.

    Stock trader: Yes, that’s the first price that the stock gets quoted at after the market opens at 9 a.m.

    You: So, the high for the day is the highest price the stock is quoted at from the time the market opens till it closes?

    Stock trader: Yes, the market closes at 5 p.m.

    You: And the low is the lowest price between open and close?

    Stock trader: Exactly.

    You: The close for the previous day? Is that the price at 5 p.m.?

    Stock trader: Pretty much. It’s the last quoted price before the market closes.

    You: And the last one was how much you’ve made on the stock?

    Stock trader: Yes. My software tells me how much of a stock I’ve got and how much I paid for it, so you can use that information to work out how much I’ve made, or lost, on the stock.

    You: Okay, I’ll have to work out how to get that information from your software.

    Stock trader: Fantastic. Well, now you know what I want, tell me how long will it take and how much it will cost me.

    You: Give me an hour and I’ll get back to you with some estimates.

    Exercise 3-6: What’s the Weather Like?
    Customer: I am running a hot air balloon race around the world and I need to have some way to know what the weather is like in the areas around where the balloons will be.

    You: So you want me to write some software that does weather forecasting?

    Customer: No! That would be a bit expensive, and the race would probably have finished before you get it right!

    You: So what do you want?

    Customer: Well, there’s all this weather information on the Web, and I thought if we could somehow collate it, it would be really useful for me.

    You: You want me to develop a portal site for weather information Web sites around the world?

    Customer: Would that be like a Web page where I could click a map of the world and get a weather report for the location I click?

    You: Yes, we could do that. Do you have a list of sites that we can use to get the weather from?

    Customer: No. I thought you’d know what was best

    You: I’ll place together a list for you to look through. Is there anything else you need it to do?

    Customer: Oh yes, I need to know if there are any severe weather conditions around the world that should be avoided.

    You: So you need a list of typhoons, hurricanes, hailstorms, floods?

    Customer: Yes. I need to be able to see that list at all times; it must be up-to-date.

    You: Okay, let me take all this information away and get back to you with some estimates for delivery times

    Customer: Fantastic, I have to dash; I have a race to run. Call me in an hour with what you have.

    Exercise 3-7: The Unfinished Solution
    Manager (customer): Ah, there you are; I’ve been looking for you.

    You: Why? What do you want?

    Manager: Remember Bob was working on that Mailer program?

    You: Sure, he seemed to be enjoying doing a .NET project.

    Manager: Yes, well he’s been pulled off because he knows everything about the C++ code in the TY project.

    You: And…?

    Manager: I need you to pick up where Bob left off and end the Mailer program.

    You: Okay, can I have a few days with Bob to hand over the project?

    Manager: It’s too late for that. Bob’s already on a plane to HQ to work with the other guys on TY.

    You: Oh… so did Bob have a spec or any Use Cases or tales he was working from?

    Manager: I don’t know. I never saw him write anything down in the entire time I’ve worked with him. That guy is just so smart he remembers everything you tell him.

    You: Fantastic, but I need to know what the software is supposed to do!

    Manager: Okay, cool down. I’ll go through it with you now. It is a program that enables you to collect a group of contacts together with their e-mail addresses and then send one e-mail that goes to all of them but with different bits being only for certain people on the list.

    You: Okay, so do you know how far Bob got?

    Manager: Yes, he had built a way of making a contact, with an e-mail address and a collection of tags, and adding that contact to a collection of contacts. He said it was all stored in an XML file.

    You: That’s a excellent start; sounds like each contact has a profile?

    Manager: That is the thought.

    You: So the next thing to do would be to provide the user with a mechanism to enter an e-mail with tags in it?

    Manager: Yes, and then send the e-mail to each person in the contact collection.

    You: Only sending each person the tags that included contact details in their profile?

    Manager: Yes. How long will that take you to do? Because we need you back on the other project shortly.

    You: Let me get back to you on that.

    Conclusion
    Although this chapter has not focused on anything that is special to .NET, it has introduced you to a technique you should be able to use whenever you are developing software. From the thoughts presented, you have hopefully gained an understanding of why XP is often quoted as being a methodology that requires a large dose of self-discipline. You should also have gained some insight as to the value of working closely with your customers to define exactly what they want.

    A valuable input that I have received when running through these task breakdown exercises in the classroom is that developers often jump straight into breaking down the problem with the thought of coding the entire solution themselves. The more experienced developers tend to do a search on the Web for any existing tools or components that do some (or even all) of the work for them. Then they can reckon about how to break down the rest of the work.

    I hope you can see the importance of some of the key values emerging from the content of this chapter, with communication, feedback, simplicity, and respect all being evident through the dialogues presented. Now you have to find the courage to do it yourself at work.
    I have worked with more than 100 developers in the past two years while consulting with software development teams.

    Chapter 4. Test-Driven Development
    Test-driven development (a.k.a. test-first programming) represents an vital change to the way most programmers reckon about writing code. The practice involves writing a test before each new piece of functionality is coded into the system. The preceding chapter hinted at this, with some of the tasks defined as tests.

    The tests themselves become part of the software. They are written in the same language that the production code is being written in (in this case, C#). This is a new concept for many developers, and they find it hard to go into the mindset of writing test code before they write “production” code. This chapter emphasizes the need to develop high-quality code and guides you through exercises to reinforce the practices. To help you write the tests, you are going to use NUnit, a freely available testing framework for development with the .NET Framework. Before starting with the exercises and writing the tests, first take a step back and reckon about how doing so can help you with your job.

    What Is Your Job?
    This is a question I often question my students. Fascinatingly, nearly everyone responds in the same way: “programmer,” “senior developer,” “project manager,” or “software engineer.” I find this fascinating because these are smart guys, and yet they are telling me the title of their job and not their job. So when I clarify and question them, “Okay, so what do you do in this job,” the answers I generally get are “develop software,” “write code,” and “manage projects.” Sometimes I get answers that pertain to the robustness or quality of the code, and occasionally I have a student answer with “to increase the value of the company I work for.” When you are developing software or any IP (intellectual property) for a company, you are attempting to increase the value of company through your inventions. The IP is an asset for the company, and the reason they hire you is to build the assets. The value of the asset that you are developing depends in part on its quality.

    Is It Possible to Write Bug-Free Code?
    This is another question I like to question, and the response is often “no, of course not” or “not with a serious piece of software.” So my conclusion is that all these programmers who answer in this way write buggy software. With a belief that it is not possible to write bug-free code, they are setting themselves up for poor quality from day one.

    As you learned in Chapter 1, one of the XP practices is playing to win. Playing to win is a mindset. If you play to win, you will believe that it is possible to write bug-free code and will aim for zero-defect solutions. This attitude gives you the edge, but attitude alone will not make bug-free code.

    An fascinating fact about bug-free code is that as the code is further developed, the bug count in it is less likely to increase than in code that is known to have bugs. Developers are more careful to ensure they do not introduce any errors to a solution that is bug free than they are when the solution is riddled with issues. It is what is known as “broken window syndrome.”[1]If a building is in pristine condition, it tends to remain that way; people take better care of it. When one window is broken or a bit of graffiti goes up, but, the building falls into disrepair very rapidly. The same phenomenon exists with code. When code starts to fall into disrepair (has bugs), a typical belief follows that a few more bugs will not make any difference because the code is already broken. Therefore, it is vital to keep the quality of the code high all the way through the process.

    Increase the Quality of Your Code
    To develop zero-defect software, you need some tools and the right way of thinking about quality. XP champions several practices to increase quality. In my opinion, one of the most powerful tools is unit testing; and by developing the tests before writing the solution code, you are “turning the volume up.” [2]Unit testing is not unique to XP, but the proliferation of agile methods, and especially XP, has raised the profile of unit testing in the past few years.

    The Huge Why
    Our eXtreme .NET team is struggling to know why the tests should be written first. The team turns to Eddie, the XP expert.

    Eddie: Test-driven development is really vital, so I want to make sure you know why we are writing code this way

    Sue: Why do we need tests in our code at all?

    Eddie: What is your job? Reckon hard enough about what we’re being paid for here. As a developer, I believe that I should aim to write bug-free code. It is my job to test my code before shipping it, and I know that I can write code that tests my code.

    Pete: Isn’t that the job of the testers?

    Eddie: This is my job, and if you write code, and have any pride in the work you do, then it is your job also. The testers should be there to validate we have written zero-defect code. Any time the testers do find a problem, it is our job to fix that problem and make sure it never happens again. If you don’t believe your job is to ensure the work you do is of the highest possible quality, then I would seriously question your integrity and what you are really doing here at work.

    Pete: Panic!

    Deepak: Why do we have to write test code?

    Eddie: The best way for me as a programmer to validate that a function behaves as I expect is to write some code that tests that function. Writing tests in my code has many advantages for me:

    I am less likely to have the code returned to me from the QA department with some negative comments attached.

    I am more likely to get a excellent response from my customer.

    With tests in my code, I am more confident that any changes I make don’t cause side effects in other parts of the code.

    The tests validate my beliefs in how a piece of code is working. The tests document my theories and beliefs.

    The tests give me confidence in the functionality I am providing.

    I am more pleased to share my code with other developers, knowing that the tests will break if they do something that causes my code to fail.

    Pete: Why not do manual testing?

    Eddie: Manual tests introduce the possibility of human error entering the system, and, if like me, you occasionally get a small bone idle you might be tempted to skip some (or all) of the manual tests. Manual tests are much harder to replicate. To replicate manual tests, we would require some documents with steps to take when carrying out the tests. The documents would quickly become out-of-date as the code changes, and that means more work to keep the documents up-to-date. Finally, manual testing is dull, although we can’t use this as a excellent justification for our manager. Why do something manually when we can write some code to do it for us? We are programmers after all; let’s use our skills for our own benefit!

    Ultimately every piece of software has some aspect of manual testing applied to it in the form of visual checks and validations. Just don’t rely on manual testing to provide anything of value for us on a regular basis.

    Sue: Why write the test code before the “proper” code?

    Eddie: I believe that one word answers most of this question: focus. Writing the test code first helps me to focus on writing the simplest code that will make the tests run. The tests define the pre- and post – conditions of a piece or unit of functionality, and this sets the boundaries for the code to be written.

    Writing the tests first helps to keep the unit of code being written small and testable. It is an obvious side effect that if we write the tests first, the code we write must be testable because we’ve already written the tests for it! If we choose to write the tests afterward, we could easily find that we have units of functionality for which it is hard to write tests. We would then need to break the units down into testable units. This effort is wasted if we can avoid it by writing the tests first.

    Chris: Why doesn’t this whole process cost me more?

    Eddie: In my experience, test-driven development has proven to be cheaper for the customer. The tests ensure a higher level of quality from day one. The largest expense in software development has traditionally been in the maintenance and upgrade stages. The tests embedded in the code reduce each of these costs dramatically. Maintenance becomes simpler. Defect diagnosis is aided by a suite of tests in the system. Fixing bugs is far less likely to cause any ill side effects if none of the tests in the system fail. Making an upgrade to a system that has tests will be simpler because the whole system can be regression tested for changes in functionality.

    This reduction in cost is so large that I believe as more systems get developed that have testing built in to them it will be very hard for other systems to keep up with the pace of change.

    Whole team: Thanks, Eddie.

    Beware The Cheap Customer
    A customer who doesn’t want to pay for testing is a customer who doesn’t want to pay for quality. This doesn’t mean they don’t want it; it just means they don’t want to pay for it! Unless your customer is asking you to knock up a prototype that you will then throw away, you have a customer who wants quality.

    Many years ago, when I was far more naïve, I was running a software company. I had a customer who had a proposal for a very fascinating project. They questioned us to bid for the project, and we place in a proposal to carry out the work. They came back and negotiated the price down, saying they didn’t want to pay for the testing; stupidly, we agreed. We place a clause in the contract saying we didn’t assure any level of quality with the software produced. Over the course of the next six weeks, we knocked out huge quantities of code that basically did the job. We shipped the code to the customer, who promptly turned around and threatened to sue us because the quality was so poor. The software crashed every so often and wasn’t consistently providing the data in a timely manner. We pointed the customer to the clause in the contract and said, “But you didn’t want to pay for testing, so we didn’t do any; of course it might crash!’ After much wasted time and effort, we came to an arrangement where the customer agreed to pay some more for the software to be tested and any bugs fixed.

    Needless to say, I learned my lesson (the hard way): I will never again allow a customer to drop the price and remove testing from the schedule. If they want to drop the price, a customer must drop functionality. I am not prepared to develop buggy code; it costs too much money, time, and effort in the long run.

    Introducing NUnit
    Now that you know the role of test-driven development in producing high-quality code, it is time to get started and place some code together using test-driven development. NUnit is a .NET Framework class library that can locate unit tests that have been written in your project. NUnit comes with a GUI windows application and a console-based application that both enable you to run the tests and see the results. Tests either pass or fail, as indicated by a green or red progress bar, respectively.

    Making a New Project in C# Using NUnit
    NUnit (version 2.2) has been written specifically for testing .NET-based applications and is the class library used in this example. To complete this example yourself, you need Visual Studio.Net and NUnit version 2.2 installed on your machine. NUnit is available from http://www.NUnit.org and is free to use.

    The aim of the exercise is not to produce a fully functional product, but to demonstrate how to write tests first. The project built through this example is a very simple calculator application, one with the functionality to add, subtract, divide, and multiply positive integers. We started this project in Chapter3 by breaking down the tasks. Now it is time to code some of those tasks, writing the tests first.

    Exercise 4-1: Get NUnit Up and Running
    1. Make a new Visual C# project called MiniCalc, using the Windows Application template, as shown in Figure 4-1.

    Figure 4-1. A new C# project.

    [View full size image]

    2. In Solution Explorer, right-click References and select Add Reference.

    3. Select Browse from the dialog box and go to where you have installed NUnit (the bin directory). Select nunit.framework.dll (see Figure 4-2). If you selected the default install directory for NUnit, it will be in the C:\Program Files\NUnit 2.2\bin folder.

    Figure 4-2. Select nunit.framework.dll.

    [View full size image]

    4. Click OK. The nunit.framework will show in your References list (see Figure 4-3).

    Figure 4-3. The nunit.framework in your References list.

    5. Add a class called CalcTests to the project (see Figure 4-4), and place the following code in the class:

    Figure 4-4. Add a class called Calctests.

    [View full size image]

    using System;
    using NUnit.Framework;

    namespace MiniCalc
    {

    [TestFixture]
    public class CalcTests
    {
    [SetUp]
    public void SetUp()
    {
    Console.Out.WriteLine(“SetUp called”);
    }

    [TearDown]
    public void TearDown()
    {
    Console.Out.WriteLine(“TearDown called”);
    }

    [Test] public void TestThatFails()
    {
    Console.Out.WriteLine(“TestThatFails called”);
    Assert.Fail(“This test is supposed to fail!”);
    }

    [Test] public void TestThatSucceeds()
    {
    Console.Out.WriteLine(“TestThatSucceeds called”);
    Assert.IsTrue(right, “This test is supposed to succeed!”);
    }
    }
    }

    6. Build the solution.

    7. Open the NUnit GUI. Choose File > Open from the NUnit menu bar, and browse for the MiniCalc application EXE you just built. You will find it (called MiniCalc.exe) in the bin\debug folder in your project directory.

    8. Click the Run button. Two tests will run, one of which will fail (see Figure 4-5).

    Figure 4-5. The NUnit GUI shows test results.

    [View full size image]

    Consider what we have just done. First, we made a C# project and referenced the core NUnit assembly. This contains the definitions for classes and interfaces to support the NUnit testing framework.

    Then we made a class called CalcTests and decorated this with the TestFixture attribute. A fixture usually consists of methods that are somehow related, often by their functionality or resource requirements. Usually, I write a test fixture for each class I am testing. Classes with the TestFixture attribute will be the building blocks of your testing infrastructure.

    You can see two other vital attributed methods, SetUp and TearDown; these methods will be called directly before and after (respectively) each test method is invoked. In the SetUp method, resources that are required for each of the test methods in the fixture can be initialized. In the TearDown method, they can be cleaned up. The TearDown method will always get called after a test even if the test fails or throws an exception. This is vital because it enables us to clean up and make sure the test will not affect other tests even if it fails.

    Then we really get to make some test methods, albeit rather simple ones for now. The TestThatFails and TestThatSucceeds methods are tests to get us started, and give us something to prove that we have got the framework up and running. We’ll start putting some real test code together in the next exercise. Notice these methods are decorated with the Test attribute, which identifies them to the NUnit framework as NUnit test methods.

    After you have compiled this application, you can run the NUnit GUI and browse for the assembly you have just built (MiniCalc.exe). NUnit GUI then loads that assembly and lists all the types that support the TestFixture attribute. In this example, we only have the one CalcTests class. When you click the Run button, each method in the Fixture will be run, proceeded by the SetUp method and followed by the TearDown method. If you examine the output in the Console Out tab, you can see the order in which these methods are being called. You can also run tests individually by clicking them in the tree view on the left side of the window.

    Exercise 4-2: Write a Test and Add Some Functionality
    In this example, we start to add some functionality to the MiniCalc program, taking you through the process one step at a time so that you get the thought of how to write code, tests first.

    We are going to build a very simple calculator application, with addition, subtraction, multiplication, and division functionality for positive integers. This example is honestly simple but provides some insight into how to go about building tests for your project.

    1. We make a new method in our CalcTests class to test addition. As we write this method, we believe that we should encapsulate all our calculation methods in a class, so we make a Calculator class. Notice that we haven’t really made the class yet; we have just made some calls to use it. What we have done is defined the need for a Calculator class and required that it support the Add method. We have also defined how the Add method is expected to behave under a set of conditions, including an exception we want to have thrown when the method is called illegally.

    This code will not compile because we have not defined the Calculator class or the exception. It is vital to know that when we write code the test-driven way, we do not define the classes or the methods we are going to need until after we have written a test that requires them. (Notice we have introduced a new type of assertion, the Assert.AreEqual method.)
    [Test] public void TestAdd()
    {
    Console.Out.WriteLine(“TestAddition called”);
    Calculator testCalc = new Calculator();
    //test for case of zeros’
    Assert.AreEqual(0, testCalc.Add(0, 0),
    “Adding 0 to 0 should produce 0″);
    //test that param ordering isn’t vital
    Assert.AreEqual(1, testCalc.Add(1, 0),
    “Adding 1 to 0 should produce 1″);
    Assert.AreEqual(1, testCalc.Add(0, 1),
    “Adding 0 to 1 should produce 1″);
    //test for non zero case
    Assert.AreEqual(3, testCalc.Add(1, 2),
    “Adding 1 to 2 should produce 3″);
    int nResult;
    try
    {
    nResult = testCalc.Add(int.MaxValue,
    int.MaxValue);
    Assert.Fail
    (“Should throw a ResultOutofRangeException”);
    }
    catch (ResultOutOfRangeException)
    {
    }

    testCalc = null;
    }

    2. The next step is to build the skeleton code so that our program can compile. We need to define the Calculator class and the exception. First, we add a new class file called Calculator.cs. In this file, we then write the following code to define everything we need for the code to compile. Do not do anything other than make the code compile for now.

    Notice that I have also removed the constructor for the Calculator class. Code that does nothing is useless; so, we stick with the XP value of simplicity and just remove it.
    using System;

    namespace MiniCalc
    {
    public class ResultOutOfRangeException:ApplicationException
    {
    }

    public class Calculator
    {
    public int Add(int a, int b)
    {
    return 0;
    }
    }
    }

    3. In the CalcTests class, we can now remove the TestThatFails and the TestThatSucceeds methods.

    4. You can now compile this program and run it through NUnit again. It compiles, but the test does not succeed. In fact, the first assertion in our TestAdd method does succeed! It is the second assertion that fails. After a test method has a failed assertion, NUnit doesn’t carry on running any of the other code in that method. We are now in an brilliant position to start writing our Add method; we need to work through the method, writing just enough code to make the test pass, and then we are done.

    Seeing the tests fail is part of the process. Sometimes you will find yourself in the fortunate position of writing a test and it passing before you have written any production code. I say “fortunate” because this teaches you that eitherthe system is already doing something you want or that your test is not testing what you reckon it is testing. You are fortunate in that you have learned something.

    5. First we do the simplest thing and add the parameters together and return the result. In the Add method we just made in the Calculator class, change the code as shown here.
    public int Add(int a, int b)
    {
    return a + b;
    }

    6. When we run this using the NUnit GUI, we see that it passes the first four assertions but fails in the try block.

    We now have two choices: We can either change the test code to expect the .NET Framework exception or write some code to make sure we are throwing our own exception. I would lean toward the latter option. We have defined how we want to see the method behave, and there is a reason we defined the method to behave that way. We have defined a contract of behavior between the class and the consumer.

    Therefore, we will change the Add method to reflect how we want it to behave.
    public int Add(int a, int b)
    {
    int result;
    result = a + b;

    if (result < 0)
    {
    ResultOutOfRangeException rangeEx =
    new ResultOutOfRangeException();
    throw rangeEx;
    }
    return result;
    }

    7. Now run the NUnit tests again, and you will see the bar go green. We have written the test and the code to pass the test. We’re done (for this function).

    We have built and tested one piece of functionality, the Add method. Now we want to really call that method from the user interface.

    Exercise 4-3: Plug the Business Logic into the User Interface
    1. Add the user interface as shown in Figure 4-6 to the existing Windows Form in the project.

    Figure 4-6. Add the user interface.
    The controls I have added are as follows:
    Two NumericUpDown controls called NumberA and NumberB

    One mark with the text +

    One button called EqualsButton and the text =

    One mark called Result (showing the 3 in the figure)

    2. Double-click the EqualsButton control to generate the event handler. In this click event, place the following code.
    private void EqualsButton_Click(object sender,
    System.EventArgs e)
    {
    try
    {
    Calculator calc = new Calculator();
    Result.Text =
    (calc.Add((int)NumberA.Value,
    (int)NumberB.Value).ToString());
    }
    catch (ResultOutOfRangeException)
    {
    Result.Text = “Out of Range”;
    }
    }

    Notice how none of the business logic resides inside this method; it just calls the Add method (which has been tested) and places the result on the GUI. Run it and see.

    You may be asking a Why question now. Why do this? Why not just place the code in the button event handler? There are a couple of very excellent reasons: First, it is simpler to test code that is detached from a user interface. Second, it is excellent programming practice to have a thin user interface layer. Suppose, for example, that we want to expose the functionality through a different kind of interface, such as the command line. It is now simple for us to reuse the business logic (addition) in a different interface. Test-driven development is helping us to write better object-oriented code. That has got to be a excellent thing.

    Exercise 4-4: Plug the Business Logic into a Different User Interface
    In this exercise, we expose our functionality through a command-line interface.

    1. Change the code in the Main method of the MiniCalc form to read as follows:
    static void Main()
    {
    int nA, nB;
    string result;
    Console.Out.WriteLine(“Welcome to Mini Calc”);
    Console.Out.WriteLine(“Please enter the first number to add”);
    nA = Convert.ToInt32(Console.In.ReadLine());
    Console.Out.WriteLine(“Please enter the second number to add”);
    nB = Convert.ToInt32(Console.In.ReadLine());
    try
    {
    Calculator calc = new Calculator();
    result = (calc.Add(nA, nB)).ToString();
    }
    catch (ResultOutOfRangeException)
    {
    result = “Out of Range”;
    }
    Console.Out.WriteLine(result);
    }

    2. Change the project properties. (Right-click the project in Solution Explorer.) Set the Output Type to be a Console Application.

    3. Rebuild the project and run it from the command line. You have now reused the fully tested business logic of the Add method in a different user interface.

    When developing software using tests, one of the rules is this: If you can reckon of a way of breaking it, write a test to prove that you can break it. Then write the code to make the test pass. At this stage, you can probably reckon of a few ways of breaking this code. But, the one that we explore here is the fact that we can add negative numbers in our Add method, even though the requirement was for a very simple calculator application with addition, subtraction, multiplication, and division functionality for positive integers. Let’s now write a test that breaks it.

    Exercise 4-5: Write a Test to Fix a Bug
    1. In the CalcTests class, add a method called TestAddNegatives.
    [Test] public void TestAddNegatives()
    {
    Console.Out.WriteLine(“TestAddNegatives called”);
    Calculator testCalc = new Calculator();
    int nResult;

    try
    {
    nResult = testCalc.Add(-1, 0);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException )
    { }

    try
    {
    nResult = testCalc.Add(0, -1);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    try
    {
    nResult =
    testCalc.Add(int.MinValue, int.MinValue);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    testCalc = null;
    }

    2. Notice that we have added a new exception type, so the code will not compile. Remember we must have a class or method used in a test before we define it. This keeps the code as simple as possible. To make the code compile, we need to make that exception type in the Calculator class file.
    public class NegativeParameterException:ApplicationException
    {
    }

    3. Now the code will compile, and you can run the tests in NUnit GUI again. The test should fail, as expected. (If you are following along with these exercises, make sure you do run the tests; it is excellent practice.) Now we can set about writing the code to fix it. Note: It’s running the tests that is the excellent practice, not the tests themselves (well, the tests are part of it).
    public int Add(int a, int b)
    {
    int result;
    if (a < 0 || b < 0 )
    {
    NegativeParameterException npEx =
    new NegativeParameterException();
    throw npEx;
    }

    result = a + b;

    if (result < 0)
    {
    ResultOutOfRangeException rangeEx =
    new ResultOutOfRangeException();
    throw rangeEx;
    }
    return result;
    }

    4. Compile the program and run the tests again. When you see the bar go green, we’re done. We spotted a way to break it, we wrote a test to prove we could break it, and then we fixed the code so that the tests all run.

    Really, but, we are not quite finished here yet; we now have some duplicate code in our tests. We can take out the creation of the Calculator object that is shared in both the tests and place it in the SetUp method. We can do the same with the freeing of the object in the TearDown method. After this small change, your CalcTests class should appear something like this.
    [TestFixture]
    public class CalcTests
    {
    private Calculator testCalc;
    private int nResult;

    [SetUp]
    public void SetUp()
    {
    Console.Out.WriteLine(“SetUp called”);
    testCalc = new Calculator();
    }

    [TearDown]
    public void TearDown()
    {
    Console.Out.WriteLine(“TearDown called”);
    testCalc = null;
    }

    [Test] public void TestAdd()
    {
    Console.Out.WriteLine(“TestAddition called”);
    //test for case of zeros’
    Assert.AreEqual(0, testCalc.Add(0, 0),
    “Adding 0 to 0 should produce 0″);
    //test that param ordering isn’t vital
    Assert.AreEqual(1, testCalc.Add(1, 0),
    “Adding 1 to 0 should produce 1″);
    Assert.AreEqual(1, testCalc.Add(0, 1),
    “Adding 0 to 1 should produce 1″);
    //test for non zero case
    Assert.AreEqual(3, testCalc.Add(1, 2),
    “Adding 1 to 2 should produce 3″);
    try
    {
    nResult = testCalc.Add(int.MaxValue,
    int.MaxValue);
    Assert.Fail
    (“Should throw a ResultOutofRangeException”);
    }
    catch (ResultOutOfRangeException)
    {
    }
    }

    [Test] public void TestAddNegatives()
    {
    Console.Out.WriteLine(“TestAddNegatives called”);

    try
    {
    nResult = testCalc.Add(-1, 0);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException )
    { }

    try
    {
    nResult = testCalc.Add(0, -1);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    try
    {
    nResult =
    testCalc.Add(int.MinValue, int.MinValue);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    }
    }

    Now we are ready to expand the functionality and add subtraction to the system, so the first thing to write is, you guessed it, a test for the (as yet unwritten) Subtract method.

    Exercise 4-6: Write a Test and Then Add Another Function
    1. Add a new method to the CalcTests class called TestSubtract.
    [Test] public void TestSubtract()
    {
    Assert.AreEqual(0, testCalc.Subtract(0, 0),
    “Subtracting 0 from 0 should produce 0″);
    Assert.AreEqual(1, testCalc.Subtract(0, 1),
    “Subtracting 0 from 1 should produce 1″);

    try
    {
    nResult = testCalc.Subtract(1, 0);
    Assert.Fail(
    “Subtracting 1 from 0 should throw a ResultOutofRangeException”);
    }
    catch (ResultOutOfRangeException)
    { }

    Assert.AreEqual(0,
    testCalc.Subtract(int.MaxValue, int.MaxValue),
    “Subtracting max value from max value should produce 0″);

    try
    {
    nResult = testCalc.Subtract(-1, 0);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    try
    {
    nResult = testCalc.Subtract(0, -1);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }

    try
    {
    nResult = testCalc.Subtract(int.MinValue,
    int.MinValue);
    Assert.Fail(
    “Should throw a NegativeParameterException”);
    }
    catch (NegativeParameterException)
    { }
    }

    2. Again we have written code that will not compile; we need to add a skeleton method to the Calculator class.
    public int Subtract(int numberToSubtract,
    int subtractFrom )
    {
    return 0;
    }

    3. Now we can compile the code and run the tests. As expected, the bar goes red, indicating that the TestSubtract method has failed. We are in the position of knowing that if we write just enough code to make this test pass, we can declare we’re done.
    public int Subtract(int numberToSubtract,
    int subtractFrom )
    {
    int result;
    if (subtractFrom < 0 || numberToSubtract < 0 )
    {
    NegativeParameterException npEx =
    new NegativeParameterException();
    throw npEx;
    }

    result = subtractFrom – numberToSubtract;
    if (result < 0)
    {
    ResultOutOfRangeException rangeEx =
    new ResultOutOfRangeException();
    throw rangeEx;
    }
    return result;
    }

    4. Compile the program and run the tests through NUnit again. They should all pass.

    If you are being observant, at this point you should notice there is some more duplicate code. The check for negative parameters occurs at the top of both the Add and Subtract methods. This can be extracted out into its own method.

    Exercise 4-7: Write a Test and Then Extract the Method
    1. Before we can just change the code, we should write a test so that we can validate that the functionality we have extracted does what we want it to do. Therefore, in the CalcTests class, add a method called TestCheckForNegativeNumbers.
    [Test] public void TestCheckForNegativeNumbers()
    {
    try
    {
    testCalc.CheckForNegativeNumbers(0, 0);
    }
    catch (NegativeParameterException)
    {
    Assert.Fail(“Zeros are not negative numbers”);
    }

    try
    {
    testCalc.CheckForNegativeNumbers(1, 1);
    }
    catch (NegativeParameterException)
    {
    Assert.Fail(“1′s are not negative numbers”);
    }

    try
    {
    testCalc.CheckForNegativeNumbers(
    int.MaxValue, int.MaxValue);
    }
    catch (NegativeParameterException)
    {
    Assert.Fail(“Max Vals are not negative numbers”);
    }

    try
    {
    testCalc.CheckForNegativeNumbers(-1, -1);
    Assert.Fail(“-1′s are negative numbers”);
    }
    catch (NegativeParameterException)
    { }

    try
    {
    testCalc.CheckForNegativeNumbers(
    int.MinValue, int.MinValue);
    Assert.Fail(“Min Vals are negative numbers”);
    }
    catch (NegativeParameterException)
    { }
    }

    2. Again we have defined a function name and declared its behavior before we have written a line of code for that function. So the next thing to do is write a skeleton for that function in the Calculator class.
    public void CheckForNegativeNumbers (int a, int b)
    { }

    3. Now you can compile and run the tests again. The test we just wrote should fail, as expected. So we need to fill in the CheckForNegativeNumbers method. We have the code for this already in the other two methods, so we should be able to copy and paste[3] it from the Add method into the new method.
    public void CheckForNegativeNumbers (int a, int b)
    {
    if (a < 0 || b < 0 )
    {
    NegativeParameterException npEx =
    new NegativeParameterException();
    throw npEx;
    }
    }

    4. Recompile the program and run the tests again; they should all pass this time. Now you can confidently replace the duplicated code in the Add and Subtract methods with a call to a method that you know has been tested. So the Add method will change from this:
    public int Add(int a, int b)
    {
    int result;

    if (a < 0 || b < 0 )
    {
    NegativeParameterException npEx =
    new NegativeParameterException();
    throw npEx;
    }
    .
    .
    .
    }
    To this:
    public int Add(int a, int b)
    {
    int result;

    CheckForNegativeNumbers (a, b);
    .
    .
    .
    }

    5. After you have replaced the code with a call to the new CheckForNegative Numbers method, compile and run the tests again to ensure that we have not broken any of our tested functionality in the Add and Subtract methods.

    Exercise 4-8: Add the UI for Subtraction
    1. All that’s left to do now is hook up the UI to the Subtract method. First, make sure the project settings are changed back to build a Windows application and the main method is changed back to call the Application.Run method with a new instance of the form. To allow both addition and subtraction, you can modify the form to include radio buttons to enable the user to choose what type of calculation to do (see Figure 4-7). Name the radio buttons AddRButton and SubtractRButton.

    Figure 4-7. Add radio buttons.

    2. You can then change the code in the Equals button click event to accommodate this.
    private void EqualsButton_Click(object sender,
    System.EventArgs e)
    {
    try
    {
    Calculator calc = new Calculator();
    if (AddRButton.Checked)
    {
    Result.Text =
    (calc.Add((int)NumberA.Value,
    (int)NumberB.Value).ToString());
    }
    else
    {
    Result.Text =
    (calc.Subtract((int)NumberB.Value,
    (int)NumberA.Value).ToString());
    }
    }
    catch (ResultOutOfRangeException)
    {
    Result.Text = “Out of Range”;

    }
    catch (NegativeParameterException)
    {
    Result.Text = “Negatives not allowed”;
    }
    }

    3. Compile the program and run it. You should be able to add and subtract positive integers. Remember that we have to place the project properties back to compile this as a Windows application, and you’ll need to change the Main method back to make and run the form.
    static void Main()
    {
    Application.Run(new Form1());
    }
    Also note that because the minimum value of the NumericUpDown controls is zero, you cannot really enter an invalid negative number. If you want to test this, you need to change the minimum value property of the controls.

    We are not quite finished yet. The GUI layer is starting to get a bit “smelly[4]“; there is functionality that might break and that is not tested. This functionality can be taken out of the GUI layer and into the Calculator class.

    Exercise 4-9: Extract Functionality Out of the UI Layer
    1. Let’s start by factoring out the choice of which type of calculation to perform. If we make a method in the Calculator to perform more than one type of calculation, we need to somehow define which calculation to do, addition or subtraction. This seems like a excellent case for introducing an enumerated type. We’ll start by building the test for this new method.
    [Test]
    public void TestCalculate()
    {
    Assert.AreEqual(2,
    testCalc.Calculate(1, CalcOperation.Add, 1),
    “Adding 1 to 1 failed”);
    Assert.AreEqual(0,
    testCalc.Calculate(1, CalcOperation.Subtract, 1),
    “Subtracting 1 from 1 failed”);
    }

    2. Again, this won’t compile. We need to place some skeleton code in the Calculator class file. Starting with the new enumerated type we have introduced, make this in the Calculator.s file but outside of the class.
    public enum CalcOperation
    {
    Add = 0,
    Subtract = 1,
    }
    Then add the framework for the Calculate function in the Calculator class.
    public int Calculate(int a, CalcOperation op, int b)
    {
    return 0;
    }

    3. Now we can compile and run the tests in NUnit. You can see the output provided by the Assert.AreEqual statement when it fails.

    4. Next we can go the logic for the Calculate function from the GUI layer.
    public int Calculate(int a, CalcOperation op, int b)
    {
    int nResult = 0;
    if (CalcOperation.eAdd == op)
    {
    nResult = Add(a, b);
    }
    else if (CalcOperation.eSubtract == op)
    {
    nResult = Subtract(b, a);
    }
    return nResult;
    }

    5. Compile and run the tests. They should pass. Now we can call this method from the UI.
    private void EqualsButton_Click(object sender,
    System.EventArgs e)
    {
    try
    {
    Calculator calc = new Calculator();
    CalcOperation op = new CalcOperation();
    if (AddRButton.Checked)
    {
    op = CalcOperation.Add;
    }
    else
    {
    op = CalcOperation.Subtract;
    }
    Result.Text = calc.Calculate((int)NumberA.Value,
    op, (int)NumberB.Value).ToString();
    }
    catch (ResultOutOfRangeException)
    {
    Result.Text = “Out of Range”;
    }
    catch (NegativeParameterException)
    {
    Result.Text = “Negatives not allowed”;
    }
    }

    6. You can simplify this further by changing the operation to be performed in the radio button handlers. To do this, you must make the local CalcOperation type a member of the Form class.
    private CalcOperation op = CalcOperation.Add;
    Then you must add new methods to handle the radio buttons being clicked.
    private void AddRButton_CheckedChanged(object sender,
    System.EventArgs e)
    {
    if (AddRButton.Checked)
    {
    op = CalcOperation.Add;
    }
    }
    private void SubtractRButton_CheckedChanged(object sender,
    System.EventArgs e)
    {
    if (SubtractRButton.Checked)
    {
    op = CalcOperation.Subtract;
    }
    }
    Finally, you can further simplify the handler method for the Equals button.
    private void EqualsButton_Click(object sender,
    System.EventArgs e)
    {
    try
    {
    Calculator calc = new Calculator();
    Result.Text = calc.Calculate((int)NumberA.Value,
    op, (int)NumberB.Value).ToString();
    }
    catch (ResultOutOfRangeException)
    {
    Result.Text = “Out of Range”;
    }
    catch (NegativeParameterException)
    {
    Result.Text = “Negatives not allowed”;
    }
    }

    In this set of exercises, we have started from scratch building a project using test-driven development principles. By now, you should know that there is a cycle to this kind of development:

    1. Choose what unit of functionality you are going to build (design); this could also be fixing a bug.

    2. Write some test code.

    3. Write skeleton code to allow a compile.

    4. Compile and run the tests. (They should fail.)

    5. Fill in the skeleton with enough code to pass the tests.

    6. Compile and run the tests. If the tests fail, go back to Step 5.

    7. Simplify the code where possible; this may involve Steps 1 through 6 again.

    8. You’re done. Take a break and start again!

    Each step in the cycle is simple to do, and at the end of the cycle you should have added one unit of functionality (or fixed one bug) that has tests that pass. You can then go on with programming other units of functionality with more confidence.

    How Do You Feel About TDD?
    For the next exercise, we are going to build the same program twice. First, we are going to build the program without doing any tests, and then we are going to build the same program writing the tests first. We will then see how we feel about each program.

    We are going to write some code to calculate some derived data from stock price data that is passed to our code. We are going to write a class library to encapsulate the calculations for other developers to use.

    The library has to take a collection of prices and timestamps for a stock price and return the high and low prices for a given date. The collection is in the form of a HashTable containing DateTime objects mapping to double values to represent timestamps mapping to prices.

    Exercise 4-10: Without Tests
    I provide the skeleton for you, and then you can end the exercise. This exercise should not take more than 30 minutes to complete.

    1. Start by making a new C# project using the class library template called NoTests.

    2. Change the name of the class that is made for you from Class1.cs to CalcClass.cs.

    3. In the CalcClass.cs file, change the code to read as follows.
    using System;
    using System.Collections.Specialized;
    namespace NoTests
    {
    public class CalcClass
    {
    public void CalcHighLow(Hashtable DatePriceList,
    DateTime day, ref decimal high, ref decimal low)
    {
    }
    }
    }

    4. Now write the code to calculate the high and low values, but do not write any tests! Excellent luck.

    Exercise 4-11: With Tests
    We are now going to do the same project again, this time by writing tests first. I will get you started, and then you can end the exercise yourself. This exercise should not take you more than 30 minutes to complete.

    1. Make a new C# project using the class library template called WithTests.

    2. Rename the generated class file from Class1.cs to CalcClass.cs.

    3. Change the code in the CalcClass.cs file to read as follows.
    using System;

    namespace CsWithTests
    {
    public class CalcClass
    {
    }
    }

    4. Add a reference to the Nunit.Framework.dll file.

    5. Add a new class called CalcTests.

    6. In the CalcTests class, enter the following code.
    using System;
    using System.Collections;
    using NUnit.Framework;
    namespace CsWithTests
    {
    [TestFixture]
    public class CalcTests
    {
    [Test]
    public void TestCalcHighLow()
    {
    Hashtable datePriceList;
    DateTime day;
    Decimal high;
    Decimal low;
    CalcClass calc;

    //calc.CalcHighLow(datePriceList, day, high, low);
    }
    }
    }

    7. Now you can fill in the test code yourself and then build the CalcHighLow function in the CalcClass function to make sure the tests pass. Excellent luck!

    Confidence Test
    How do you feel after completing the last two exercises? Which class library are you more confident is right?

    If you have built meaningful tests, you should feel very confident with the second library. Even if you do not believe you have place much effort into the tests in the second exercise, the very fact that you have some means of validating your code should give you some extra level of certainty.

    Visual Studio.NET 2005 Team System
    The next version of Visual Studio.NET will be available in several flavors. A group of these flavors is called Visual Studio.NET 2005 Team System. This group is aimed at the enterprise development community. Two of the products in this group will include an integrated unit-testing framework. This framework will be similar to NUnit. The two products that include the unit testing will be Visual Studio Team Developer and Visual Studio Team Tester. The beta of Visual Studio 2005 Team System indicates that the attributes you have learned in NUnit will differ slightly:

    TestFixture is called TestClass.

    Test is called TestMethod.

    SetUp is called TestInitialize.

    TearDown is called TestCleanup.

    The lessons you have learned in this chapter will all still hold right. It will be simple to go from NUnit to the unit-testing system in Visual Studio.NET Team System.

    The current plans indicate that the unit-testing tools will not be shipped with other versions of Visual Studio.NET 2005. Testing is a cornerstone of the XP practices. Testing is vital to all the practices in this book. Is Microsoft making a mistake by not shipping unit-testing tools with all the versions of Visual Studio?

    Conclusion
    This chapter has introduced you to test-driven development, which is without a doubt one of the most vital practices of XP. These tests underpin many of the practices in XP, such as refactoring, small releases, continuous integration, pair programming, and collective ownership.

    The tests were intended to increase your confidence in the code you are writing. If you follow the test-driven development methodology and are a member of a team of developers who are all writing tests, you will have more confidence in their code, and they will have more confidence in your code. The outcome of this is that you can now go forward more quickly and tackle problems more aggressively.

    You should now see the reason this practice is called test-driven development. The tests are driving the development process. By writing the tests first, you should find your focus on the code you are writing changes substantially. Your goal now is to define how the class will be used with a test method and then to get the tests to pass. You will learn about more testing techniques later in the book.

    This chapter simplified the code in several places. The next chapter explores the practice of refactoring. Refactoring provides techniques for simplifying code.
    Gladwell, Malcolm. The Tipping Point. Boston, Massachusetts: Back Bay Books, 2002.

    “Turning the volume up” means taking something that works well and making it work even better.

    Copy and paste is often referred to as editor inheritance by parts of the developer community.

    A code smell is a term used in XP to define code that has something amiss. XP teams will call code smelly when it can be improved.

    Chapter 5. Refactoring
    Like test-driven development, refactoring is a mindset that can be best achieved by doing it and understanding what has been gained from the process. Martin Fowler’s book, Refactoring: Improving the Design of Existing Code (Addison-Wesley, 1999), is the most complete resource to date, and I have no interest in competing with it. This chapter instead presents scenarios in which refactoring the code leads to a dramatic improvement in the readability, lowers the cost of change, and increases the quality of the code produced. These scenarios take the form of step-by-step exercises.

    What Is Refactoring
    Refactoring is changing the structure of existing code without changing the behavior of that code. A refactoring (noun) is one particular (usually small) well-defined change that is made to the structure of the code. When developers are refactoring (verb) code, they are applying one or more refactorings (noun) to their code; they are making one or more changes to the code’s structure.

    The changes are made to the code to improve the design, with the aim of making the code simpler to read, simpler to know, and cheaper to change. In Chapter 4, we simplified the code and removed code duplication several times. We were refactoring the code.

    Do It As You Go
    In XP, refactoring is done after each new piece of functionality is added to the system. The aim is to write the tests, write the code to get the tests running, and then simplify the code by refactoring. This cycle of activities is then repeated over and over again for each new function added to the system. By carrying out this constant refactoring, the changes made each time will be small and few, and so they should also be simple to do.

    The Importance of Tests
    If you are not working in an XP environment, you can still reap some benefits from using refactoring, but I strongly recommend you do this only if you have tests in place. The tests will validate that when you carry out refactorings you have not changed the behavior of the software. The tests are your safety net.

    The Benefits
    It is vital to know the benefits that you should expect to see from performing refactoring on your code as you develop it. Refactoring is certainly no “silver bullet,” but Martin Fowler describes refactoring as “a pair of silver pliers that helps you get a excellent grip on your code.”

    Refactoring is an vital tool for all programmers to have in their toolboxes. There will always be certain points in any software project where the structure of the code needs to be changed, and the refactoring tool can be used for this.

    By continually refactoring and using the test-code-refactor approach to developing code, you will see patterns[1] emerge in the code. This enables you (the developer) to work with these emerging patterns and further improve the structure of your code.

    Always being on the look out for changes that will improve the structure of your code will force you to be reviewing the code. By constantly reviewing the code, you will be getting a deeper understanding of how the code works and what it is doing. Without knowing the code, it is much harder to refactor it.

    Let’s look at how refactoring works with the XP values we discussed in Chapter 1.

    Feedback
    The ability to refactor your code takes the pressure off the design phase of software development. Formal methods (such as waterfall) advocate developing a perfect design before any code is written. In the real world, perfect design upfront is impossible because during the implementation of the code you will learn lessons that affect the design.

    Refactoring enables you to change the design of the code at a later stage. This means that you do not have to get the design absolutely right before you write any code. You can get a rough design worked out, code it up, and then if (when) you spot a better design you can refactor your code toward the better design.

    Refactoring enables you to get started on the coding earlier than you might have been able to otherwise. Getting started earlier enables you to get feedback on the progress from other coders and even customers at an earlier time. This feedback is valuable because it might force you to rethink the original design. The earlier you rethink designs, the higher your chances are of getting the final result that the customer wants.

    Communication
    Some of the refactorings we will do in this chapter do nothing more than improve the readability of the code. The benefit in the small term is that other programmers will find it simpler to work with the code. In the medium to long term, more-readable code is simpler to know and therefore simpler to maintain.

    Simplicity
    By simplifying your code through refactoring, you get the immediate benefit to the development team of having less to know. This in turn improves the quality of the code. Bugs often result because of misunderstanding existing code and writing code that causes existing code to break.

    Some More Huge “Why” Questions
    Our eXtreme .NET team has gathered together again to question Eddie about refactoring.

    Sue: Why not just get it right the first time?

    Eddie: It is very rare for any piece of software to be developed “right the first time.” I should qualify that by adding that every programmer I have ever spoken to has said that if given a second opportunity to code a solution they would do it differently. I have met a few arrogant individuals who claim they are so smart they always code the right solution the first time. Personally, I don’t believe they can always be right, and even if they are, they are in a very small minority. Most of us need all the help we can get to ensure we get a excellent piece of software written. Refactoring is some of that help; it allows us to admit that we are less than perfect and provides us with a tool to enable us to work toward perfection over time.

    Deepak: Why not just start again if you know it’s incorrect?

    Pete: Yeah! If we know we will always do a better job the second time around, why don’t we build a throwaway prototype and then start again when we have learned the lessons to be gained from this?

    Eddie: There are development methods that use this approach, and they appear to work well because the developers can make mistakes in the first version and learn from these mistakes. The problem in my mind is this: Where is the cutoff point? At what stage should we stop prototyping and start building the real application? There are always lessons to be learned as we develop a system.

    Chris: If you have the time to build the entire system first and then throw it away and start again, then you are in an enviable position. We are not in that position!

    Eddie: Right, most of us developers are working under tight time constraints, and we need some way to incorporate the lessons we are learning back into the code being developed. Refactoring is a mechanism that allows this constant learning to be fed back into improving the software. The prototyping approach doesn’t scale when adding new feature to an existing system; it is not feasible to recode the entire solution every time a new feature has to be added. Refactoring allows existing software to be scaled and enhanced over time.

    Pete: Why can’t I just refactor at the end of the project?

    Eddie: So, we can do larger code “tidy ups” at the end of the project or large periods of coding, but we will lose the benefits to be gained by constantly refactoring. I am not sure I would call this refactoring either. Refactoring is making small changes through the project. By constantly refactoring, we are making the next piece of work we do potentially simpler. We will also see patterns emerge more rapidly, and we can then work with those patterns to make the code simpler to know.

    Deepak: Why does this help me develop more robust code?

    Eddie: Refactoring forces us to review the code we have written and look for ways to simplify it. The very fact that we are reviewing the code is a excellent starting point for increasing the quality of our software. It has been shown time and time again that code reviews are valuable for improving the code quality. Many of the refactoring techniques that you will learn have been developed because they do enforce robustness in the code. For example, one refactoring replaces an enumerated type with an object hierarchy. This introduces a level of type safety not previously present in the code.

    Time to Tidy Your Code
    In the early 1990s, I was working on a software project in C; at the end of each deliverable (usually every month), I would spend a few days “tidying up my code.” My boss was not overjoyed by this, but I was so insistent about it being vital that he let me carry on; he was a smart boss! The tidying up meant that I could get the code into better shape for building the next deliverable, and I have no doubt that helped the project succeed. This tidying up was really a huge refactoring exercise. I could see patterns in the software that needed to be improved so the next stage would be simpler to develop. Although I insisted on spending three or four days doing this refactoring, I really didn’t like it much. It is dull to spend four days moving code around and not get any new functionality into the system. I did it because, like cleaning the car windows, I wanted to see where I was going more clearly. By doing constant refactoring at the end of each test-code cycle, I was spreading the boredom out into smaller chunks of refactoring throughout the development process.

    Why Should I Do It When No One Else Does?
    This is not a question that has much to do with refactoring but more to do with team dynamics; but, with refactoring, the question comes up more often than other techniques because developers believe they are spending time refactoring “other peoples’ code,” and see this as unfair. A common weep I hear is this: “Why can’t they refactor their own code?”

    My opinion is that when you are working as part of a team, the goal is for the team to succeed, not individuals. If this means I spend more of my time refactoring “other people’s code” than they do and that refactoring is making the system simpler to develop and maintain, then I am adding value to the team. If I ignore code that would be better refactored, I am doing hurt to the team. Ideally, the whole team will be refactoring their code. If they are not, but, I still want to add as much value to the team as I possibly can, so I refactor code even when those around me don’t.

    Why Do Something That Doesn’t Add Any New Features to the Code?
    All the answers I have given to the previous questions contribute to answer this one question. Refactoring does not add any new features to the code, but it is very valuable to the longevity of the code. If I had finished working on a piece of software, it was tested and ready to ship, and I knew there was no more work to do on the code; I would not refactor it. A metaphor I like to use is that refactoring is like doing exercises for your code. To function well and get a sense of well being, humans need to exercise and stretch their bodies. Code is similar; if you want your code to live for a long time, it’s excellent to exercise it, and refactoring is a workout for your code. After refactoring your code, it is in better shape and ready to take on the challenges presented in the future.

    Let’s Start Refactoring
    Hopefully by now you can see there are some benefits to giving your code the refactoring workout. So how do you go about doing it? Let’s get started with an exercise to introduce some basic thoughts about refactoring.

    Exercise 5-1: Currency Converter Refactoring
    For this exercise to be both achievable and printable within the size constraints of this book, the example is reasonably small. If this were the entire piece of software, it is highly unlikely you would refactor it. It is also unlikely you would get paid anything for building it! The application is a simple currency converter that works with conversion rates that are purely the wishes of an Englishman who spends much of his time in Australia and the United States. We will start with the existing Currency Converter application and take some steps to refactor the code. You can download the source code for this application from http://eXtreme.NET.Roodyn.com/BookExercises.aspx.

    After we have done the refactoring, the code will be in better shape for us to add new functionality, such as increasing the number of currencies. The refactoring steps each contain one or two well-defined refactoring techniques. The names of these techniques have come from Martin Fowler’s Refactoring book.

    Step One: Extract Method
    1. Open the Currency Converter solution in Visual Studio.

    2. Examine the code and the form. Notice that it is a very simple program with a basic form. Things to notice include the following:
    All the functionality occurs in the form code.

    There are no tests.

    There is not much else to it!

    3. First we need some tests. We cannot refactor without validating we have not changed behavior. This presents a dilemma: There are no tests to start with, so how do we know we are not refactoring a bug? Also all the code is tightly tied into the GUI; this makes it hard to test and write tests for. Should we go the code away from the GUI first, or should we attempt to write some clever tests to test the code in the GUI layer? As with many real-world scenarios, we are going to compromise. We will write tests for the code we are going to extract from the GUI layer. Then we will get the tests to pass as we go the code. First we need to add a reference to NUnit in the References section, so right-click References, select Add Reference, and browse for the Nunit.Framework.dll file.

    4. We will make a test fixture class to hold our tests. Right-click the project and select Add / Add Class from the pop-up menu. We will name this class ConvertTests.cs.

    5. Edit the class code so that it uses the Nunit.Framework namespace, and add the TestFixture attribute to the class.
    using System;
    using NUnit.Framework;

    namespace CurrencyConverterCS
    {

    [TestFixture]
    public class ConvertTests
    {
    }
    }

    6. Now we can start writing some tests. The first test will be a breadth test that enables us to start refactoring some functionality with the confidence that we haven’t broken anything.
    [Test]
    public void ConversionBreadth()
    {
    decimal result;
    decimal amount;
    CurrencyType fromCur;
    CurrencyType toCur;

    amount = 100.0M;
    fromCur = CurrencyType.US;
    toCur = CurrencyType.US;
    result = MainForm.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “US to US should be no change”);

    fromCur = CurrencyType.UK;
    toCur = CurrencyType.UK;
    result = MainForm.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “UK to UK should be no change”);

    fromCur = CurrencyType.AUS;
    toCur = CurrencyType.AUS;
    result = MainForm.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “AUS to AUS should be no change”);

    decimal expected;
    fromCur = CurrencyType.US;
    toCur = CurrencyType.AUS;
    result = MainForm.CurrencyConvert(amount,
    fromCur, toCur);
    expected = amount * 2;
    Assert.AreEqual(expected, result,
    “US to AUS is incorrect”);

    fromCur = CurrencyType.UK;
    toCur = CurrencyType.AUS;
    result = MainForm.CurrencyConvert(amount,
    fromCur, toCur);
    expected = amount / 0.5M * 2;
    Assert.AreEqual(expected, result,
    “UK to AUS is incorrect”);
    }

    7. As you have probably worked out, this won’t compile. We have added a new enumerated type called CurrencyType and are calling a method on the MainForm that doesn’t exist. We need to go back to the MainForm and make these. In the MainForm above the class, we add the CurrencyType enum.
    public enum CurrencyType
    {
    US,
    AUS,
    UK,
    }

    8. Next we add the CurrencyConvert method to the MainForm code. We need to make it static or shared so that it can be accessed from the test code. This isn’t ideal, but we can work on refactoring away from that later.
    public static decimal CurrencyConvert(decimal amount,
    CurrencyType fromCur, CurrencyType toCur)
    {

    return 0;
    }

    9. Now you can compile and run the test. It will fail because the method has no body. We need to go the body from the button click.
    public static decimal CurrencyConvert(decimal amount,
    CurrencyType fromCur, CurrencyType toCur)
    {
    decimal converted = 0.0M;
    decimal initial = 0.0M;

    initial = amount;
    converted = initial;

    if (fromCur == CurrencyType.UK)
    {
    converted = initial / UKInUS;
    }
    else if(fromCur == CurrencyType.AUS)
    {
    converted = initial / AusInUS;
    }

    if (toCur == CurrencyType.UK)
    {
    converted = converted * UKInUS;
    }
    else if(toCur == CurrencyType.AUS)
    {
    converted = converted * AusInUS;
    }

    return converted;
    }

    10. This will not compile because the UKInUS and AusInUS variables are not static, so we need to change the declaration of these, too.
    private static decimal AusInUS = 2;
    private static decimal UKInUS = 0.5M;

    11. Now compile and run the test in the NUnit GUI (or console if you prefer); the test should pass.

    12. We can now call this new method from the button click event.
    private void ConvertButton_Click
    (object sender, System.EventArgs e)
    {
    decimal converted = 0.0M;
    decimal initial = 0.0M;

    CurrencyType fromCur = CurrencyType.US;
    CurrencyType toCur = CurrencyType.US;

    initial = Convert.ToDecimal(Amount.Text);

    if (FromUK.Checked)
    {
    fromCur = CurrencyType.UK;
    }
    else if (FromAUS.Checked)
    {
    fromCur = CurrencyType.AUS;
    }

    if (ToUK.Checked)
    {
    toCur = CurrencyType.UK;
    }
    else if (ToAus.Checked)
    {
    toCur = CurrencyType.AUS;
    }

    converted = CurrencyConvert(initial, fromCur, toCur);

    Result.Text = converted.ToString();

    }

    You can see that we now have more code than before, and in fact it appears less obvious. This often happens in the early stages of a refactoring session. Don’t be worried of this. If you have an thought of where you want to go, you reckon at first that you are going in the incorrect direction. Have the courage that you are going to get somewhere that is much better in the end, but, and you will find you can get there most of the time. Occasionally, you will be incorrect, and then you need to have the courage to admit defeat and throw your changes away. Just do it.

    Step Two: Extract Class
    At this point, I am looking at the code and thinking that the CurrencyType should be encapsulated in a class that has the conversion routines as methods. To go in this direction, we must make a new class called ConvertibleCurrency. Do this from the right-click pop-up menu in Solution Explorer, as we did before.

    1. Before we get started on the code in the new class, we will define some behaviors of the class in a test. This documents what we are expecting the class to do. Back in the ConvertTests class, we add a new method:
    [Test]
    public void ConvertTo()
    {
    ConvertibleCurrency currency;
    decimal result;
    decimal expected;

    currency = new ConvertibleCurrency(
    CurrencyType.US, 100.0M);

    result = currency.ConvertTo(CurrencyType.US);
    Assert.AreEqual(100.0M, result,
    “US to US should be no change”);

    currency = new ConvertibleCurrency(
    CurrencyType.AUS, 100.0M);
    result = currency.ConvertTo(CurrencyType.UK);
    expected = 100.0M / 2 * 0.5M;
    Assert.AreEqual(expected, result,
    “AUS to UK incorrect result”);
    }

    2. We have now defined the constructor of the new class and one method, so let’s add those to the class.
    public ConvertibleCurrency(CurrencyType type, decimal val)
    {
    }

    public decimal ConvertTo(CurrencyType type)
    {
    decimal converted = 0.0M;
    return converted;
    }

    3. Compile and run the tests; the latest test will (as expected) fail. We need to implement the constructor and go the code from the MainForm static method into the class.
    public class ConvertibleCurrency
    {
    private decimal amount;
    private CurrencyType currency;

    public ConvertibleCurrency(CurrencyType type, decimal val)
    {
    currency = type;
    amount = val;
    }

    public decimal ConvertTo(CurrencyType type)
    {
    decimal converted = amount;

    if (currency == CurrencyType.UK)
    {
    converted = converted / UKInUS;
    }
    else if(currency == CurrencyType.AUS)
    {
    converted = converted / AusInUS;
    }

    if (type == CurrencyType.UK)
    {
    converted = converted * UKInUS;
    }
    else if(type == CurrencyType.AUS)
    {
    converted = converted * AusInUS;
    }

    return converted;
    }
    }

    4. The code will not compile yet because the UKInUS and AusInUS variables cannot be reached from this class; they need to be went into the class, but they no longer need to be static.
    private decimal AusInUS = 2;
    private decimal UKInUS = 0.5M;

    5. Now compile and run the tests; they should pass. We are now ready to use this class from the MainForm code.

    6. Change the CurrencyConvert method in the MainForm as follows.
    public static decimal CurrencyConvert(decimal amount,
    CurrencyType fromCur, CurrencyType toCur)
    {
    decimal converted = 0.0M;

    ConvertibleCurrency currency =
    new ConvertibleCurrency(fromCur, amount);
    converted = currency.ConvertTo(toCur);

    return converted;
    }

    7. You can also delete the UKInUS and AusInUS variables from the MainForm code. These variables are now declared and used in the ConvertibleCurrency class.

    8. Now would also be a excellent time to go the CurrencyType enum declaration into the ConvertibleCurrency class file.

    9. Compile the project and run the tests. The tests should pass, and the program should still function as before. We have encapsulated the behavior of the currency converter into a class and reduced the functionality in the GUI. This helps with testing and with porting the program to another user interface such as the Web.

    Step Three: Go Method and Extract Method
    Before we end with the GUI layer, we can go the static CurrencyConvert method from the MainForm to the ConvertibleCurrency class. This is a more sensible place for this method because it deals with the ConvertibleCurrency class.

    Cut and paste the method into the class and compile the project. You should get some build errorssix to be precise. Five are in the test class for calls to the MainForm method we just went, and the sixth one is in MainForm where the call to the method was made.

    The method we went is still static, so we need to prefix it with the class name ConvertibleCurrency in these six places.

    I often use the compiler in this way to detect the places I have broken code when I go a method or change a name. The compiler is far better at finding all the places the change has effected than I am!

    1. Now compile and run the tests again; they should pass. The program should still function as before.

    2. We can now turn our attention to the code in the ConvertibleCurrency class. The if-else blocks of code that convert the amount to U.S. dollars and then to the currency requested look like excellent candidates for extraction. We’ll start by taking the block that converts the amount to U.S. dollars and make a method called ConvertToUS.
    private decimal ConvertToUS()
    {
    decimal converted = 0.0M;
    converted = amount;

    if (currency == CurrencyType.UK)
    {
    converted = converted / UKInUS;
    }
    else if (currency == CurrencyType.AUS)
    {
    converted = converted / AusInUS;
    }

    return converted;
    }
    Then replace the code in the ConvertTo function so it looks like this:
    public decimal ConvertTo(CurrencyType type)
    {
    decimal converted = ConvertToUS();

    if (type == CurrencyType.UK)
    {
    converted = converted * UKInUS;
    }
    else if(type == CurrencyType.AUS)
    {
    converted = converted * AusInUS;
    }

    return converted;
    }
    Compile and run the tests to validate we haven’t broken anything.

    3. We can do the same with the second if-else block by making a function called ConvertFromUS.
    private decimal ConvertFromUS(CurrencyType type,
    decimal USAmount)
    {
    decimal converted = 0.0M;

    converted = USAmount;

    if (type == CurrencyType.UK)
    {
    converted = converted * UKInUS;
    }
    else if (type == CurrencyType.AUS)
    {
    converted = converted * AusInUS;
    }

    return converted;
    }

    4. Again we need to change the code in the ConvertTo method so that it calls this new method.
    public decimal ConvertTo(CurrencyType type)
    {
    decimal converted = ConvertToUS();

    converted = ConvertFromUS(type, converted);

    return converted;
    }

    5. Compile and run the tests. The fact they work shows us we haven’t made any changes to the functionality, even though we have changed the structure of the code in a honestly huge way.

    Step Four: Replace Type Code with State/Strategy and Replace Conditional with Polymorphism
    We are now in a far stronger position to change the structure of the code further and remove some more “terrible smells”[2] from the code. There are two areas of the code that are smelly: the enumerated type and the if-else blocks. Fascinatingly, the enumerated type and if-else code are related. The fact they are related makes the smell even fouler!

    1. We will start by using Replace Type Code with State/Strategy. The CurrencyType enumerated type can be replaced with a simple object hierarchy. We’ll start by coding the hierarchy.
    public abstract class BaseCurrency
    {
    public abstract decimal InUS
    {
    get;
    }
    }

    public class USCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 1; }
    }
    }

    public class UKCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 0.5M; }
    }
    }

    public class AUSCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 2; }
    }
    }

    2. Check it compiles and the tests still run. They should because we haven’t yet touched any of the code being called. We will do this now by replacing the use of the enumerated type in the CovertibleCurrency class with the class types we have just made.
    public class ConvertibleCurrency
    {
    private decimal amount;
    private BaseCurrency currency;

    public static decimal CurrencyConvert(decimal amount,
    BaseCurrency fromCur, BaseCurrency toCur)
    {
    decimal converted = 0.0M;

    ConvertibleCurrency currency =
    new ConvertibleCurrency(fromCur, amount);
    converted = currency.ConvertTo(toCur);

    return converted;
    }

    public ConvertibleCurrency(BaseCurrency type, decimal val)
    {
    currency = type;
    amount = val;
    }

    public decimal ConvertTo(BaseCurrency type)
    {
    decimal converted = ConvertToUS();

    converted = ConvertFromUS(type, converted);

    return converted;
    }

    private decimal ConvertToUS()
    {
    decimal converted = 0.0M;

    converted = amount / currency.InUS;

    return converted;
    }

    private decimal ConvertFromUS(BaseCurrency type,
    decimal USAmount)
    {
    decimal converted = 0.0M;

    converted = USAmount * type.InUS;

    return converted;
    }
    }

    3. Pay careful attention to what has changed in the ConvertibleCurrency class. The if-else statements have disappeared through the use of the hierarchy. The replacement of the enumerated type with a hierarchy has enforced a better code base. The two member variables AusInUS and UKInUS are no longer needed; they have also been deleted.


    If we now compile this project, we should find all the places that call the class that also need to be changed; this will be in the MainForm and in the tests. The tests are an area of the code where we need to tread especially carefully. Changing the test code could cause us to inadvertently break one of the tests. The methods in the test code should now read as follows.
    [Test]
    public void ConversionBreadth()
    {
    decimal result;
    decimal amount;
    BaseCurrency fromCur;
    BaseCurrency toCur;

    amount = 100.0M;
    fromCur = new USCurrency();
    toCur = new USCurrency();
    result = ConvertibleCurrency.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “US to US should be no change”);

    fromCur = new UKCurrency();
    toCur = new UKCurrency();
    result = ConvertibleCurrency.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “UK to UK should be no change”);

    fromCur = new AUSCurrency();
    toCur = new AUSCurrency();
    result = ConvertibleCurrency.CurrencyConvert(amount,
    fromCur, toCur);
    Assert.AreEqual(100.0M, result,
    “AUS to AUS should be no change”);

    decimal expected;
    fromCur = new USCurrency();
    toCur = new AUSCurrency();
    result = ConvertibleCurrency.CurrencyConvert(amount,
    fromCur, toCur);
    expected = amount * 2;
    Assert.AreEqual(expected, result,
    “US to AUS is incorrect”);

    fromCur = new UKCurrency();
    toCur = new AUSCurrency();
    result = ConvertibleCurrency.CurrencyConvert(amount,
    fromCur, toCur);
    expected = amount / 0.5M * 2;
    Assert.AreEqual(expected, result,
    “UK to AUS is incorrect”);
    }

    [Test]
    public void ConvertTo()
    {
    ConvertibleCurrency currency;
    decimal result;
    decimal expected;

    currency = new ConvertibleCurrency(
    new USCurrency(), 100.0M);

    result = currency.ConvertTo(new USCurrency());
    Assert.AreEqual(100.0M, result,
    “US to US should be no change”);

    currency = new ConvertibleCurrency(
    new AUSCurrency(), 100.0M);
    result = currency.ConvertTo(new UKCurrency());
    expected = 100.0M / 2 * 0.5M;
    Assert.AreEqual(expected, result,
    “AUS to UK incorrect result”);
    }

    4. In the MainForm code, the button click code should now look like this.
    private void ConvertButton_Click
    (object sender, System.EventArgs e)
    {
    decimal converted = 0.0M;
    decimal initial = 0.0M;

    BaseCurrency fromCur;
    BaseCurrency toCur;

    initial = Convert.ToDecimal(Amount.Text);

    if (FromUK.Checked)
    {
    fromCur = new UKCurrency();
    }
    else if (FromAUS.Checked)
    {
    fromCur = new AUSCurrency();
    }
    else
    {
    fromCur = new USCurrency();
    }

    if (ToUK.Checked)
    {
    toCur = new UKCurrency();
    }
    else if (ToAus.Checked)
    {
    toCur = new AUSCurrency();
    }
    else
    {
    toCur = new USCurrency();
    }

    converted = ConvertibleCurrency.CurrencyConvert(
    initial, fromCur, toCur);

    Result.Text = converted.ToString();

    }

    5. Notice that we have really added an extra else condition to the if-else block. The fact that we have replaced the enum with a hierarchy means we no longer can have a default value; this is forcing our code to be more type safe. This lack of type safety might have been the cause of a bug in a later stage, but we have prevented this bug from being born.

    6. Compile and run the tests. We should be back to a working state and ready to go forward to the last step.

    Step Five: Replace Conditional with Polymorphism
    1. Because we are now confident that we do not need the enumerated type anymore, we can delete it from the code. But, there is still a small whiff in the MainForm code. Although we’ve eliminated the if-else blocks of code in the ConvertibleCurrency class, they still linger in the button click method. To remove them, we can use the same hierarchy we have already made. We can also take advantage of a feature of the .NET Framework; if you bind a list of objects to a list box or a combo box, the box will show each object using its ToString method. We will therefore override the ToString method in our concrete currency type classes.
    public class USCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 1; }
    }
    public override string ToString()
    {
    return “US$”;
    }
    }

    public class UKCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 0.5M; }
    }
    public override string ToString()
    {
    return “UK£”;
    }
    }

    public class AUSCurrency : BaseCurrency
    {
    public override decimal InUS
    {
    get{ return 2; }
    }
    public override string ToString()
    {
    return “AU$”;
    }
    }

    2. Return to the MainForm in the design view and replace the From and To radio button groups with combo boxes (called fromCombo and toCombo), as shown in Figure 5-1.

    Figure 5-1. Replace radio buttons with combo boxes.

    3. Double-click the form to generate the MainForm_Load method. In here we will make a list of the concrete currency types and bind them to the combo boxes.
    private void MainForm_Load(object sender, System.EventArgs e)
    {
    ArrayList currencyList = new ArrayList();
    currencyList.Add(new UKCurrency());
    currencyList.Add(new USCurrency());
    currencyList.Add(new AUSCurrency());

    fromCombo.DataSource = currencyList;
    toCombo.DataSource = currencyList.Clone();
    }

    4. In the button click event, we now need to get the selected object from the combo boxes.
    private void ConvertButton_Click
    (object sender, System.EventArgs e)
    {
    decimal converted = 0.0M;
    decimal initial = 0.0M;

    BaseCurrency fromCur;
    BaseCurrency toCur;

    initial = Convert.ToDecimal(Amount.Text);

    fromCur = fromCombo.SelectedItem as BaseCurrency;
    toCur = toCombo.SelectedItem as BaseCurrency;

    converted = ConvertibleCurrency.CurrencyConvert(initial,
    fromCur, toCur);

    Result.Text = converted.ToString();
    }

    5. Compile and run the tests, and then do some manual testing to verify you have now made a working piece of software.

    Step Six: Customize
    I leave it to you to now explore what else you can do with this code. Some thoughts for you are as follows:

    Make an ASP.NET Web interface for the code.

    Add another set of currencies to the application.

    Collect the currency exchange rates from an XML file.

    When Not to Refactor
    Now that you are all excited about refactoring, you probably want to go and look at some other code and start doing some refactoring. First some words of warning:

    Do not refactor code that is not going to change. You will be wasting your time. If you know the code is working and doesn’t need a bug fix or enhancement, leave it alone.

    Learn when to stop refactoring. It takes practice, but be aware you only want to refactor enough to make the code simple to know and maintainable. The code doesn’t have to be a thing of beauty; it is far better if it works and you can deliver your solution quickly.

    Refactoring is not an excuse to hide the fact that you reckon someone else’s code is rubbish and so you need to rewrite it. I have seen people who rewrite other people’s code because they don’t like it and call this “refactoring.” It is not refactoring. The fact this is happening indicates you have a larger problem with your development team that needs to be addressed. Don’t hide behind refactoring.

    Tools for Refactoring
    You have manually done the refactoring in this chapter. You have had to cut and paste code, make new methods, and change structures. You can download tools that will help you to achieve this. Refactory from Xtreme Simplicity is the best one I have tried. Refactory plugs into Visual Studio and provides a menu item with a selection of refactorings.

    Visual Studio .NET 2005 is going to include refactoring tools within the IDE. You will be able to highlight code from a method and then click an Extract Method menu item. The extract method refactor will be done for you. The refactors supported in the Visual Studio.NET 2005 beta are as follows:

    Extract Method

    Rename

    Encapsulate Field

    Extract Interface

    Promote Local Variable to Parameter

    Remove Parameters

    Reorder Parameters

    Generate Method Stub

    Add Using Unbound Type

    You will find two aspects of the Visual Studio.NET 2005 refactoring tool extremely innovative. First, each time you perform a refactor, the tool brings up a preview window that shows you the changes about to be made in the code. Second, the refactoring tool enables you to perform a refactor across multiple projects in the same solution.

    Like all excellent developer tools, this will make our lives as developers better. We will be able to refactor code more easily. And like all excellent developer tools, it will work best when you know exactly what the tool is doing. I suggest you learn to refactor your code manually to start with. After you have learned the skill of refactoring, the tools will become very powerful in your hands.

    Conclusion
    This chapter provided you with some hands-on experience with refactoring and clarified how you can develop your code using the test-code-refactor cycle. I strongly recommend reading Refactoring by Martin Fowler; though the examples are in Java, don’t let that scare you from seeing how they would apply to C#.

    If you are the only one on your team doing refactoring, it will be hard at first, but don’t try to force others to see the wisdom of your ways; instead, let them learn by seeing the results you produce. If they reckon you are wasting your time, that is fine, too. Many people reckon I am wasting my time going to the gym three days a week or getting up early for a run on the beach. I know I am doing some excellent for myself and for the excellent of my team, and that is enough. They will see that the code that has been refactored has more flexibility and is simpler to work with. Your code will be fitter than code that has not been refactored.
    Gamma, Erich, Richard Helm, Ralph Johnson, & John Vlissides. Design Patterns. Reading, Massachusetts: Addison-Wesley Professional, 1995.

    Fowler, Martin. Refactoring. Reading, Massachusetts: Addison-Wesley Professional, 1999. In this book, Fowler describes code that has something amiss as having a terrible smell.

    Chapter 6. Spiking
    Experimentation is a fundamental part of research. To know and validate how something works, we experiment with it. Spiking is the XP term given to research and experimentation. Spiking provides a way to learn more information about a specific part of the project.

    This chapter guides you through carrying out some spikes (research) on technologies that you have not encountered. After you have spiked an area of technology, you have a much better understanding of what it will take to develop software using that technology. This understanding will enable you to more effectively break down tales into tasks and make more accurate time estimates for those tasks.

    You Can’t Know Everything
    The vast amount of information available about even something as focused as just the .NET Framework means that it is nearly impossible to know everything about it. Most of us don’t just concentrate on one area of work. XP development environments do much to discourage specialization.

    If you specialize in a particular field, you are potentially damaging both your career and the business you are working with. The specialization takes your focus away from seeing the larger picture, which is harmful to both you and your business. There is no point in knowing everything about how to optimize databases if the core business needs of the software are not being met. If the data is stored in a way that does not provide simple access to valuable information for people in the company, it matters not how well its storage is optimized.

    What is vital is knowing how to get that information when you need it. Spiking is the tool that will help you get that information when you need it.

    Raise Your Confidence
    By having a rough understanding of how a technology works, you can boost your confidence in that area by doing some experimentation. You don’t want to build the entire system or develop a fully working prototype. It is more vital to drive a thin vertical wedge of understanding through the area of concern. This is where the term spike comes from; it is a thin vertical slice of information.

    When you are experimenting, focus on understanding one specific thing, not a whole host of things. That way you can focus on solving one problem and not become distracted. Set a goal that is achievable in a relatively small time period. If you are trying to know a complex technology, use your task breakdown skills. Break down the problem into a collection of smaller problems. As mentioned in Chapter 3, I like to aim for something that I believe is achievable within a four-hour timeframe. If a problem takes longer than this to solve, I realize I have bitten off more than I can chew. I need to take a step back and break down the problem.

    In each spiking session, I attempt to build a prototype that I will be pleased to throw away. The point is not to build a piece of software from these sessions, but to gain an understanding that I can apply to the software system being developed.

    Let’s Learn Something
    Let’s rejoin our eXtreme .NET team to see how they are learning about spiking.

    Sue: What are we going to do about the task to get a list of time zones from the operating system?

    Deepak: Yes, I was hoping to find a component that did that for us. I searched on Google for something to help us.

    Pete: Cool thought! What did you find?

    Deepak: Nothing.

    Pete: Panic!

    Eddie: Looks like we’ll have to work this one out for ourselves. Time for a spike; anyone really want to do this?

    Deepak: Hold on. First we need to know what operating system we want the information for.

    Sue: Windows!

    Pete: Yeah, Windows. Doh!

    Deepak: You are assuming every version of Windows works the same way? I know that is not right from previous problems I’ve solved that are like this one.

    Pete: Panic!

    Eddie: Wow! Okay. Chris? What version of Windows does this need to run on?

    Chris: Ninety percent of our customers are running Windows XP.

    Eddie: Okay, let’s change the spike task to get a list of time zones from Windows XP.

    Deepak: That makes me pleased.

    Eddie: Excellent; who wants to do this spike?

    Dr. Neil and you: We’ll do it!

    Exercise 6-1: Spiking How Time Zone Data Works in Windows
    In this exercise, we are going to investigate how we can use time zone information in our application. In Chapter 3 we encountered this as a task we couldn’t accurately estimate. We didn’t know enough about how time zones are stored to give an accurate estimate. We need to know how to access the time zone data from the operating system. Then we need to work out how to use this information to get the time in different places in the world. With this knowledge, we can go back to our team with some firmer estimates about how long this task will take to develop.

    The first place to look is the classes that ship as part of the .NET Framework. If there is support for time zone data there, our lives will be made much simpler.

    1. Open up the help file and look up the .NET Framework DateTime structure.

    Unfortunately the only time zonerelated functionality provided is to convert local times to time in UTC (formally GMT; don’t question me why this was changed!) and back again. This just works using the local time zone that the machine is currently running in. As the documentation states:

    This method assumes that the current DateTime holds the local time value, and not a UTC time. Therefore, each time it is run, the current method performs the necessary modifications on the DateTime to derive the UTC time, whether the current DateTime holds the local time or not.

    This method always uses the local time zone when making calculations. (Source: MSDN library)

    2. Within the System namespace, there is a TimeZone class; let’s see whether that is useful for us.

    All the documentation has to say about it is this:

    A time zone is a geographical region in which the same standard time is used. (Source: MSDN library)

    Not very verbose, but it sounds as though it might be promising.

    If you examine the methods, you will learn that the constructor is protected, and the only way to make an instance of this class is to use the static property CurrentTimeZone. This is not very useful if we want to get the time zone information for different time zones.

    (As another exercise, you can try to build a test application using the Time-Zone type and see whether you can get time zone for some other part of the world.)

    3. Our next stop is to see what the Win32 API provides in terms of time zone functionality. A couple of functions look fascinating: GetTimeZoneInformation and SetTimeZoneInformation. They both work with a TIME_ZONE_INFORMATION structure, which contains all the data that we need to build our application; for a given time zone, the fields in the structure are as shown in the following table.
    Time Zone Fields

    Field
    Description

    Bias
    The offset from UTC in minutes

    Standard Name
    The name of standard time on this machine in this time zone

    Standard Date
    The date and time that daylight savings moves over to standard time

    Standard Bias
    The additional difference from UTC during standard time (usually zero)

    DaylightName
    The name of daylight savings time on this machine in this time zone

    DaylightDate
    The date and time of the transition from standard time to daylight savings time

    DaylightBias
    The additional difference from UTC during daylight savings time (usually60)

    This looks promising, but the methods only enable you to get or set the time zone on the local machine and retrieve time zone information about the time zone set on the local machine.

    We are still stumped. We want to get time zone information for all the available time zones in the world. We figure it must be possible because the Control Panel extension that you use to set the Date and Time does it in the Time Zone tab.

    4. That is the next place for us to look. If we could work out how the timedate.cpl (basically a DLL) worked, we could emulate that and get all the time zone information for around the world. So, first, we can look to see whether it exposes any form of interface (COM or .NET). You can try to open it using OLE View or ildasm, but no luck there; it supports neither a COM interface nor does it contain CLR header information.

    5. Back to basics, open the CPL in Visual Studio as a resource to examine whether there are any clues in there. Maybe the time zone information might have been stored in the DLL (maybe in a string table).

    Nope.

    The only thing left we can reckon of is to open up the timedate.cpl file in a hex editor. (Yuck, I haven’t poked around inside Windows system files for a while; surely there’s a excellent reason for that!)

    We start this stage of the investigation by examining the DLLs that the code uses, all the usual suspects: KERNEL32, NTDLL.DLL, USER32.dll, COMCTL32.dll, ole32.dll, SHELL32.dll, GDI32.dll, ADVAPI32.dll, IMM32.dll and SHLWAPI.dll. Nothing of use here.

    So carry on looking through the file for any other obvious clues; maybe the time zone data is hard coded in the DLL. Again no.

    So where did the time zone information get stored? How about the Registry? Look for any references to Registry paths in the CPL file; you should find a few. The first ones lead to information about time synchronization via a timeserver and then some Registry entries for storing the current time zone settings for the local machine. Then about halfway down the file you can find a reference to the Registry key: Software\Microsoft\Windows NT\CurrentVersion\Time Zones.

    Eureka!

    6. This key contains a subkey for each time zone that is listed in the combo box in the second tab of the timedate.cpl. The data in each of the subkeys has to provide all the data required to build a TIME_ZONE_INFORMATION structure so that the application can set the time zone for the system. Now we just have work out how the data is formatted.
    Registry Information for Each Time Zone

    Value
    Meaning

    Show
    Extra information about the time zone for show purposes

    Dlt
    DaylightName; the name of daylight savings time on this machine

    Index
    Unknown

    MapID
    Presumably used for placing on the bitmap of the world in the CPL

    Std
    StandardName; the name of standard time on this machine

    TZI
    All the other data we need to fill a TIME_ZONE_INFORMATION structure

    7. The string data is reasonably clear, as shown in the preceding table; we just need to work out how the byte data in the TZI (Time Zone Information) is stored. We start off by going back to the documentation on the structure, from which we can draw up the following table. So adding up the numbers, we are looking for 44 bytes of information, and the TZI value in the Registry is exactly 44 bytes long. Therefore, we must assume that we have all the data we need in the byte array. All we need to do is figure out which byte means what!
    Break Down of Time Zone Information

    Data Type
    Name
    Description
    Bytes

    LONG
    Bias
    In minutes
    4

    SYSTEMTIME
    StandardDate
    Month, day of week and day only
    16

    LONG
    StandardBias
    Mostly 0 (minutes)
    4

    SYSTEMTIME
    DaylightDate
    Month, day of week and day only
    16

    LONG
    DaylightBias
    Mostly 60 (minutes)
    4

    8. On your own, write a program that decodes the byte data in the TZI fields in the Registry, and try to work out how the time zone information data is stored in the TZI field. The best thing to do would be to write some tests that validate how we believe the time zone data is stored. We can run those tests when the OS changes and check whether the way time zone data is stored has changed.

    You should have deduced the data was stored in the following order: Bias, Standard Bias, Daylight Bias, Standard Date, and Daylight Date. Okay, now we are ready to place together some code to use this information.

    Below are some functions written in C# that use the time zone information from the Registry.

    9. To populate a list with the available time zones, a static method on a class is shown first. It is static because it requires no instance data to be functional.
    public static string[] GetTimeZones()
    {
    RegistryKey regKey = Registry.LocalMachine;
    regKey = regKey.OpenSubKey(
    @”SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\”);
    return regKey.GetSubKeyNames();
    }

    GetTimeZones Function
    After a time zone has been selected, you must get the time zone information for the place selected. The next set of code demonstrates this.

    1. Open the Registry key for the time zone provided.

    2. Read in the TZI value to a byte array.

    3. Use some helper functions to extract the data out of the byte array and into the member variables of the PlaceTime object.

    The helper functions MakeUShort and MakeInt are equivalent to the traditional Windows MAKEWORD and MAKELONG macros. Remember that a Long in .NET world is 64 bits and not 32 bits as it was in the ancient Win32 world. GetValueFromBytes builds a 32-bit integer value from an array of bytes, using an offset from the beginning of the array at which to start “stripping” the bytes.

    protected void GetTimeZoneInfo(string strTimeZone)
    {
    RegistryKey regKey = Registry.LocalMachine;
    regKey = regKey.OpenSubKey(
    @”SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\” +
    strTimeZone);
    System.Byte[] tziData = (Byte[])regKey.GetValue(“TZI”);

    m_nBias = GetValueFromBytes(tziData, 0);
    m_nStandardBias = GetValueFromBytes(tziData, 4);
    m_nDaylightBias = GetValueFromBytes(tziData, 8);

    m_StandardDate = GetDateTimeFromBytes(tziData, 12);
    m_DaylightDate = GetDateTimeFromBytes(tziData, 28);
    }
    private static ushort MakeUShort(byte low, byte high)
    {
    return (ushort) (low | (high<< 8));
    }

    private static int MakeInt(ushort low, ushort high)
    {
    return (int) (low | (high<< 16));
    }

    private static int GetValueFromBytes(byte[] data, int offset)
    {
    int nResult = 0;
    ushort lowWord = MakeUShort(data[offset],data[offset+1]);
    ushort highWord = MakeUShort(data[offset+2],data[offset+3]);
    nResult = MakeInt( lowWord, highWord );
    return nResult;
    }

    private static DateTime GetDateTimeFromBytes(byte[] data, int offset)
    {

    DateTime dateTime = DateTime.UtcNow;

    int Year = MakeUShort(data[offset],data[offset+1]);
    int Month = MakeUShort(data[offset+2],data[offset+3]);
    DayOfWeek DayofWeek =
    (DayOfWeek)MakeUShort(data[offset+4],data[offset+5]);
    int Day = MakeUShort(data[offset+6],data[offset+7]);
    int Hour = MakeUShort(data[offset+8],data[offset+9]);
    int Minute = MakeUShort(data[offset+10],data[offset+11]);
    int Second = MakeUShort(data[offset+12],data[offset+13]);
    int Milliseconds = MakeUShort(data[offset+14],data[offset+15]);

    dateTime = dateTime.AddMonths(Month – dateTime.Month);
    dateTime = dateTime.AddDays(1-dateTime.Day);
    dateTime = dateTime.AddHours(Hour – dateTime.Hour);
    dateTime = dateTime.AddMinutes(Minute – dateTime.Minute);
    dateTime = dateTime.AddSeconds(Second – dateTime.Second );
    dateTime = dateTime.AddMilliseconds(Milliseconds
    dateTime.Millisecond );
    bool bFoundDay = fake;
    int nCoveredRequiredDay = 0;
    while (dateTime.Month == Month)
    {
    if (dateTime.DayOfWeek == DayofWeek)
    {
    nCoveredRequiredDay +=1;
    if (nCoveredRequiredDay == Day)
    {
    bFoundDay = right;
    break;
    }
    }
    dateTime = dateTime.AddDays(1);
    }
    while(!bFoundDay)
    {
    dateTime = dateTime.AddDays(-1);
    if (dateTime.DayOfWeek == DayofWeek)
    {
    bFoundDay = right;
    }
    }
    return dateTime;
    }

    GetTimeZoneInfo and Related Functions
    The final helper function, GetDateTimeFromBytes, builds a .NET Framework Date-Time structure from the byte array passed in, starting at the offset provided. This is the more complicated of the methods here and requires some extra explanation.

    The TZI byte array contains 2 sets of 16 bytes, which correspond to a Win32 SYSTEMTIME structure. These SYSTEMTIMEs contain the data for the Standard Date and Daylight Date in the TIME_ZONE_INFORMATION structure. The standard and daylight dates represent the date and time at which the transition occurs from daylight savings to standard time and back again.

    The TIME_ZONE_INFORMATION structures contain the month, the day of the week (for example, Sunday), the day on which the transition occurs, along with the time. The day can be a value between 1 and 5. If the month is 4, the day is 1, and the day of the week is 0 (Sunday), that would represent the first Sunday in April. If the day value is 5, that always means the last of that day in the month. If the month is 9, the day is 5, and the day of the week is 6, which represents the last Saturday in September.

    The GetDateTimeFromBytes function sets the DateTime structure to the first day of the month given and walks through the month until it finds the right day of the transition. If the method fails to do this, it assumes (perilous, I know) that we want the last occurrence of that day of the week in the month and starts walking backward through the month until it finds that day. I have no doubt this could be greatly optimized, but I leave that as another exercise for you!

    Encode the Knowledge in Tests
    As previously mentioned, putting your newly found knowledge into tests is a fantastic way to capture the knowledge you have gained. The tests not only document your findings for other developers to read, they also ensure the knowledge is still valid and not out-of-date. It is sometimes hard to write the tests when you do not know what you are testing, so spiking is often carried out without tests being written first. This is not always the case, as Ron Jeffries shows us in his book Extreme Programming Adventures in C# (Microsoft Press, 2004). In the book, Ron carries out spikes purely with tests.

    It is not a hard-and-quick rule, and I personally find I can be more playful and creative if I can muck around with thoughts in code without the concern of testing. I can write the tests after I know the technology being researched.

    Let’s place our newly gained knowledge of how the time zones are stored into a test fixture. Notice that we are testing the helper methods that build the values out of the byte arrays. These helper methods will likely be extracted into a real class when we come to use the time zone information in our project. Having tests for them means that the refactoring exercise that will happen when we need those methods can be done with much more confidence.

    using System;
    using Microsoft.Win32;
    using NUnit.Framework;

    [TestFixture]
    public class TimeZoneTests
    {
    [Test]
    public void TestRegistryKey()
    {
    RegistryKey regKey = Registry.LocalMachine;
    regKey = regKey.OpenSubKey(@”SOFTWARE\Microsoft\Windows NT\CurrentVer-
    sion\Time Zones\”);
    Assert.IsNotNull(regKey, “Invalid registry key”);
    }

    [Test]
    public void TestMakeUShort()
    {
    ushort testVal = MakeUShort(0, 0);
    Assert.AreEqual(0,testVal);

    testVal = MakeUShort(1, 0);
    Assert.AreEqual(1,testVal);

    testVal = MakeUShort(byte.MaxValue, 0);
    Assert.AreEqual(byte.MaxValue,testVal);

    testVal = MakeUShort(0, 1);
    Assert.AreEqual(byte.MaxValue+1,testVal);

    testVal = MakeUShort(byte.MaxValue, byte.MaxValue);
    Assert.AreEqual(ushort.MaxValue,testVal);
    }

    [Test]
    public void TestMakeInt()
    {
    int testVal = MakeInt(0, 0);
    Assert.AreEqual(0,testVal);

    testVal = MakeInt(1, 0);
    Assert.AreEqual(1,testVal);

    testVal = MakeInt(ushort.MaxValue, 0);
    Assert.AreEqual(ushort.MaxValue,testVal);

    testVal = MakeInt(0, 1);
    Assert.AreEqual(ushort.MaxValue+1,testVal);

    testVal = MakeInt(ushort.MaxValue, ushort.MaxValue);
    Assert.AreEqual(-1,testVal);
    }

    [Test]
    public void TestGetValueFromBytes()
    {
    byte[] testBytes = {0,0,0,0,0,0,0,0};
    int testVal = GetValueFromBytes(testBytes,0);
    Assert.AreEqual(0, testVal);

    testVal = GetValueFromBytes(testBytes,4);
    Assert.AreEqual(0, testVal);
    testBytes[0] = byte.MaxValue;
    testBytes[1] = byte.MaxValue;

    testVal = GetValueFromBytes(testBytes,0);
    Assert.AreEqual(ushort.MaxValue, testVal);

    testBytes[2] = byte.MaxValue;
    testBytes[3] = byte.MaxValue;

    testVal = GetValueFromBytes(testBytes,0);
    Assert.AreEqual(-1, testVal);

    testBytes[0] = 0;
    testBytes[1] = 0;

    testVal = GetValueFromBytes(testBytes,0);
    Assert.AreEqual(-1-ushort.MaxValue, testVal);
    }

    private ushort MakeUShort(byte low, byte high)
    {
    return (ushort) (low | (high<< 8));
    }

    private int MakeInt(ushort low, ushort high)
    {
    return (int) (low | (high<< 16));
    }

    private int GetValueFromBytes(byte[] data, int offset)
    {
    int nResult = 0;

    ushort lowWord = MakeUShort(data[offset],data[offset+1]);
    ushort highWord = MakeUShort(data[offset+2],data[offset+3]);
    nResult = MakeInt( lowWord, highWord );

    return nResult;
    }

    [Test]
    public void TestTimeZoneInfoForGMT()
    {
    RegistryKey regKey = Registry.LocalMachine;
    regKey = regKey.OpenSubKey(
    @”SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\GMT Stan-
    dard Time”);
    Assert.IsNotNull(regKey, “Invalid registry key”);
    System.Byte[] tziData = (Byte[])regKey.GetValue(“TZI”);

    int bias = GetValueFromBytes(tziData, 0);
    Assert.AreEqual(0, bias, “Bias was incorrect”);
    int standardBias = GetValueFromBytes(tziData, 4);
    Assert.AreEqual(0, standardBias,
    “Standard Bias was incorrect”);
    int daylightBias = GetValueFromBytes(tziData, 8);
    Assert.AreEqual(-60, daylightBias,
    “Daylight Bias was incorrect”);

    int month = MakeUShort(tziData[14],tziData[15]);
    Assert.AreEqual(10, month,
    “Month for change to standard time should be Oct”);
    DayOfWeek dayofWeek = (DayOfWeek)
    MakeUShort(tziData[16],tziData[17]);
    Assert.AreEqual(DayOfWeek.Sunday, dayofWeek,
    “Time should change on a Sun”);
    int day = MakeUShort(tziData[18],tziData[19]);
    Assert.AreEqual(5, day,
    “Time should change on 5th or last Sunday of month”);
    int hour = MakeUShort(tziData[20],tziData[21]);
    Assert.AreEqual(2, hour,
    “Time should change at 2am”);
    int minute= MakeUShort(tziData[22],tziData[23]);
    Assert.AreEqual(0, minute,
    “Time should change at 2am – zero minutes”);

    month = MakeUShort(tziData[30],tziData[31]);
    Assert.AreEqual(3, month,
    “Month for change to daylight savings should be Mar”);
    dayofWeek = (DayOfWeek)
    MakeUShort(tziData[32],tziData[33]);
    Assert.AreEqual(DayOfWeek.Sunday, dayofWeek,
    “Time should change to daylight on a Sun”);
    day = MakeUShort(tziData[34],tziData[35]);
    Assert.AreEqual(5, day,
    “Time should change on 5th or last Sunday of month”);
    hour = MakeUShort(tziData[36],tziData[37]);
    Assert.AreEqual(1, hour,
    “Time should change at 1am”);
    minute= MakeUShort(tziData[38],tziData[39]);
    Assert.AreEqual(0, minute,
    “Time should change at 1am – zero minutes”);
    }
    }

    Go Where No Man Has Gone Before
    Spiking is a skill, one that must be learned. And one thing you must learn is to relax and open your mind to the different possible solutions to your problem. Often, obvious solutions will not solve your problem; you have to look deeper. That’s why we get paid as software developers to solve such problems!

    The following exercises reinforce what you have learned in this chapter and require that you consider spiking in a bit more detail. As you work through the exercises, remember to encode your learned knowledge into tests. If you get stuck at any point, look for some clues on my Web site at http://eXtreme.NET.Roodyn.com.

    Exercise 6-2: Spike Web Services Without a Web Server
    The client wants to build an application that can be run on many machines in his company (laptops, desktops, and servers). He wants each machine to provide some status information via a Web service that can be queried on that particular machine. The machines might not necessarily be running IIS. The question is whether can we build a .NET Web service without the need for that machine to host a Web server.

    Exercise 6-3: Spike Session State Across Service Calls
    Our customer wants to amalgamate a number of Web service functions through a Web site. We propose to build the Web site in ASP.NET. The issue is that some of the Web services need to maintain state. Is it possible to do this?

    Exercise 6-4: Spike Drag and Drop Documents in a Rich Text Control
    The application we are building requires that it interact with other documents by allowing the user to drag a document from Explorer and drop it onto a Rich Text box. As with Outlook when you send an e-mail, the user wants to see the document as an icon and not the contents of the document. Is this something we can easily achieve?

    Conclusion
    Spiking is about experimentation and about being prepared to throw away the code you have written while retaining the knowledge gained from it. It is a fundamental skill that many developers start with but lose when under pressure to deliver business-value functionality under strict deadlines. The discipline to take a step back and experiment in a structured way will prove very valuable in the long run, enabling you to better know new technologies and validate theories about various systems.

    Chapter 7. Automating the Build Process
    If you can automate a step in the development process, you should do so. By doing this, you make the process simpler to carry out repeatedly in a consistent way. Remember, simplicity is a core value of XP. This chapter examines the tools that are available to aid automating the compilation and testing of your code.

    This chapter includes some thoughts about how to set up machines to carry out integration and build tasks. This chapter also covers some of the command-line tools available in the .NET Framework SDK. The exercises show how these tools enable you to automate steps of the build process. This chapter also introduces NAnt, a tool that carries out tasks defined in an XML file.

    What is the Build Process?
    The build process consists of a number of steps that you should carry out every time you have finished a task. As discussed in Chapter 3, the tasks are generally small; this means you will be carrying out these steps a number of times a day. Here is a list of the typical steps you need to complete:

    1. Get the latest version of the code for the entire solutions from the source control software.

    2. Build the latest version, including the changes made to complete the task.

    3. Run all the tests.

    4. If the tests all pass, add new changes to the source control system.

    5. Rebuild the solution to a central location.

    6. Build the installer to a central location.

    A few readers might now be asking, “What is source control software?” If you are one of those readers, please read this carefully. Source control software provides a central location for the entire team to store the code that has been developed. Reckon of it as a database for your code. It will let you look at the changes made over time and roll back to examine how the code looked at a given time. Microsoft currently supplies Visual SourceSafe with Visual Studio.NET as a source control software solution. Visual SourceSafe integrates with Visual Studio.Net and works well enough for the examples in this book. If you are developing software without using source control, stop reading this book and go and deploy source control software for your team now!

    XP teams often carry out these tasks on another computer called an integration machine. Having a separate machine for carrying out integration tasks proves valuable on several levels.

    An integration machine prevents more than one set of code changes from being integrated into the system at the same time. This helps to prevent conflicts from occurring. This works best in small teams of less than 15. With a large team, the bottleneck caused by having only one integration machine can be detrimental.

    Using an integration machine increases the visibility, to the entire development team, of the current state of the project. The feedback from this machine provides a continual reminder of the importance of having a working build and ensuring the tests run. As you will learn in the first exercise in this chapter, I like to set the entire screen of the machine to be either green for a excellent system state or red to indicate there is something broken in the system. Remember, feedback is one of the XP values, and this can help promote that feedback to the team.

    Having a separate machine to test your code before checking it in to the source control software helps to prevent the “it works fine on my machine” chant that I often hear from development teams. By testing the code on at least more than one machine, you reduce the chances of hearing these frustrating words again.

    What’s Incorrect with F5?
    If you are a regular user of Visual Studio, you are sure to know that the F5 function key compiles and runs your application. You can extend the functions carried out in this process by adding pre- and post- build steps to your projects. This is excellent for a certain number of things, such as copying all the compiled assemblies to a common folder. The distress is, it doesn’t go far enough or provide clear enough feedback.

    Larger software solutions consist of multiple Visual Studio solutions. Each solution might contain multiple projects. When we want to check whether we have broken anything through the changes we have just made, we need to run all the tests exposed by these components of the system. This involves getting the latest version of the source for these projects, compiling all the projects from the different solutions, and then running all the tests they expose. This calls for more than the support provided by an F5 compile and run. You could extend Visual Studio to do this, but it would not be the simplest thing you could do, and therefore it would break one of the XP tenets: Do the simplest thing that could possibly work.

    I’m Just Too Bone idle
    One of the reasons I have a fascination with computers and software is the belief that they should make our lives simpler. I am bone idle; I don’t want to have to type up letters, print them out, and mail them to someone. I like e-mail; it is the bone idle person’s answer to staying in touch. Instant messenger is even better! The same goes for spreadsheets; they save me having to do loads of calculations on a calculator or, worse yet, on paper. Computers can do lots of things to make my life simpler and give me more time to do the things I delight in doing. So when I see a task that I am having to repeat on a regular basis, such as building my application or running the tests, the Mr. Bone idle in me says, “Hey, let’s automate this so you can stop wasting your time and get on with something more fun.”

    I Make Mistakes
    A excellent reason to automate steps in a process is that the automation helps to reduce the likelihood of human error creeping in. This is even more vital when those steps have to be repeated many times. The more you do something, the less careful you are. This is right with many areas of life, and when you have to carry out a build and test process hundreds of times a week, it gets pretty damn dull. I tend to go into a trance when I do those tasks; I might forget to get the latest version from the source control or to run the tests on the components being developed in the other office or to build the installer. I need some way to remove the chance of my mistakes entering the system. Having a repeatable set of steps encoded into a program seems the most obvious way for a programmer to solve this problem.

    If a Computer Can Do It, Then It Should
    I believe as programmers we should use the tools we have at hand for our own advantage, and the computer is an ideal tool for carrying out many of these repetitive steps. When the team I am working with starts a new project, I always insist on setting up a build procedure as one of the first steps in the development process. I also like to ensure that we have an installer program ready from day one. This makes shipping the software simpler at the end of the project, because we dealt with it at the beginning.

    Let’s see how our eXtreme .NET team is dealing with automating the build process.

    Sue: I know that setting up the build process is going to be more work for us to do. I don’t see the point. I just hit F5, and Visual Studio builds and runs the code.

    Eddie: F5 doesn’t do everything we need. It doesn’t run our tests for a start. It doesn’t get the latest version of the code from SourceSafe, and it probably shouldn’t.

    Deepak: Okay, so we’re doing something different here than just building and running our app. I reckon I get that. So what else should we be doing in our build process?

    Eddie: Well, there are a lot of things we could do in our automated build. In the last project I worked on, we got the latest version from the code control, compiled the code, ran all the tests, and sent out an e-mail to all the team members indicating the status of the build and the results from the test.

    Deepak: We could get the automated build to look through all our code for any issues!

    Sue: What do you mean?

    Deepak: Well, there’s some software that sniffs the code for potential issues. Microsoft has a package called FxCop. It will tell us where the code doesn’t comply with our coding standards

    Pete: Panic!

    Eddie: That would be cool!

    Deepak: When the code has compiled and run all the tests successfully, we should get the automated build to make our install package. Then it will be simple for Chris to get the latest excellent build whenever he wants to play with it.

    Chris: That would be fantastic, but I’m not just playing, you know? This is serious; I like the thought of being able to get the latest version on a regular basis. Then I might be able to spot any issues more quickly than I could before

    Pete: Panic!

    Sue: Could we store the results from these builds in a database?

    Eddie: Sure, that is a excellent thought. Then we can see how the build has been going over a period of time. We can chart our progress and see if there are any patterns to failing builds. That could be really useful.

    Pete: Hey, we could also obfuscate the assembly in this process. That would be worth doing; I always forget to do that.

    Sue: Okay, I can see there is more to this than I realized. Let’s do it!

    Do It the Ancient Way
    You can automate builds, run tests, and deploy packages from the command line. This requires a small work and is often the simplest way to get started. In the following exercises, we set up some projects in Visual Studio and make a batch file that builds the files, runs the tests, and provides visible feedback as to whether anything failed.

    A batch file is just a text file that executes a set of commands from the command prompt. To run the batch file, you need to have the right command prompt environment variables set up. The simplest way to ensure this is to run the Visual Studio Command Prompt from the Visual Studio Tools folder in the Start menu.

    Exercise 7-1: Making an Integration Build Batch File
    In this exercise, we make a simple batch file that gets a solution from Visual Source-Safe, builds it, and runs the tests.

    1. Make a new blank solution called MySolution. I have made it in a directory on my C: drive called Work; you can make it where you want, but make sure you replace anywhere I have C:\Work\ with the directory you have used.

    2. Right-click the solution and add a new C# Library project called MyLibrary.

    3. Right-click the solution again and make a new Visual Basic Windows application called MyWindowsApplication.

    4. Right-click the solution again and select Add Solution to Source Control from the pop-up menu (see Figure 7-1). I am adding the solution to a database I have made for this exercise called MySolution; if you use another database, remember what it is called.

    Figure 7-1. Add solution to source control.

    5. We are now ready to make a batch file to get the latest version of the source from the database and build the solution. The batch file I made is shown below, and yours should look something like it. I used my favorite batch file editor, Notepad, but you can use any text editor, including Visual Studio.

    Remember to change the names of the directories depending on where you have made the solution and where your Visual SourceSafe database is. Notice how simple it is with the devenv command to build a Visual Studio Solution; we don’t have to worry about the fact that it contains a C# project and a VB.NET project.
    @echo off

    rem: set the source safe database
    set SSDIR=C:\Work\SSDB\MySolution

    rem: set the working directory for the source safe database root project
    ss Workfold $/ C:\Work

    rem:change to the directory where all the projects work is
    C:
    cd Work

    rem: get the latest version of the source files from source safe
    ss get $/ -R -I

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    rem: use the Visual studio cmd line to rebuild the entire solution
    devenv /rebuild Debug “C:\Work\MySolution\MySolution.sln”

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    :D isplayResult
    if errorlevel 1 goto failed

    echo Success!! :-)
    goto end

    :failed
    echo FAILURE :-(

    :end

    6. Save the file as Build.bat and don’t forget to save the solution. Then run the batch file to make sure it compiles. Remember, this needs to run in a command prompt with the right environment variables (such as paths to the Visual Studio folders) set correctly. As mentioned previously, Visual Studio provides a Visual Studio command prompt that has this set up already.

    7. We can now add some unit test code to the library and get the batch file to run the tests as well. Back in Visual Studio, check out the My Library Project using the right-click pop-up menu.

    8. Add a reference to the NUnit.Framework.Dll, as you learned in Chapter 4.

    9. Add a new class called LibraryTests to the Library project.

    10. In this class, we will make two tests, one that always passes and one that always fails, as shown in the following code.
    using System;
    using NUnit.Framework;

    namespace MyLibrary
    {
    [TestFixture]
    public class LibraryTests
    {
    [Test]
    public void AlwaysPasses()
    {
    }

    [Test]
    public void AlwaysFails()
    {
    Assert.Fail(“This test should fail”);
    }
    }
    }

    11. Make sure it compiles in Visual Studio, and then save the file and the project. Check it back into SourceSafe, and then run the batch file to make sure it still compiles.

    12. We can now add two lines to the batch file to run the tests.
    @echo off

    rem: set the source safe database
    set SSDIR=C:\Work\SSDB\MySolution

    rem: set the working directory for the source safe database root project
    ss Workfold $/ C:\Work

    rem:change to the directory where all the projects work is
    d:
    cd Work

    rem: get the latest version of the source files from source safe
    ss get $/ -R -I-

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    rem: use the Visual studio cmd line to rebuild the entire solution
    devenv /rebuild Debug “C:\Work\MySolution\MySolution.sln”

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    rem: run the tests
    nunit-console C:\Work\MySolution\MyLibrary\bin\Debug\MyLibrary.dll

    rem: check that they passed
    if errorlevel 1 goto DisplayResult

    :D isplayResult
    if errorlevel 1 goto failed
    echo Success!! :-)
    goto end
    :failed
    echo FAILURE :-(

    :end

    13. Run the batch file again. It should run the tests and report a failure. You can play with commenting out the test that fails, and the tests should pass.

    14. You can use this batch file for an integration machine in an XP environment. As I mentioned earlier, I like to be able to see the state of a build on the integration machine from the other side of the room so that I know where we are. Therefore, I have added a couple of lines in the batch file to change the color of the screen based on the result (red for failed and green for succeeded).
    @echo off

    rem: set the source safe database
    set SSDIR=C:\Work\SSDB\MySolution

    rem: set the working directory for the source safe database root project
    ss Workfold $/ C:\Work

    rem:change to the directory where all the projects work is
    d:
    cd Work

    rem: get the latest version of the source files from source safe
    ss get $/ -R -I-

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    rem: use the Visual studio cmd line to rebuild the entire solution
    devenv /rebuild Debug “C:\Work\MySolution\MySolution.sln”

    rem: check that it worked
    if errorlevel 1 goto DisplayResult

    rem: run the tests
    nunit-console C:\Work\MySolution\MyLibrary\bin\Debug\MyLibrary.dll

    rem: check that they passed
    if errorlevel 1 goto DisplayResult

    :D isplayResult
    if errorlevel 1 goto failed
    color A1
    echo Success!! :-)
    goto end
    :failed
    echo FAILURE :-(
    color C1

    :end
    rem: for continuous builds the line below
    call C:\work\Build.bat

    I have also added a line at the bottom of the file to run the batch file again when it has finished. If I now set this up on an integration machine, it will continuously be getting the latest version from Visual SourceSafe, building it, and running the tests. This is useful because the integration machine can now give the development team feedback as to the state of the system. For this reason, I always recommend putting the integration machine somewhere highly visible. As soon as something breaks, the whole team can do something about getting it fixed.

    Introduction to NAnt
    The following exercise introduces NAnt, a build tool based on ANT, which is an XML-based Java build tool. NAnt enables us to define how we are going to build and test our .NET projects by using an XML file. The advantage this has over the batch file we just made is that it can be more configurable. We can define different build targets within the NAnt build file.

    At the time of this writing, NAnt is still in early stages of development, with version 0.84 being the latest release. So we are dealing with a piece of software that is not yet at version 1.0. Saying that, NAnt does have much of what is needed to build and test your project. You can download the latest version from http://nant.sourceforge.net/, and then we can get started and make a NAnt build file.

    To use NAnt, you need to have configured the path environment variable to include the Nant\bin directory. NAnt is a command-line tool; therefore, you also need to have the Visual Studio .NET (or .NET Framework if you are working without Visual Studio) environment variables registered in your command-line environment. There is a batch file called vsvars32.bat in the Microsoft Visual Studio .NET\Common7\Tools directory, which will most likely be in your Program Files directory. This batch file will set up your environment variables for you.

    Exercise 7-2: Using NAnt to Automate the Build Process
    We will start by building a simple C# Windows application project and setting up the NAnt build file for it.

    1. Make a new C# Windows application project called NAntTest.

    2. In Solution Explorer, right-click the NAntTest project and select Add/Add New Item from the pop-up menu. Then select XML file and call it NAntTest.build (see Figure 7-2). The standard practice for NAnt build files is to call them the project name and use the extension .build. NAnt build files are XML files.

    Figure 7-2. Add a new NAntTest.build file.

    [View full size image]

    3. Now we can work on adding the tags to this XML file that we need to be able to build the project using NAnt. We’ll start by defining the project in the build file, as shown. The project element is attributed with name and basedir; these represent the project name and the base directory for the build process, respectively.
    Note
    You can get the Visual Studio.NET IDE to show your build file as syntax-highlighted XML by right-clicking the file, selecting Open With, and then selecting the HTML/XML Editor.

    <?xml version=”1.0″ encoding=”utf-8″ ?>
    <project name=”NAntTest” basedir=”.”>

    </project>

    4. Next we will add some properties to the project; these will be used by the other sections in the build file.
    <project name=”NAntTest” basedir=”.”>
    <property name=”basename” value=”NAntTest”/>
    <property name=”debug” value=”right”/>
    <property name=”build.dir” value=”build”/>
    </project>

    5. We can now define a target, nested within the project, for the build, as shown here.
    <?xml version=”1.0″ encoding=”utf-8″ ?>
    <project name=”NAntTest” basedir=”.”>
    <property name=”basename” value=”NAntTest”/>
    <property name=”debug” value=”right”/>
    <property name=”build.dir” value=”build”/>
    <target name=”build”>
    <mkdir dir=”${build.dir}”/>
    <csc target=”exe” output=”${build.dir}\${basename}.exe”
    debug=”${debug}”
    imports=”System,System.Collections,
    System.Data,System.Diagnostics,
    System.Drawing,System.Windows.Forms”
    rootnamespace=”NAntTest” >
    <sources>
    <includes name=”*.cs”/>
    </sources>
    <references>
    <absolute file=”System.dll”/>
    <absolute file=”System.Data.dll”/>
    <absolute file=”System.Drawing.dll”/>
    <absolute file=”System.Windows.Forms.dll”/>
    <absolute file=”System.XML.dll”/>
    </references>
    <arg value=”/main:NAntTest.Form1″/>
    </csc>
    </target>
    </project>

    Build File Components
    Let’s examine what this file consists of:

    The target element has a name; we will use this later when we define more than one target.

    Then we use the mkdir element to make the build directory for the build output to go in. Notice we use the build.dir property we just defined in the previous step.

    The next element is csc for C# compiler options. We use the target attribute to state we are building an EXE rather than a DLL assembly. The output attribute defines the location and name of the output from the compilation. Again, notice we are using properties we defined earlier.

    The debug attribute uses the debug property we defined to indicate whether we are building the project for debug.

    Then the imports attribute defines all the assemblies to import into the project.

    The final attribute we use here is the rootnamespace attribute to define the root namespace of the code being compiled. For us that’s the NAntTest project namespace.

    The sources element, which is a child of the csc element, defines the source files to compile for this target. Notice here we are including all C# files.

    The references element enables us to define all the assemblies we need to reference for the build of this target to work.

    The final child element of the csc element is arg; this enables us to define free-form text arguments to pass to the compiler. Here we are defining the main assembly entry point.

    6. After saving the build file, go to the command line and call NAnt to build the project (see Figure 7-3).

    Figure 7-3. Our first NAnt build.

    [View full size image]

    8. We can now define some more targets within the project. This enables us to carry out more than one type of build from the same file. Let’s start by defining a target that really doesn’t build at all but instead deletes all the build output. We make a new target called clean, as shown here.
    <target name=”clean”
    description=”deletes the build directory”>
    <delete dir=”${build.dir}” verbose=”right”
    failonerror=”fake”/>
    </target>
    Notice that we have added a description attribute to the target element. We then add the child delete element to the target. The dir attribute defines the directory to delete. The verbose attribute indicates whether the output should be explicit. The failonerror attribute indicates whether NAnt should consider it has failed if there is an error. Here we set this to fake; we do so because if NAnt fails to delete the directory, we don’t want to consider this an error because it might happen often when the directory is not there.

    9. Save the file and run NAnt from the command line, passing clean as a parameter (see Figure 7-4).

    Figure 7-4. Run NAnt using the clean target.

    [View full size image]

    10. We can go back to the outermost project element and add an attribute to indicate the default target, as shown; this will set the default target to our build target. You can test this by just calling NAnt from the command line without specifying a target to build.
    <project name=”NAntTest” default=”build” basedir=”.”>

    11. Now we can define how to make release and debug builds by changing the debug property. Notice how these targets have a depends attribute; this defines the other targets on which they depend. When NAnt encounters this, it will build the other target first. So before building either for release or debug, NAnt will now build the clean target, which deletes any files previously built.
    <target name=”debug” depends=”clean”>
    <property name=”debug” value=”right”/>
    </target>
    <target name=”release” depends=”clean”>
    <property name=”debug” value=”fake”/>
    </target>

    12. We can get a debug and release build from this file by calling NAnt with the right parameters, as shown in Figure 7-5.

    Figure 7-5. NAnt builds the release and build targets.

    [View full size image]

    13. Finally, we are going to add a target that will do the program that we have built. The exec element contains the program attribute to define the program to do and the basedir attribute to define where to do the program.
    <target name=”run” depends=”build”>
    <exec program=”${build.dir}/${basename}.exe” />
    </target>

    14. We can now build and run the program using NAnt (see Figure 7-6).

    Figure 7-6. Build and run the project from NAnt.

    [View full size image]

    15. You can also choose whether to build and run the debug or the release version, as shown in Figure 7-7.

    Figure 7-7. Use NAnt to do a release build and run the application.

    Incoming search terms:

    Share and Enjoy:
    • Print
    • Digg
    • Sphinn
    • del.icio.us
    • Facebook
    • Mixx
    • Google Bookmarks
    • Blogplay
    • Add to favorites
    • BarraPunto
    • Bitacoras.com
    • BlinkList
    • blogmarks
    • Blogosphere News
    • blogtercimlap
    • connotea
    • Current
    • Design Float
    • Diggita
    • Diigo
    • DotNetKicks
    • DZone
    • eKudos
    • email
    • Fark
    • Faves
    • Fleck
    • FriendFeed
    • FSDaily
    • Global Grind
    • Gwar
    • HackerNews
    • Haohao
    • HealthRanker
    • HelloTxt
    • Hemidemi
    • Hyves
    • Identi.ca
    • IndianPad
    • Internetmedia
    • Kirtsy
    • laaik.it
    • LaTafanera
    • LinkaGoGo
    • LinkArena
    • LinkedIn
    • Linkter
    • Live
    • Meneame
    • MisterWong
    • MisterWong.DE
    • MOB
    • MSN Reporter
    • muti
    • MyShare
    • MySpace
    • N4G
    • Netvibes
    • Netvouz
    • NewsVine
    • NuJIJ
    • PDF
    • Ping.fm
    • Posterous
    • Propeller
    • Ratimarks
    • Rec6
    • Reddit
    • RSS
    • Scoopeo
    • Segnalo
    • SheToldMe
    • Simpy
    • Slashdot
    • Socialogs
    • SphereIt
    • StumbleUpon
    • Suggest to Techmeme via Twitter
    • Technorati
    • ThisNext
    • Tipd
    • Tumblr
    • Twitter
    • Upnews
    • viadeo FR
    • Webnews.de
    • Webride
    • Wikio
    • Wikio FR
    • Wikio IT
    • Wists
    • Wykop
    • Xerpi
    • Yahoo! Bookmarks
    • Yigg
    • Yahoo! Buzz

    Topics: Uncategorized | No Comments »

    Comments are closed.