This is a news update, not another card, but our latest article is up at Pragmatic Programmers.
We've gone a few weeks without a new card here, but it's because we've been working on the final versions of our cards to be published by Pragmatic Publishers "Real Soon Now." You will find a lot of familiar content, but even more polished and even more condensed. You'll get to enjoy physical cards, suitable for sticking and sharing with your whole team or company. Even better yet, they'll have been edited by actual professional editors.
We're not going to quit the blog, but we are going to be available in more forms than ever before. PragProg will release AgileInAFlash as physical cards and as ebooks. Imagine how cool "Courage" or "ABCs of Pair Programming" will look on your hot little iPad or Android phone! You'll have virtual Tim & Jeff everywhere you want to take us. This blog continues to be a place to write your comments, or to see cards never before released into the wild.
When you get your deck(s), take a picture of yourself using the cards and send it to us. We'll be thrilled and honored to see how you use your AgileInAFlash in your daily work!
Blessings.
Tim
Tim Ottinger & Jeff Langr present the blog behind the versatile
Pragmatic Programmers reference cards.
Basic Agile Flow
Tim Ottinger and Jeff Langr
There are many ways to conduct an agile project. Some work with huge backlogs, some with spur-of-the moment requirements, some have continual release, some have non-time-boxed continual flow. We recommend starting with the structure shown on this Agile in a Flash card.
Following this plan, the customer team puts together a prioritized list (feature backlog) of desired features for the upcoming product release. The release is broken into iterations, and the team and customer agree on what will be delivered at the start of each iteration (no sooner). The iteration is of fixed length, something that allows the team to begin gathering consistent data, which in turn they feed back into their estimates and subsequently a larger plan. Upon incrementing and iterating the software a few times, the software reaches a state that it may be released to the customer. Does the system implement the agreed-upon features (did it pass all of its acceptance tests)? Yes: Release to production!
The flow outlined above is a reasonable starting point for a team transitioning to agile. It represents a kind of "Shu" in the Shu-Ha-Ri cycle, where one follows a certain technique or style for a while to build up their ability to perform it. In fact, both of us started with this basic pattern and found that it worked just fine.
As you move to more "Ha" stage, you might experiment with reducing the size of stories so that more of them are done and "in the can" before the end of the iteration. You might work on making the software releasable at every iteration boundary. You might shorten your iteration period so you can gather data more often, provide smaller increments to certification, and get feedback from users more quickly. You might pick fewer stories per iteration. You may experiment with self-organizing to get work done. It is a waste to spend a lot of time detailing features which may be done in the remote future or not at all, so you may reduce the entire feature backlog to perhaps a handful of stories. You may learn (as Deming recommends) to use more effective quality practices and eliminate a "certification" stage, as indeed many software shops are doing (research topic: continual release).
Once you are into the Ha and the Ri stages, using agile principles and values should lead you to more informal yet more effective approaches. Here's an "agile flow" card for the more seasoned agile team:
In a bit more detail:
- The customer describes a small subset of needs orally, to the team.
- Through negotiation with the customer, the team commits to completing code that satisfies some, most, or all those needs in a given period.
- The team agrees on a working set of rules that define how they will deliver quality code, under good, sustainable working conditions, in the specified period. (Hint: The team might use retrospectives to help derive and tweak the rules.)
- Repeat. This magic word allows the introduction of things like projects containing releases, and releases containing iterations. Or not.
Acceptance Test Design Principles
Jeff Langr and Tim Ottinger
Acceptance tests (ATs) are as enduring and important an artifact as your code. The proper design of each will minimize maintenance efforts. You'll recognize some familiar concepts--Kent Beck's rules for simple design and some classic OO principles apply well to the design of acceptance tests.
Abstract. A test is readable as a document describing system behavior. Uncle Bob's definition for abstraction applies equally well to tests: Amplify your test's essential elements, and bury its irrelevant details and clutter. Anyone, including non-DBA and non-programming staff, should be able to follow the steps taken in the test, and understand why it passes. Extracting duplicate behavior to a common place--the AT analog of programming's extract method--is the main workhorse that allows you to increase abstraction at the same time you remove duplication.
Bona fide. To ensure continual customer trust, a test must always truly exercise a system as close to production as possible. Passing acceptance tests tell the customer that what they asked for is complete and working. But once the customer has doubt as to what your tests exercise, you have severely damaged your ability to continue using them as contracts for completion.
Cohesive. A test expresses one goal accomplished by interacting with the system. Don't prematurely optimize by combining multiple scenarios into a single test. Keep single-goal tests simple by splitting common content into separate fixtures. Yes, this will mean your acceptance test suite runs more slowly, but it's far more important to avoid compromising clean test design. (It's also why your unit test suites should be as fast as possible.)
Decoupled. Each test stands on its own, not depending upon or being impacted by results of other tests. A failure caused by problems in another test can be difficult to decipher.
Expressive. A test is highly readable as documentation, not requiring research to understand. Name it according to the goal it achieves. As with unit tests, refactor each test to improve the ability of a third party to understand its intent. You should always eliminate magic numbers, replacing them with constants as appropriate. Improve visual accessibility by formatting your test using Arrange-Act-Assert (AAA). You should also make it clear what context is being set up in the test; one way is to incorporate additional assertions that act as preconditions.
Free of duplication. Eliminate duplication across tests (and even within the same test) before it eliminates you! Duplication increases risk and cost, particularly when changes to frequently-copied behavior ripple through dozens or more tests. Duplication also reduces the use of abstraction, making tests more dense and difficult to follow.
Green. Once a story is complete, its associated ATs must always pass. A failing AT should trigger a stop-the-line mentality. Don't allow your test suite to fall into disarray by allowing failures to be ignored!
Acceptance tests (ATs) are as enduring and important an artifact as your code. The proper design of each will minimize maintenance efforts. You'll recognize some familiar concepts--Kent Beck's rules for simple design and some classic OO principles apply well to the design of acceptance tests.
Abstract. A test is readable as a document describing system behavior. Uncle Bob's definition for abstraction applies equally well to tests: Amplify your test's essential elements, and bury its irrelevant details and clutter. Anyone, including non-DBA and non-programming staff, should be able to follow the steps taken in the test, and understand why it passes. Extracting duplicate behavior to a common place--the AT analog of programming's extract method--is the main workhorse that allows you to increase abstraction at the same time you remove duplication.
Bona fide. To ensure continual customer trust, a test must always truly exercise a system as close to production as possible. Passing acceptance tests tell the customer that what they asked for is complete and working. But once the customer has doubt as to what your tests exercise, you have severely damaged your ability to continue using them as contracts for completion.
Cohesive. A test expresses one goal accomplished by interacting with the system. Don't prematurely optimize by combining multiple scenarios into a single test. Keep single-goal tests simple by splitting common content into separate fixtures. Yes, this will mean your acceptance test suite runs more slowly, but it's far more important to avoid compromising clean test design. (It's also why your unit test suites should be as fast as possible.)
Decoupled. Each test stands on its own, not depending upon or being impacted by results of other tests. A failure caused by problems in another test can be difficult to decipher.
Expressive. A test is highly readable as documentation, not requiring research to understand. Name it according to the goal it achieves. As with unit tests, refactor each test to improve the ability of a third party to understand its intent. You should always eliminate magic numbers, replacing them with constants as appropriate. Improve visual accessibility by formatting your test using Arrange-Act-Assert (AAA). You should also make it clear what context is being set up in the test; one way is to incorporate additional assertions that act as preconditions.
Free of duplication. Eliminate duplication across tests (and even within the same test) before it eliminates you! Duplication increases risk and cost, particularly when changes to frequently-copied behavior ripple through dozens or more tests. Duplication also reduces the use of abstraction, making tests more dense and difficult to follow.
Green. Once a story is complete, its associated ATs must always pass. A failing AT should trigger a stop-the-line mentality. Don't allow your test suite to fall into disarray by allowing failures to be ignored!
Agile Success Factors
Jeff Langr and Tim Ottinger
Font: Brown Bag Lunch
Pop quiz, hotshot.
Q. "You're not agile if you don't ... "
A. Select one more of the following:
| a. | Have daily stand-up meetings | |
| b. | Pair program | |
| c. | Do TDD | |
| d. | Employ a metaphor | |
| e. | Have a ScrumMaster | |
| f. | Run iteration planning meetings | |
| g. | Use index cards |
The answer is H, none of the above. Practices are just that--specific techniques a team might or might not employ to aid them in being agile--whatever agile means. Here's our definition: Agility means you are able to frequently and continually deliver high-quality software that meets the customer's needs.
The agile manifesto lays out four core values ("working software over comprehensive documentation," e.g.) and a dozen or so principles. But what factors truly make an agile team successful?
Freedom to change. Incremental change, one of the other success factors, can only occur if your teamis able to change how they work without outside interference. Meddling and micromanaging, never mind the intentions, usually divert the team from what should be everyone's goal of shipping quality software. Get the right people in place in your organization to support the team's rightful decisions, and to not try to change them. We'll be blunt: Conversely, this may mean removing the wrong people from the chain of influence.
Energized team. The successful agile team just gets it. They want to work this way. We can walk into a room and generally see whether or not a team will succeed. A good team is highly transparent and visibly enjoying what they're doing. They've built a true team spirit, and no one talks about "my code" or "my stories." They collaborate without being told; they hold their own stand-ups without a project manager having to crack the whip. They always act to protect the product and its integrity--they don't discard quality controls even when under intense pressure to deliver. They also look for ways to make life better for everyone--"How can I rework this test so that the next developer will understand my intent?" They'll step in and help anyone as needed to deliver quality product, even if it's "not their job."
While we like to think a good, energized team is all it should take, lack of freedom to change will demoralize even the best teams, to the point where your guys who "get it" choose to move on to something less oppressive.
Commo (line of communication) to customer. A product is an intricately detailed ship that must be well understood and constantly steered. The best teams we've seen have been steered by a strong, enthusiastic single-person, dedicated customer who truly understands what needs to be built. This customer has the time to ensure that everyone else can learn from them what needs to be built. While the strong customer can have a supporting cast, a large, committee-style product management team simply doesn't work. (It's always unfathomable to us that most companies are willing to staff development teams with no end of apathetic dregs, but are unwilling to pay well for strong people who know what product to build.)
Attention to quality. The code is your product, and, unlike most other products, one you will continually build on and shape to meet continual new customer demand. If you fail to pay attention to quality, you will eventually slow down in your ability to meet demand, sometimes to the point of stagnation. The team must ensure that the code is clean enough to accommodate new incremental customer needs. Attention to quality is never a separate task on a plan; it must be embodied in everything you do to build your product, including coding, design, documentation, testing, automation, tracking, communication, and so on. Quality must be incrementally and continually addressed.
Incrementalism Most of the practices you employ in agile have something to do with ever-smaller steps. Instead of a massive requirements document, you allow the customer to provide features just in time, in small chunks described on little index cards. Instead of a comprehensive up-front design document, you learn how to design on a task-by-task and test-by-test basis. And so on. You must learn to think incrementally.
You must also look to correct course continually and incrementally. For every few lines of code added or changed, take time to ensure the design is as good as you can get it. (Which you can only do if you have enough controls in place to allow frequent code improvement. Best way we know how to get there: TDD.) Not only do you need to correct course in the product, you need to always correct course in your team. You should always be introspecting about your team, probing for ways it's not performing optimally, and working to correct these problems. Retrospectives are a good start.
A successful agile project is not a bunch of hare-like sprints to the finish line. It is a cool-headed, tortoise-like, slow 'n' steady approach of small, well-reasoned steps. Each step is an opportunity to look up and see where it got you--closer to the finish line or further away? It's easy to correct a single misstep. In contrast, a single mad sprint in the wrong direction can take you pretty far off course from the finish line.
Automation. There are numerous ways to waste people's time on a software development effort--running automatable regression tests manually, for example, or suffering a build process that unnecessarily requires multiple manual steps or manual verification. Agile cannot work unless you automate as many menial, tedious, and error-prone tasks as possible. There's simply not enough time across a two-week period to get any real work done if you have to slow down for numerous manual gating processes.
Information Radiators
Tim Ottinger and Jeff Langr
Font: Brown Bag Lunch
In keeping with the agile value of Communication, agile teams often place large charts and graphs in their workspaces to radiate important information such as defect rates, rate of completion, and measures of code goodness (CRC, bugs, test counts). Much is made of Informative Workspaces or Big Visible Charts (BVCs).
You'll find numerous graph types in the agile literature. Some types, such as burn-up, burn-down, and cumulative flow are commonly used to graph progress against a goal such as an epic story. Defects and velocity are also useful things to track, but don't limit yourself. Let your team determine--and let these information radiator principles guide--what you track and publicize.
- Simple
A chart or graph should not require minutes or hours of study. Ensure it is brief and concise. Anything dense or complicated will fail to communicate. Also, don't use highly derivative, biased, weighted information. Simple facts speak more profoundly than clever algorithms. - Stark
BVCs don't exist to convince the public of your team's excellence. Nor should you mask errors or problems with them. The purpose of the graphs is to display progress and expose problems. Don't subvert the honesty of the graphs, otherwise your team will stop trusting them, and therefore stop using them to improve their work.
- Current
Any information that is not kept current is quickly ignored. You may want to have the CI build graphs based on automatically-generated stats. Information more than a few days old is too stale to have evocative powers. - Transient
Radiators that only expose problems shouldn't be up there long, otherwise it's clear that you aren't solving your problems. Choose a BVC to highlight a current challenge for which you can demonstrably show improvement over the next several days or iterations. Once it's clear the team has gotten the message, and things are back on track, take down the BVC.
- Influential
A good information radiator influences the team's daily work. It may also influence managers, customers, developers, or other stakeholders. Ideally it will empower the whole team to make better decisions, otherwise it is not worth preparing and presenting. - Highly visible
An effective information radiator needs to not only have information on it, but must transfer it to team members, stakeholders, and passers-by. - Minimal in number
Having too many graphs or charts will cause all of the charts to lose evocative power. Also, exposing too many problems on the wall at one time can demoralize any team, so choose either the most important, timely, or fixable problem to highlight, and defer the rest. Sometimes less truly is more.
Development Iteration
Jeff Langr and Tim Ottinger
Font: Brown Bag Lunch
These half-dozen items provide the core set of principles around the iteration workflow for delivering stories to an eager customer. (Most of the principles would also apply to a kanban environment, with a bit of tweaking.)
Team commits to stories they can complete. Each iteration begins with a short planning session. The primary goal of this session is to ensure that the development team (hereafter "the team" in this blog post) and customer are in sync on what the team will deliver by iteration end. The customer and team jointly produce acceptance criteria that act as the contract for completion. The team commits to only the set of stories they can confidently deliver by iteration end. The workload is thus fixed for the duration of the iteration, although the customer can negotiate a change to the workload with the team. Hopefully this occurs only rarely, and hopefully the team has the sense to insist on work being taken off the iteration's plate.
Team works stories from prioritized card wall. The customer is responsible for managing the flow of work. Their job is to ensure that available stories are presented in priority order. Available developers grab the card with highest priority and move it into an "in progress" bucket. The card wall, whether real or virtual, is visible to everyone involved in the project.
Team minimizes stories in process. Applying non-collaborative approaches to agile asks for the same, lame results you got from waterfall. A typical anti-pattern we've seen (we'll call it "Indivigile"): Every story is close to a full iteration in size, and each developer grabs their "own" story to work on. So much for any of the significant benefits that you might have gained from collaboration (primarily better solutions, increased mindshare, and thus minimized risk). Worse, you dramatically increase the probability that stories will not be delivered by iteration end. A better approach: Team members work on the smallest sensible number of stories at one time, maximizing collaboration and ensuring that each story is truly done before moving on to the next.
Following this approach, you should see almost half of the committed stories 100% complete by midway through the iteration. Overall, the number of stories fully complete by iteration end should increase. Also, many activities that would have otherwise been blocked until iteration end can start earlier (additional testing, clarification/correction, documentation, etc.).
Team collaborates daily. A daily stand-up meeting is a good start for getting the team on the same page, but never sufficient. If the stories-in-process are few, the team must find ways to collaborate frequently throughout each day, to avoid wasting additional time.
Customer accepts only completed stories. Stories must pass all programmer and acceptance tests before the customer looks at the the software. The customer needs to play hard-ball at this point: Any story shy of 100% passing gets the team zero credit: Incomplete work provides no business value. The lesson for the team to learn (and apply in subsequent iterations) is to not over-commit.
Team reflects on iteration and commits to improvements. Agile is built around frequent incremental delivery, in order to maximize feedback, which in turn provides opportunities to improve. Iterations are not only opportunity points to improve the product, but also for the team to reflect on what the team needs to change, whether to improve quality, throughput (which improving quality will do), team morale, or any other execution concerns that the team recognizes. See our Retrospectives card for guidance on this critical agile practice.
Everything else that happens with respect to iteration execution is "implementation details," and thus up to your team to determine. We don't care if you use software tools or physical card walls. We don't care if your team is distributed, whether you run a formal stand-up meeting, whether you use velocity, planning poker, load factors, yesterday's weather, Scrum Master whip cracking, or any other specific practices for planning and organization. All is generally good as long as you adhere to the above principles for flowing work.
Why Agile?
Source: Tim Ottinger, Jeff Langr
Font: Erwin
We've talked about what agile development is, how to do it, and why people object to it, but the big question that remains is "Why Go Agile At All?" If you or your employer are considering a conversion to agile, you should know what to expect from the change.
Agile is a work system, not just a style of writing code or a set of tracking tools. It is a very disciplined and orderly way to work, and it is also a lot of fun. It is intense, requiring a high degree of personal involvement (which is why Agile teams cap their work weeks at roughly 40 hours).
The most common reason does not appear on the list above, "What we were doing was not working." That is a reason to change from what you were doing, but not necessarily a reason to change to anything in particular. If you are considering a change, consider whether you want the qualities listed here enough to give Scrum and/or XP a shot.
Font: Erwin
We've talked about what agile development is, how to do it, and why people object to it, but the big question that remains is "Why Go Agile At All?" If you or your employer are considering a conversion to agile, you should know what to expect from the change.
Agile is a work system, not just a style of writing code or a set of tracking tools. It is a very disciplined and orderly way to work, and it is also a lot of fun. It is intense, requiring a high degree of personal involvement (which is why Agile teams cap their work weeks at roughly 40 hours).
- Improve Customer Involvement Agile methods put the customer in the drivers' seat. Customers choose which bit of functionality comes next, and when a feature is complete enough for their needs. Agile is intentionally customer-intimate, so customers and developers (including testers, tech writing, and customers) are on the same team. It is a strong alternative to an adversarial relationship
- Increase Quality Agile depends heavily on testing, both at the acceptance test level and at the unit test level. Tests are written constantly and run constantly. The legacy code you have lying about in piles may not be amenable to testing, so expect some early delays as the team converts it. These delays are more than offset by the lack of bugs (and days lost to bug-finding research) a few months down the road. Improved quality results in fewer customer complaints, reducing support costs.
- Simplify Releases Agile teams release early and often, and try to maintain their code base in a perpetually-releasable state. Tests and Continuous Integration ensure you don't have long dark times when the code does not run. Periodic integration hell and mad release rush are reduced, even eliminated.
- Increase Operational Awareness Agile teams keep their work-in-progress to a minimum, and track their progress on visible charts and the kanban wall. One can walk into the group work area and tell what tasks are in progress and how close they are to being completed. You can glance at a burn-down or burn-up and tell how close the team is to completing some critical functionality. It is an orderly and visible work system.
- Drive Down Risk
Agile teams work in tiny increments of functionality, not huge end-all features. This allows them to have working software ready early on. They do not necessarily produce software faster than non-agile shops, but it is in a usable state earlier. This means that the software can be used while it is being developed. It might even pay for itself.
Because software is usable so soon, features are assessed sooner. The Customer can see immediately if they are really as useful as he expected. Corrective steering is possible. There is a greatly reduced risk of building the wrong thing, or a gold-plated excess of the right thing.
- Reconnect With Geek Joy Boy, did I ever detest sitting through all-day meetings debating use cases or refining requirements documents in the name of JAD or RAD or RUP or whatever. Agile focuses on getting things done well and often, which according to studies is the primary factor that drives job satisfaction. Having working code nearly at all times is empowering. Having tests to rely upon is comforting. Having steady progress is refreshing. It is great to be making real progress (learning and coding) all of the time. It's why many of us chose this vocation.
The most common reason does not appear on the list above, "What we were doing was not working." That is a reason to change from what you were doing, but not necessarily a reason to change to anything in particular. If you are considering a change, consider whether you want the qualities listed here enough to give Scrum and/or XP a shot.
The Only Agile Tools You'll Ever Need
Source: Tim Ottinger and Jeff Langr
Font: BrownBagLunch
Font: BrownBagLunch
Perhaps you were expecting a list of software products?
Agile's raison_d'être stems from backlash against "heavyweight" methodologies that insisted upon voluminous documentation, never-ending and never-useful meetings, and vendor-lovin' high end tools. Yet in 2010, there are at least three major high-price, high-profile agile project management tools and dozens of lower-end ones.
We contend that using one of these expensive software tools says, "you don't get it, and maybe shouldn't bother, because agile may not work well for you." No doubt this will perturb those of you who have found some value in agile management tools, so let's step back and talk through the issues.
Agile is primarily about team communication and collaboration. It is predicated on continual face-to-face interaction. Every step in the opposite direction decreases the chance of success. Kent Beck had it right: The best opportunity for success, still, is having all project members sit in a single room and work as a team, instead letting a bunch of self-interested individuals retreat to the isolated comfort of their cube.
There is no room in agile development for "avoidance technology." If you can't find a way to meet its demand for close-contact, continuous communication, then you are not ready. If you don't want your programmers sitting together, talking through problems, writing code socially, then try something else. Attempting to bolt avoidance technology onto agile methods is like castrating a stud horse.
Once you diminish teamwork, you have to compromise other agile principles. If we're not in the same room, we need more meetings to talk to one another. We need to write more things down and produce more centrally-stored documentation. We need to have more contractually-oriented agreements between people who really work on the same team, because we can't trust one another, because we're can't see each other face-to-face every day. The agile practices topple like dominoes.
There is always questionable rationale about why things must be that way. "Every project has to be split evenly between low-cost [read: offshore] labor and high-cost [local] labor." That's not a definition of project success, just a broad-brush attempt at cost control. Having some remote team members should never force all team members to work as if they were remote.
Perhaps the executives could use their hard-won corporate smarts to organize the teams differently. "Half our projects must be low-cost" should appease the bean-counters, and could just work. Here come the excuses: "But we don't have business experts who can act as customers in Bangalore." Really, that's a problem you can't solve? Having two truly agile teams producing quality code should be better than having two teams pretending to be, and failing at, agile.
If you want to succeed at agile, find a way to put each team in its own room. Give them the tools we list on the card, and they'll rarely ask for more. We guarantee they won't ask for a high-end agile tool, because they don't need one and don't want to be bothered with one. Executives of various stripes might ask for one, but all they really want is a simple way to view and present status across significant numbers of projects. You don't need a high-end, specialized, complex tool to do that, and you definitely don't need to waste the time of everyone across every agile team to do that (hint: see Tracker and Coordinator on Agile Roles card. This is what you pay project managers to do).
Agile's raison_d'être stems from backlash against "heavyweight" methodologies that insisted upon voluminous documentation, never-ending and never-useful meetings, and vendor-lovin' high end tools. Yet in 2010, there are at least three major high-price, high-profile agile project management tools and dozens of lower-end ones.
We contend that using one of these expensive software tools says, "you don't get it, and maybe shouldn't bother, because agile may not work well for you." No doubt this will perturb those of you who have found some value in agile management tools, so let's step back and talk through the issues.
Agile is primarily about team communication and collaboration. It is predicated on continual face-to-face interaction. Every step in the opposite direction decreases the chance of success. Kent Beck had it right: The best opportunity for success, still, is having all project members sit in a single room and work as a team, instead letting a bunch of self-interested individuals retreat to the isolated comfort of their cube.
There is no room in agile development for "avoidance technology." If you can't find a way to meet its demand for close-contact, continuous communication, then you are not ready. If you don't want your programmers sitting together, talking through problems, writing code socially, then try something else. Attempting to bolt avoidance technology onto agile methods is like castrating a stud horse.
Once you diminish teamwork, you have to compromise other agile principles. If we're not in the same room, we need more meetings to talk to one another. We need to write more things down and produce more centrally-stored documentation. We need to have more contractually-oriented agreements between people who really work on the same team, because we can't trust one another, because we're can't see each other face-to-face every day. The agile practices topple like dominoes.
There is always questionable rationale about why things must be that way. "Every project has to be split evenly between low-cost [read: offshore] labor and high-cost [local] labor." That's not a definition of project success, just a broad-brush attempt at cost control. Having some remote team members should never force all team members to work as if they were remote.
Perhaps the executives could use their hard-won corporate smarts to organize the teams differently. "Half our projects must be low-cost" should appease the bean-counters, and could just work. Here come the excuses: "But we don't have business experts who can act as customers in Bangalore." Really, that's a problem you can't solve? Having two truly agile teams producing quality code should be better than having two teams pretending to be, and failing at, agile.
If you want to succeed at agile, find a way to put each team in its own room. Give them the tools we list on the card, and they'll rarely ask for more. We guarantee they won't ask for a high-end agile tool, because they don't need one and don't want to be bothered with one. Executives of various stripes might ask for one, but all they really want is a simple way to view and present status across significant numbers of projects. You don't need a high-end, specialized, complex tool to do that, and you definitely don't need to waste the time of everyone across every agile team to do that (hint: see Tracker and Coordinator on Agile Roles card. This is what you pay project managers to do).
Agile Roles
Some of you might be surprised that there are no farm animals on this card. We'll talk about that later.
You'll also note that each role definition is preceded with the word "helps." Everyone on an agile team can act as any role at any given time, helping the team toward its ultimate goal of producing quality product.
In agile, roles are just that, roles. We don't look to protect our role from being usurped. While we are most comfortable playing in our primary role, we have no qualms about stepping into other roles as needed or appropriate. A tester might act as a tracker to gather useful team metrics; a programmer might assist the customer and testers in defining acceptance criteria for a story; a manager might help execute any remaining manual acceptance tests; and so on.
Extreme Programming (XP) originally designated two roles, programmer and customer (for whom XP described little--it is extreme programming after all). Each camp had specific rights, to protect each camp's interests against likely infringements by the other. A bit divisive? Indeed. You will be hard-pressed to find much remaining literature that mentions "XP Rights."
Within the programmer camp, XP eschewed specialists and hierarchies, fostering instead experts and team collaboration. But things other than programming and steering as a customer still needed to be done. Various adjunct needs, such as coaching and tracking, emerged. Who would do these things? These part-time needs were fulfilled by XP team members (customers or programmers) shifting in and out of secondary roles.
Proponents of Scrum (which predates XP a bit) were never so trusting in a teams' ability to self-manage, so they introduced the Scrum master, whose job is to keep the team on track. As for XP, the reality of human behavior brought its lofty goals down a peg, more so as Agile took off. Organizational interests and self-preservation took over. The concept of a self-organizing, title-ignoring team threatened HR, project managers, managers, and others who had vested interests in promoting and maintaining specific titles. In an attempt to keep us from falling back into isolationist and divisive behavior, Kent Beck began referring to the collection of all team members as "the whole team," instead of discussing specific roles.
Today, the agile organization doesn't usually look terribly different than the pre-agile organization, except within some programming teams. You'll still hear long-standing, specific names for specific customer roles, such as "business analyst," "product manager," "UI design specialist," "subject matter expert (SME)," and "stakeholder." But on the programming side of the fence, a team working within an open workspace and pairing usually has lost any real concern over titles and artificial divisions such as "front end programmer vs. back-end programmer." Since these roles are temporary, it is futile and undesirable to to tie hierarchical positions or increased benefits to them.
It is best for us to concentrate more on putting out quality product, and least on relative positions. We understand that it may not be realistic in your organization to shed your title, but you should still consider the ego-less organization a general direction to move toward. Sometimes simply thinking that there are no titles can help you find an answer to your problems.
Astute readers will note that "manager," "project manager," and "Scrum Master" do not appear on this list. We have instead substituted "team coordinator," someone who buffers the day-to-day development team from outside interference and distraction. A team coordinator can communicate scheduling issues, handle incoming requests, and smooth interpersonal problems. Within Scrum, this team coordinator also takes on the responsibility of enforcing the rules, something that a team is certainly capable of doing on their own. We suggest that the best Scrum Masters plan their own obsolescence: Their primary job should be to help us mature to the point where the team no longer needs a Scrum Master.
The lack of official leaders and managers in agile is off-putting to some. We've noted that most software teams do not suffer from a shortage of management, but a drastic overage as different departments try to exert control over the isolated "programmers" and "testers." In an agile team we come together as a team, and the work has us busy enough that little traditional management is necessary.
As far as the chicken and pig roles that some of you might have expected to see on this card: Everyone we've met on a well-functioning agile team has been unsurprisingly human. We don't believe people who might have something important to say should be stifled. If someone says inappropriate things at inappropriate times, we muster the courage to ask them to take it elsewhere. "Chicken" was deliberately chosen as a derisive moniker, the spirit of which has no place on a real team. (We quote Jeff Sutherland here, because his original blog post has been archived and may soon rightfully be buried entirely: "People who are not committed to the project and are not accountable for deliverables at the meeting do not get to talk. They are excess overhead for the meeting. ... Whatever we call them it should have a negative connotation because they tend to sap productivity. They are really suckers or parasites that live off the work of others. Sorry to be political [sic] incorrect but others should come up with a euphemism that conveys the right balance between being "nice" and communicating clearly that eavesdroppers must minimize their impact on the productivity of the team." Perhaps the goal is laudable, but the sentiment is so wrong as to be repulsive.)
Test Double Troubles
- Inhibited Refactoring. Mock-based tests must have special knowledge of a class' interactions with its collaborators. We gladly accept this special role of tests, as it allows us to test otherwise impenetrable code. By testing interactions, however, we create dependencies on design structure. Refactoring changes the structure of code, which breaks naïve structure-dependent tests. Tests that extensively use test doubles can exhibit structure-sensitive breakages which dissuade programmers from refactoring. Fear of refactoring is death to system evolution.
A proper unit test should have a clear intent, signaled by the name, and should read as though it is explaining the code. To a certain extent, though, the test will rephrase or paraphrase the system under test. If the system under test is not structure-shy, then the mock-enabled tests will also not be structure-shy. In general, the tests should be as simple as you want the code to be.
A test with extensive mock setup signals a class with many dependencies or too little encapsulation. A class designed with the Law Of Demeter in mind will be structure-shy, making it more cleanly and easily tested with partial mocks.
- Tool complexity. Third party mock libraries like Rhino Mocks and Mockito are getting better at allowing you to write expressive tests, but they all introduce complexity. You must first learn a tool's extensive API and unique view of mock usage, which can include subtle nuances around things like partial mocks and void methods. Some tools even support multiple styles of mocking, each with its own special syntax. You must also learn how to read often-idiomatic code required to implement these various nuanced mock recipes.
Refactor tests to eliminate redundant test double detail*. Good tests require high levels of abstraction, emphasizing readability and de-emphasizing mock implementation details. Extract the idiomatic, tool-dependent code to small, declaratively-named helper methods. - Passing tests that indicate nothing. A naive mock-based test may tell you that function X is called twice, and function Y is called once, but it does not tell you if you have a good design or even if you will get a good result. A heavily-mocked test suite may not behave in the same way that the underlying code will behave in production. It may have assumptions about handling of nulls or exceptions that are not coherent with production code. Worse yet, a test generated via 'tracer bullet' method may exercise a class or method but provide no useful information or evidence of correctness.
A proper unit test is more than function counting. To combat unrealistic mock scenarios, examine the code as-written to determine weaknesses that can be simulated and explained in further tests. Avoid writing tests that are mere exercises of code, and have no clear intent. - Testing mocks rather than the SUT. In a maze of test doubles, stubs, mocks, and partial mocks, one can become lost in the entanglement between tests and production code. A feature may appear covered by tests, all passing, but fails in production. Deeper exploration reveals that someone unwittingly replaced the method being tested with a stub. This always happens in subtle and indirect ways, and always results in face-palming.
It is important to be careful when mock setup has been extracted from test methods. One may not be aware that the method under test has been replaced by a mock in some shared setup method. Avoid using stubs that are distanced from the direct class target of a test. - Low readability. Tests can require significant amounts of detailed setup ("record") and verification ("expect"). Such clutter makes it hard to tell which expectations are simulation-enabling and which are the crucial assertions of the test.
The primary goal of test doubles is to emulate collaborators in as simple a fashion as possible. Well-designed test doubles have virtually no logic, and well-designed classes only directly interact with a few collaborators. When interactions are many and span many classes it is because the system under test is too structure-sensitive. Refactoring the system under test to be structure-shy will help reduce the number of collaborators that demand mocking, which in turn will simplify its test. Extracting methods which interact with other classes or APIs will allow effective use of partial-mocking. - Ambitious mock implementations. Fakes--objects that completely emulate all aspects of a collaborator--require implementing redundant behavior, which sometimes requires involved logic. The problem with real logic, as opposed to simple stubbed methods, is that it's easy to screw up. Recently both of us have been working with code that uses a massive faking scheme, and both of us have wasted considerable time in implementing, deciphering, and debugging the fakes.
If you have many tests that require variant test double behaviors for a single collaborator, absolutely resist the temptation to combine these into a "mock mother." One mock, one behavior. Combining behaviors into a single test double class will quickly lead you down the divergent path of maintaining mocks for a living. Keep your test doubles simple and discrete! - Vendor dependency. You'd think we would have learned our lesson years ago. We created Java systems that rampantly interacted with JDBC (an almost direct mapping to SQL statements). Most of us moved to APIs that provided higher levels of abstraction, such as JDO, entity beans, and Hibernate. That transition was painful, mostly because of the highly-redundant, highly vendor-dependent code that we allowed to seep into hundreds of classes and thousands of methods.
Mock tools are no different. Some of you chose RMock several years ago, and some of you probably feel that you're stuck with it due to its pervasive use in your system's tests. Too bad. Mockito is a great tool, but we imagine a better one will come along when Java finally sports closures (Java 8? 9? ...). We want to transition to this new tool without so much pain.
The recommendation is, once again, devise small, cohesive methods that encapsulate mock tool details.
Subscribe to:
Posts (Atom)

