It describes some of the techniques that make agile methods successful, including pair programming, test-driven development, and design by contract.. ❑ Courage — This is the idea that de
Trang 1Agile Methodologies
Chapter 2, “Lifecycle Methodologies,” discussed several models for managing a project through-out its lifespan This chapter explains newer “agile” approaches to controlling development While the more traditional approaches focus on predictive planning to guide the project, these methods react quickly and change the project’s direction as needed to move toward the eventual goal of producing a finished application
This chapter describes agile development methods in general, and spends a little extra time on the Crystal Clear and Extreme Programming models It describes some of the techniques that make agile methods successful, including pair programming, test-driven development, and design by contract Even if you don’t adopt agile methods in their entirety, some of these techniques may be useful to you in more traditional lifecycle models
The first sections in this chapter focus on the goals of agile development They describe some of the approaches developers have taken, their advantages, and their rationale Later sections com-pare these methods to the more traditional methodologies described in Chapter 2 and cover some
of the dangers and disadvantages in agile programming
Agile Programming
Agile programming is as much an attitude or philosophical approach as a strictly defined
methodol-ogy The basic principle behind agile development is that the development lifecycle should be quick and responsive It should be able to adjust rapidly to changing requirements, and should be able to take advantage of new innovations as they occur
Different variations of agile development have such names as Crystal Clear, Scrum, Adaptive Software Development, Feature Driven Development, and Lean Software Development Another form of agile development, Extreme Programming, is described in more detail later in this chapter You can learn more about other agile methods on the Web or in books that focus on agile
Trang 2develop-(Boston: Addison-Wesley Professional, 2004), Agile and Iterative Development by Craig Larman develop-(Boston: Addison-Wesley Professional, 2003), and Managing Agile Projects by Kevin Aguanno (Lakefield, Ontario,
Canada: Multi-Media Publications Inc., 2005)
Though different agile methods have different details, they share some common themes In 2001, a group of prominent agile developers got together and assembled what is now called the Agile
Manifesto The short summary of the manifesto at agilemanifesto.orgis as follows:
These rather vague statements try to convey the agile philosophy, rather than specific rules to follow The idea is that developers should place greater importance on building a flexible, usable, effective application than on following rigidly defined methods to build a complete specification and then follow
it to the letter
The following text shows the manifesto’s principles in slightly greater detail Some of these points are more concrete rules that you can actually follow:
Our highest priority is to satisfy the customer through early and continuous delivery
of valuable software.
Welcome changing requirements, even late in development Agile processes harness
change for the customer’s competitive advantage.
Deliver working software frequently, from a couple of weeks to a couple of months,
with a preference to the shorter timescale.
Business people and developers must work together daily throughout the project.
Build projects around motivated individuals Give them the environment and
support they need, and trust them to get the job done.
The most efficient and effective method of conveying information to and within a
development team is face-to-face conversation.
Working software is the primary measure of progress.
Agile processes promote sustainable development The sponsors, developers, and
users should be able to maintain a constant pace indefinitely.
Continuous attention to technical excellence and good design enhances agility.
Simplicity — the art of maximizing the amount of work not done — is essential.
The best architectures, requirements, and designs emerge from self-organizing teams.
At regular intervals, the team reflects on how to become more effective, then tunes
and adjusts its behavior accordingly.
Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan
Trang 3The emphasis is on producing small software releases very quickly with constant feedback from users to ensure that development continues toward a useful goal
Crystal Clear
The Crystal Clear methodology reduces the Agile Manifesto to seven principles You can find a detailed description of these principles in the chapter, “Crystal Clear Applied: The Seven Properties of Running
an Agile Project,” of the book Crystal Clear: A Human-Powered Methodology for Small Teams (you can find
this chapter at www.awprofessional.com/articles/article.asp?p=345009&seqNum=1) The fol-lowing list summarizes those principles:
❑ Frequent Delivery — Each iteration should take only a few weeks, not the months or years
some-times required by other lifecycle models Each cycle should produce a high-quality release-ready application, although post-release activities such as documentation are often neglected
❑ Reflective Improvement — After each iteration, the team makes a list of the things that are working
and those that are not It then continues using the methods that work and improves the things that are not working Even if things go badly wrong, the team should be able to get back on track in the next iteration or two
❑ Osmotic Communication — Communication occurs frequently, so all of the team members can
listen in, preferably with all of the team members in the same room For example, if all of the developers work in a large “bullpen” style office, they can listen in on each other’s conversa-tions Naturally, this kind of “eavesdropping” style of communication is more difficult with large teams (However, some developers may be uncomfortable in the “bullpen” style office and get the feeling that someone is constantly looking over their shoulders Some managers may think this encourages developers to work hard and only on business-related projects, but it may also lead to a stressful environment that chases away good developers.)
❑ Personal Safety — The work environment encourages developers to speak up when they see
prob-lems without fear of retaliation Developers respect each others’ opinions and discuss issues openly (As is the case with osmotic communication, the real world sometimes makes this sort of assumption difficult We’ve all met “prima donna” developers who have extremely high opin-ions of their own abilities, and it is difficult to build an atmosphere of trust with them around In some cases, it may be best in the long run to keep some of these developers apart so they don’t sour the rest of the team.)
❑ Focus — Developers stay focused on clearly defined tasks and high-priority items to control
their workload (Occasionally, however, developers may need a break from crucial program ele-ments Building a quick, unrelated programming tool or attending a conference can help keep developers fresh Google employees are expressly told to spend a certain percentage of their time experimenting to see what they can accomplish.)
❑ Easy Access to Expert Users — Developers have quick, easy access to expert users so that they can
get prompt authoritative feedback and guidance on changing requirements (Developers should keep themselves under control, however, and not become total pests Frequent interruptions can reduce the experts’ productivity at their normal jobs and can be frustrating for them In some projects, I have worked with experts assigned full-time to our project, but at other times the users had to handle their normal workloads in addition to answering our questions In that kind of situation, you must be sensitive to the experts’ situations and not overwhelm them.)
Trang 4❑ A Strong Development Environment — This includes the tools that you would want for any
devel-opment effort such as a source code control system and automated testing tools Alistair
Cockburn, the author of the Crystal Clear: A Human-Powered Methodology for Small Teams book
(Boston: Addison-Wesley Professional, 2004), also argues that developers should perform fre-quent integration — as often as several times per day, but no less than once every other day He calls this “continuous integration-with-test.” Frequent integration combined with good testing tools lets developers move forward confidently
Again, the emphasis is on producing small software releases very quickly with constant feedback from users to ensure that development continues toward a useful goal Specific principles (such as reflective improvement, osmotic communication, and personal safety) help keep the team working smoothly at a rapid pace
Extreme Programming (XP)
The Agile Manifesto and Crystal Clear focus on a set of relatively high-level goals and procedures For
example, frequent releases, reflective improvement, and quick user feedback are tools that help keep development on track They do not address the day-to-day process of writing code
Extreme Programming (www.extremeprogramming.org) uses similar concepts, but also adds a few more concrete rules for guiding everyday development
The book Extreme Programming Explained: Embrace Change by Kent Beck and Cynthia Andres (Boston:
Addison-Wesley, 2004) lists five key values that are central to Extreme Programming:
❑ Communication — Communication occurs frequently and informally within the development team.
❑ Simplicity — Code starts simply and is later modified, if necessary, to build a better solution.
❑ Feedback — Expert users provide frequent feedback The team provides feedback to itself to
improve the development process
❑ Courage — This is the idea that developers should bravely push forward writing code for their
immediate needs, and not focus on code they will need to write later Developers focus on the current simpler needs, rather than on the more complicated modified code they may need to write later
❑ Respect — Developers respect each other They work together to improve each others’ code and
take each others’ suggestions seriously
Advocates of Extreme Programming also recommend embracing changes and making incremental change, rather than making large-scale changes all at once Extreme Programming also assumes that the code is fre-quently tested so that the releases have high quality
If you compare these values to the list of principles for Crystal Clear given in the previous section, you will see some parallels Both emphasize communication, user feedback, and improving the development process (reflective improvement in Crystal Clear, feedback in Extreme Programming) Both stress fre-quent, incremental, high-quality releases, rather than fewer large releases
Trang 5You can also see some of the same potential drawbacks Frequent communication and trust can be diffi-cult with some developers Some of the team’s stronger personalities may have trouble giving total respect to less-experienced members Occasionally, it’s better to place a bit of distance between trouble-some developers and the others so the team as a whole functions smoothly
In addition to these higher-level values and principles, Extreme Programming requires developers to follow the 12 specific practices described in the following sections
Whole Team
The development group works as a unified team, ideally in a single location sharing a large workspace Proximity and a relaxed team atmosphere make it easy for team members to ask and answer questions whenever necessary
The team will certainly include programmers Often, it will include customers, or at least someone who represents the customers’ interests Depending on the scope of the project, it may also include project managers, testers, documentation writers, trainers, and others Extreme programming works best with small teams, so that often a single person fills several of these roles
The Planning Game
In the “planning game,” users and developers sit down and discuss the next round of development Users describe features that they need implemented Developers estimate the times and costs needed to implement the features The users then pick the most important features for inclusion in the next release The result is a short list of changes and additions to the current solution that developers can implement
in a few weeks
One of the key points of the planning game is to select the features that will be added to the next release This focus encourages users to think in terms of releases with some features deferred for one, two, or more release cycles Keeping track of deferred features can help lay the groundwork for long-term plan-ning and future planplan-ning games
One problem with this sort of planning is that it can be hard for the participants to commit to difficult tasks Suppose a particular feature will take four weeks to implement, but the goal is to select features that can be implemented in no more than three weeks Unless you can find a way to break the large task into smaller pieces, it is easy to defer this large task indefinitely At some point, you need to admit that the task is necessary and “lose” the planning game to get the job done
Simple Design
The application uses the simplest design possible to achieve its goals at every step Programmers focus
on the immediate needs, and don’t worry about building general solutions to later problems Test-driven development (described later) promotes this idea of keeping the design as simple as possible while get-ting the job done
Developers are often prone to “featuritis,” adding unnecessary bells and whistles to code because they are interesting or improve flexibility It is better to get the immediate job done as simply and quickly as possible and only make more complicated changes later when they prove necessary.
Trang 6Design Improvement
An Extreme Programming project starts with a simple design and grows more complicated as necessary over time Because Extreme Programming favors frequent small builds, the overall design grows incre-mentally Sometimes decisions that made sense when a particular piece of code was written don’t make sense later as the project expands
As development progresses, the code is refactored as necessary to improve the overall design Redesign
activities focus on consolidating redundant code, improving consistency, and decoupling subsystems
Small Releases
Like other agile methods, Extreme Programming uses many small releases to work rapidly toward the final solution Small releases give the users frequent chances to provide feedback and give the develop-ers frequent opportunities to improve the design, the requirements, and the development process itself
Continuous Integration
After a piece of code successfully passes its tests, it is integrated into the system All of the system’s tests must run after the new code is added In Extreme Programming, this system integration should be per-formed several times each day if possible
Continuous integration ensures that the code always has high quality Before a piece of code is perma-nently added to the system, its authors have tested it, added it to the code base, and tested the whole system to ensure that the new code didn’t break anything The system may have some missing features, but the features that are present have been tested
Coding Standard
The project should have a set of coding standards that all users follow The standards should cover such things as the following:
❑ Class, variable, and routine naming conventions
❑ Calling conventions, such as how parameters are named and whether they are declared ByVal
or ByRef
❑ Commenting conventions for routines, modules, and code
❑ Standards for using the Withor Usingkeywords, defining loop variables, and so forth
❑ Error-handling conventions
Using a common code style makes it easier for developers to understand each other’s code, and can pre-vent petty disputes over style that might otherwise arise during pair programming
Collective Code Ownership
The Extreme Programming team as a whole owns the code, not particular developers or pairs That means
if you find a problem in a piece of code that has been checked into the system, you check it out, modify it, retest it, check the code back in, and retest the system to ensure that you didn’t break anything else You may need to ask other developers for information about code they wrote, but you should not regard that code as their property It belongs to the project and the project team as a whole
Trang 7System Metaphor
The system’s metaphor is an all-encompassing story that describes the system This should be an intu-itive parallel to some process that all of the developers can easily understand The developers can use the metaphor to think about the relationships among the system’s pieces, and to pick names that go together reasonably well
For example, Windows uses a desktop metaphor, where folders contain files and you put files you no longer need in a wastebasket Until you empty the wastebasket, you can retrieve files from it if you decide you really need them
With this metaphor, it is easy to think of consistent names for most of the operations a program might need
to perform: CreateFile, PutFileInFolder, MoveFileToWastebasket, MoveFolderToWastebasket, ListWastebasketContents, RemoveFromWastebasket, EmptyWastebasket, ArrangeDesktop, and so forth Names such as DeleteFile, PermanentlyDelete, and ReorderIconsdon’t fit the metaphor, so they are not as good
If you can’t think of a reasonably intuitive metaphor, you can at least give names to all of the major sys-tems and classes so that developers can use them to generate other consistent names For example, if a dispatching application uses network classes named StreetNodeand StreetLink, developers can easily generate related names such as ConnectStreetNodes, TraverseStreetLinks, and so forth
Pair Programming
In pair programming, two programmers work together to write a single piece of code They design,
write, test, and debug the code together as a two-person team One person, the driver, types at the com-puter while the other, the observer or navigator, reads the results and thinks about the direction of the
steps to come The two programmers switch roles periodically (some recommend at least every half hour) to keep both fresh, and to allow both to develop their pair programming skills
People are naturally very good at filling in pieces that are missing from a puzzle When you write code and later when you read the code you wrote, you sometimes see what you think is there instead of what is
really there That’s why programmers sometimes stare right at a bug for hours without actually seeing it.
One way traditional development efforts try to improve code quality is by holding code reviews, where
a programmer steps through his code and explains it to the other programmers Often, the process of holding the review enables the programmer who wrote the code to spot bugs The act of slowing down and describing the code verbally often forces the programmer to see the code that is actually there and that makes the bugs obvious
Pair programming lets programmers take advantage of the same phenomenon while writing every line
of code If one person verbally describes the code while typing it into the computer, and the other person listens and reads along, the code is reviewed by two people in four different ways (speaking, typing, lis-tening, and reading) and the programmers are more likely to catch any mistakes
One way to proofread a novel takes advantage of this same principle of reviewing text in two different ways
at the same time Two reviewers read the book together, taking turns where one reads aloud (in a whisper to conserve their voices) and the other follows along silently If a word is missing or extraneous, one reviewer may mentally correct the mistake, but if the other does not, then the error is immediately apparent.
Trang 8Pair programming can also help less-experienced developers improve their skills by working with a more experienced developer It can act as a form of apprenticeship to help the junior programmers learn new techniques more quickly than they could on their own It is important that the pair switch roles periodically, however, even if one programmer is more experienced than the other Both developers must participate, or the experienced programmer may end up doing all of the work while the apprentice sits quietly, removing the multiple-point-of-view benefit provided by pair programming
Pair programming can help overcome some of the difficulties that less-experienced developers may
face when using other agile methods When requirements change frequently, junior programmers who require more guidance may have trouble quickly adapting to the new circumstances, and may need extra help to get settled in the new direction When paired with a more senior developer, the junior program-mer can still make progress relatively quickly Two novice programprogram-mers paired together might make
adequate progress on simple, well-defined tasks, but you wouldn’t want that team to tackle the trickier parts of the system without guidance.
Pair programming also has some less-tangible benefits, such as faster team building and fewer interrup-tions (people are more reluctant to interrupt a pair)
Pair programming does have a few drawbacks Some programmers prefer to work alone and may find working too closely with a partner to be irritating Very advanced developers may find it particularly difficult to work with junior developers Pairing a coding wizard with a novice may reduce the wizard’s productivity Sometimes it may be better to let the wizard work alone, particularly when deadlines are approaching Often, though, it’s worth at least some loss of productivity to put more “eyes on the code” and to give the novice some extra experience and insight
Differences in coding styles can cause friction between paired developers You can avoid some of this problem by creating a project code standard and requiring all of the developers to follow it Then, instead
of arguing over who has the better system for naming variables, the pairs can just blame the style stan-dard for any deviations from their preferred styles and move forward (They may even bond a bit during
a joint complaining session.)
Test-Driven Development
One of the main goals of Extreme Programming is to produce code that is of high quality at all times One approach to achieving that goal is test-driven development
In test-driven development (also called test-first development), you write the tests first, and then you write
code to pass the tests You then run the code against the tests If there are any problems, you revise the code and run the tests again You repeat this process until the code passes all of the tests
Of course, when you design code to pass a test, you must assume that the test is correct If the test is
wrong, it will drive you to write perfectly working code that does the wrong thing Take some time with the tests and ensure that they test the right thing If the code doesn’t satisfy a test, ensure that you
understand why, and be certain that it’s because the code is wrong, not because the test is flawed.
Sometimes during initial development or while you are fixing the code to pass a test, you may think of another test case that you didn’t consider before At that point, you can add the new test to the suite you have already written Before you do, however, you should consider whether the test is really necessary or whether it would be possible to restrict the requirements to prohibit that particular test case Restricting the requirements usually leads to simpler code that can be easier to debug and maintain
Trang 9For example, suppose you need to write a routine to sort a list of customer names You write some tests that generate random lists of names, pass them into the sorting routine, and then verify that the returned results are sorted The test software performs any number of trials with lists of customer containing from
1 to 100,000 customers
You write the sorting code, run the tests on it, and fix some bugs While fixing the code, you realize that the routine won’t work if two customers have exactly the same name, or if the list of customers contains zero entries
In this case, you probably need the code to handle the case where two customers have exactly the same name How many Jane Smiths and Manuel Garcias are in your local phone book? You should write a new test that runs the software on customer lists that contain duplicates
However, your application may have other requirements that make a zero-item customer list impossible Perhaps the user cannot get to the form that displays the sorted list unless there are entries in it In that case, you may want to note in the requirements that this situation is impossible, so you don’t need to write code to handle it or test against it
You might also include a Debug.Assertstatement in the code to verify that the list has at least one item Then, if the program somehow manages to pass an empty customer list to the routine, the program will stop so that you can figure out why this is happening and fix it.
Figure 3-1 shows the process graphically
Figure 3-1: In test-driven programming, you write tests first and then code As long as the tests fail, you fix the code and possibly write more tests
Test-driven development has many advantages To write the tests, you must understand the require-ments, but you don’t need to know yet how to write the code This keeps you focused on the code’s usage and results, rather than its implementation This focus on usage is similar to the design by con-tract approach described later in this chapter
Tests F ail
Done
Trang 10That, in turn, helps you write tests that determine whether the code meets the requirements, rather than
determining whether the code does what you think it does Just as your brain can fill in missing pieces in
a puzzle or subroutine, it can also predispose you to write tests that evaluate the code you wrote, rather
than the code that you should have written If you’re not on guard, it’s very easy to write code that only
tests the cases you thought of when you wrote the code, and not all of the cases that the requirements demand
It’s also easy to write just one or two tests, and then assume that if the code passes those, it must pass any others that you might write Some developers don’t write any tests for their code, at least at the rou-tine level, and they just assume that it will work After all, if they knew there was a problem in the code, they would have fixed it Since they don’t know of any problems, the code must be correct Because test-driven development places test writing first, programmers have no excuse to skip writing tests Even the most delusional developers cannot claim that their code works correctly if it doesn’t exist yet
Sometimes test-driven development leads to simpler code Because the programmer is writing code that only satisfies a specific set of tests, there’s less temptation to add extra bells and whistles that don’t lead
to passing the tests
Finally, test-driven development ensures that every piece of code is covered by some automated test That makes automated module and unit testing easier, so the code is more likely to be tested thoroughly Test-driven development is not completely without drawbacks If you write a routine to perform a mini-mal set of tests, and later discover that the routine needs to do more, you must spend additional time revising the tests in addition to modifying the code
Though testing gives you some confidence that your code works, it is far from a guarantee Ideally, your tests would try out every possible combination of inputs and verify the results In practice, it’s rare that
you can test with every possible set of input values In that case, testing doesn’t guarantee correctness
and, if you design the tests poorly, it may add a false level of confidence to code that doesn’t work Designing tests is itself a bit of an art form Generally, it’s a good idea to test inputs near the boundaries
of allowed values; very big and very small values Depending on the code, you should test with values
in the middle of the allowed values, empty and missing inputs, lots of duplicate inputs, and inputs sorted forward and backward Try a large assortment of values that seem typical for the application, in addition to a variety of values that seems weird or unusual Try illegal values and verify that the code catches them
Even with all of these tests, you can’t be sure to catch every possible bug What if the test code is written incorrectly so that it doesn’t actually catch any bugs at all? One approach that many test-driven develop-ers use to prevent that particular error is to start writing the actual code with a vdevelop-ersion that doesn’t work, and then verify that the testing code realizes it For example, you might have a sorting subroutine return the same values it receives as input, so any tests that did not start with already sorted data should detect an error
Another drawback to test-driven development is that it can be difficult to write good tests for certain kinds of development before the code is written For example, it’s hard to write programmatic tests for graphical and GUI code beforehand Suppose a program should display the locations of sales represen-tatives on a map You can buy regression-testing tools that will take a snapshot of the map so that you can later tell if a test achieved the same result However, it would be difficult for you to manually gener-ate the map ahead of time so that you could compare the code’s output to it