Tim Ottinger & Jeff Langr present the blog behind the versatile
Pragmatic Programmers reference cards.
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.
Mock Terminology
By Jeff Langr and Tim Ottinger
Font: BrownBagLunch
Well, the title of this post is just wrong. The generic term for "things we use in testing to emulate production behavior" is test double, not mock. The casual programmer may bandy about the term mock when they mean test double, but it is technically incorrect and may lead to misinterpretation. We've never seen it make much of a difference to the end result of a programming conversation, but there are distinct definitions for the various implementations and uses of test doubles.
The term mock object stems from a 1999 paper by Tim Mackinnon, Steve Freeman, and Philip Craig, "Endo Testing: Unit Testing With Mock Objects." The authors' simple definition: "a substitute implementation to emulate or instrument other domain code." Mocks, or whatever you might call them in 2010, still serve the same purpose.
Use of mock objects in TDD circles grew dramatically over the next several years. Debate grew dramatically, too. The community debated about (a) whether or not to use them at all, (b) in what situations they were most appropriate, and (c) whether or not to use one of the mock tools that were starting to proliferate and pro-create.
In 2006, Gerard Meszaros published the book XUnit Patterns, which enshrined a handful of nuanced terms for the various kinds of test doubles. These terms had been shopped around in various agile forums for some time leading up to publication of the XUnit Patterns book. Today the taxonomy is commonly accepted by programmers and mock frameworks alike (oops, but "mock frameworks" itself is a misnomer, as these frameworks usually support all sorts of test doubles, not just mocks).
- Test Double is the generic term, the phylum for all our species of testing dopplegangers.
- Stub - An object that returns a specific, fixed value to the system under test (SUT). Stubs are usually constrained to a small subset of methods defined on a collaborating class. "When someone calls the
pricemethod, return the value 9.99." - Fake - An object that completely emulates its production equivalent. The classic example of a fake is a lightweight, in-memory "database" object that allows for simple, fast emulation of a relational database interface.
- Mock - An object that self-verifies. A mock asserts that information sent to it is as expected. A test that uses a mock defines and verifies this expectation.
- Partial mock - An object that contains a mixture of production method implementations and mock method implementations. Partial mocks are generally used when you need to emulate non-existent behavior (i.e. abstract methods) or troublesome behavior defined on the same class you are testing, something that might indicate questionable design.
- Spy - An object that simply captures messages sent to it, so that the test can later verify that the SUT interacted correctly with its collaborator.
So, where do we stand on the debate? (a) Yes, use test doubles (b) when you must, (c) and use a tool if it makes things easier or clearer. Next time, we'll talk about more important things, such as what pitfalls to avoid when working with test doubles.
Organizational Objections To Agile Process

By Jeff Langr and Tim Ottinger
Font is Andrew Script
It is no surprise that organizations struggle when attempting to transition to agile methods. As with any new venture that threatens the status quo, the list of objections is long and varied. In developing this card we collected over a hundred typical sentiments and grouped them into about a dozen categories--too many for a single card. In keeping with our personal vows of brevity, we present here the first card: Objections borne out of organizational and cultural circumstances. We will present reasons that stem from individual belief systems and biases separately.
In order to help transitional consultants and rank-and-file people who are struggling, we provide commentary and counter-arguments.
- "It Can't Work Here" There is a common assumption that Agile methods require a special set of initial conditions. Most companies believe that their own situation is unique, their software uniquely complex, their market position too tenuous, or their management system too inflexible. Given such specialized initial conditions, how could a general-purpose method based on simplicity possibly work?
Agile is not so much a set of a constraints and rules as it is a framework in which a team can continually discover its own limitations and then derive better approaches. There are few necessary initial conditions beyond an agreement to work together in an incremental and iterative way.
- "They Won't Let Us" is a special condition of "It Can't Work Here." Agile methods may be deemed feasible and even advantageous among the technical crowd, but may seem counter to the organizational culture and/or management habit. For instance, there may be a competitive personnel evaluation system for staff which frustrates attempts at collaboration. The management might have a strong command-and-control model which prevents self-organization. Perhaps the organization is built upon the concept of a strong lead programmer directing a squad of "code monkeys." Maybe schedule pressures are so great that there is no slack to spend on organizational learning. It may be that the team cannot modify the layout of the office due to union issues or concern for decor.
Agile methods are advantageous to development and product management since they provide more data about the team's real progress, allow better focus on important features, and require very limited limited overhead to practice. While some aspects of Agile practice are clearly focused on management practices and product management strategies, an increasingly capable team can usually cope with difficult organizational practices in the short term and can win over leaders in the long run. - "Guilt By Association" refers to the situation where Agile methods have not been tried, but at first blush seem to resemble other methods or practices that have fallen from favor. Sometimes Agile is associated with uncontrolled "cowboy coding." Other times Agile is perceived as a trick by management to force programmers to work harder. It may be confused with ceremony-heavy consulting-driven methodology. The poor image is often tarnished further by tool vendors hoping to cash in on the latest buzz with tools that are rarely necessary, of limited helpfulness, hard to learn, tedious to use, or even detrimental to collaboration and communication. An Agile conversion project may follow on the heels of other failed "flavor of the month" methodology attempts.
Agile is a low-ceremony, disciplined way of working built on concepts and ideas that have been successfully applied in the software industry for many decades, and longer in other industries that still embrace these principles today. It is a simple, incremental approach to team software development that requires little tooling beyond a place to sit, a whiteboard, a good supply of index cards, and a few rolls of tape. It would be a shame if an unfair prejudice caused us to miss out on an opportunity to build a truly great team.
- "Means/Ends Juxtaposition" is a variation on "cargo cult" mentality. A typical non-agile company will have layers of policy and management practices built on strict phase separation, copious up-front documentation, individual accountability, rigidly-defined hierarchical roles, and/or tail-end quality control processes. Artifacts produced by these practices become the primary output of teams, and enforcing mandated behaviors becomes the primary concern of managers, even though neither contribute meaningfully to quality software development.
An organization attempting to transition to agile may fall into the same trap by rigidly applying so-called agile practices. Numerous teams claim (capital-A) "Agility" because they hold interminable feckless retrospectives, prescribe stand-up meetings that provide only vertical status, or prolong interminable pair "marriages." Stand-ups, retrospectives, and pairing are extremely valuable tools, but only if you are able to align them with agile values and principles.
To succeed at agile, we must first understand that it is a continual journey of team discovery, and not a rigid set of practices. We must have some sense of where we want agile to take us, and that the journey will reveal unforeseen challenges and opportunities. Agile development is about growth rather than conformity.
- "Inferiority Complex" The team that ships quality software on a consistent and frequent basis exhibits a high level of confidence. A team that lives with frequent failure and inability to estimate quality of product will exhibit a low level of confidence. An observer may attribute the confidence and ability of the team as an initial condition and not as an eventual outcome of the process, surmising that confident superstars are a necessary initial condition of agile success.
The Pareto distribution suggests that most teams simply don't have enough star developers to conquer this mistaken understanding of agile. Real concerns over minimizing entropy in a rapidly changing system engender pure fright: "How can we possibly introduce new features without pre-conceiving the entire design? Our code is horrible to start with, and we've tried to write some unit tests, and it's just too hard." A large number of teams ultimately feel they lack the skill to produce anything of value in a short iteration.
Agile software development is about teamwork, not about superstars. For example, pair programming helps make TDD less difficult (for everyone, superstars and supernovices alike); TDD in turn provides us with the means to safely refactor code; refactoring sustains quality design in an extremely dynamic environment. Likewise, introspection and teamwork allow for continual improvement. Agile is a means to raise the competence of a team and lower the difficulty of working with a code base.
- "Superiority Complex" is when an organization feels that they have a pretty good handle on things. They have a process that has allowed them to deliver successfully in the past, and regard any change in practice as a step down. Practices like TDD and pair programming are regarded as training wheels for junior programmers, and wholly inappropriate for serious software professionals. They may believe that they have a special gift for up-front design that makes incremental design wasteful and unnecessary. The organization believes they have transcended the need for Agile practices.
There will always be those who think that the world has nothing left to teach them. If the organization is perfect, there are no flaws to uncover, no waste to reduce, and no improvements for agile to bring. Since agile methods are about doing, measuring, and reflecting on the work, we often find that Superiority Complex is based mostly in wishful thinking and a lack of measurement.
If, on the other hand, a company has found the techniques that leave Agile in the dust, we would love to learn about and adopt this superior method at work. Agile methods are perhaps not the best methods possible, only the best ones we know as of this writing.
- "Rejection of Insufficient Miracle" is the tendency to refuse to use a practice which leaves any current problems unsolved. "It's all or nothing, baby!" A team that cannot automate all testing sees little point in automating tests at all. Incremental development does not guarantee that a certain date will be met with all features in place, so there is no reason to iterate. The team must collaborate with other groups which do not work in an Agile way--what is the sense in only part of the company being agile? If we can't guarantee everyone will refactor the code, why should anyone spend the time cleaning up the design? By refusing incremental improvements, the organization rejects the very soul of the Agile way of working.
Samuel Johnson once said, "Nothing will ever be attempted if all possible objections must first be overcome." All software projects, even one that might be hypothesized to be free of technical error, are prone to failure from myriad reasons. All products, teams, and organizations are "insufficient miracles," leaving many of life's problems unsolved. Seeing that we have all gotten out of bed and come to the office, the question is whether we want to try a process that maximizes learning and quality (without guarantees), or an equally guarantee-free process that does not.
We fully recognize that there are teams that will not want to use Agile methods, and we suspect that there are organizations unwilling to modify their practices to accommodate a new style. We suspect that any method will not be successful in such organizations and that abandonment may be a reasonable strategy. As they say, "Change your company, or change your company."
In time, we may discover ways of fulfilling the promises of Agile with other methods. Agile is not the only possible way to improve an organization, even though we have found it to be one exceptional way to improve software-developing companies.
If, on the other hand, an organization is not interested in the kinds of benefits Agile methods promise (teamwork, growth, quality, productivity) we recommend that they become our competitors.
Branch Per Feature

Font: Mechanical pencil for body, Erwin for heading
Sources: Tim Ottinger, George Dinwiddie (via mail list), Jeff Langr
Branch-per-feature is a common SCM strategy in which a branch is created on a central server for each feature that is under development. As a feature is completed, the branch is integrated back into the main development code line.
In some organizations, releases are composed by merging selected, completed features together. This seems quite rational, and can be made to work with enough effort applied in bursts. Every merge creates a unique, new configuration in the system that must be tested for side effects. If the merge has unintended consequences, then one or more features must be modified or the release re-composed without it. As a result, releases become major events in the life of the company with huge testing parties and great schedule risk. These times are frequently called "hell week" or "hell month" depending on the release periodicity.
In addition, the more two lines of code diverge, the harder it is to reconcile their changes. When work is integrated several times a day, it tends to be a fairly trivial effort. When it is integrated only a few times per month, it is rather harder. A few times a year, and it is surprisingly difficult. Likewise, if many branches are held for a long time, each branch will not only diverge from the main codeline but from other branches as well. This effect can make it rather difficult to estimate the effort of integrating branches, which contributes to the nervousness around hell week.
Agile teams integrate continually with great ease and success. Why, then, do some organizations hail branch-per-feature? Teams that use branch-per-feature as regular practice are often compelled to do so because they don't know which tasks/stories will actually be completed by the end of the sprint. It seems easier to hedge bets with version control systems than to tackle the organizational/political problems that frustrate planning and execution of sprints.
- Too much WIP (work-in-process) means that too many tasks are undertaken at once. Branch-per-feature helps the team deal with the fact that work is not being finished predictably or reliably within the iterations. Many tasks are reported complete on the last days of the iteration, yet some of those are rejected. Branch-per-feature allows management to decompose and recompose the release at the tail-end as they find out what is actually completed.
In an agile team, as many as half of the features are done by the midpoint of the iteration and are being tested frequently. Very few changes are actually at risk of being left incomplete. In the best teams, missing an iteration boundary is a rare event, so branched features are unnecessary.
- Features are too large if they cannot be completed in a small part of a single iteration. Otherwise the uncertainty prompts the team to fork the code base. The forked code base is more difficult to integrate as it diverges from the original code line. Fear of difficult integrations actually encourages the team to hold isolated branches longer.
Agile teams instead look to ensure features are small enough to completed within a few days. Small features completed in a day or two rarely require complex merging. Any overlap of effort can be easily coordinated with other team members during stand-ups or ad hoc conversations across the team table, further minimizing the chance that a merge will be necessary. - Structure is poor if changes routinely span many files in many libraries or assemblies (something Martin Fowler refers to as "shotgun surgery"). When a feature's implementation is scattered all over the code base, it is harder to accurately make changes and harder to predict when work will be truly done. This uncertainty drives the team to isolate rather than integrate.
Agile teams are highly cognizant of the value of simple, SOLID design. They understand that systems exhibiting true cohesion and minimal duplication dramatically lower the need for shotgun surgery. - If there is no way to turn off incomplete features then the team will fear customers stumbling into incomplete sections of code and causing damage to data or additional customer support burden. This force drives developers to develop code in isolation from the main codeline, which of course increases the cost of integration.
Agile teams view changes to the system holistically, breaking down each new feature as a series of incremental changes to the mainline. They understand that while this requires some level of overhead, it means that merge hell is minimized, and that it demands a better system design. For larger changes, they look to solutions such as branch by abstraction as helping provide both benefits.
The Seven Code Virtues

Authors: Tim Ottinger and Jeff Langr
Font: Burst My Bubble
Programming pundits often decry the dismal state of code in the world. We hear speakers demand professionalism or a more craftsmanlike value system, rigorous certification, etc. In response to these very demands we find contradiction of these very concepts. The argument is frequently made that whether code is "good" or "bad" is subjective and situational. We beg to differ.
To promote a shared set of programming values, we propose these seven virtues of code:
- Working, as opposed to incomplete
A program that works is simply superior to one that doesn't work. We contend that a working program now is of higher value than one that might work some day. To this end, incremental and iterative methods (such as agile methods) push us to complete small features as soon as possible, with improvements and expansions to follow.
We ensure code is working by writing tests before and after writing code as we consider more success and failure modes. We can tell code is working by running the tests and by using the software.
- Unique, as opposed to duplicated
The worst thing we can do to working code is to duplicate it. Copies and near-copies scattered willy-nilly across the code base makes code difficult to maintain. We struggle to eliminate duplication each time we refactor in our red, green, refactor cycle.
A dirty software industry secret: Many "stepback" or "regression" errors are not really re-broken code, but are instead examples of fixes to duplicated code.
We can tell that code is duplicated visually (common paragraph structures) or by the use of duplicate detecting tools like Simian.
- Simple, as opposed to complex
Simplicity here refers to the number of entities, operations, and relationships present in any particular routine/function, and not to the readability of that module (which we call "clarity").
The best way to increase simplicity is to use simpler structures and algorithms. Reducing complexity in this way often translates to improved runtimes, smaller code size, and easier optimization.
We can also improve simplicity of one routine by extracting methods so that a series of manipulations becomes a single step as far as all of its callers are concerned. By moving the extracted methods to the appropriate classes, we also further develop the type system. After extraction, the code still takes all of the same steps, but those steps are evident in far fewer places in the code. The extracted methods are also simpler because they are unencumbered by their original context, a fact which aids us in finding yet simpler algorithms and structures.
Such simplifying code migration is at the heart of object-oriented design.
- Clear, as opposed to puzzling
The meaning and intent of code must be obvious to the reader. Code misunderstandings generate errors. Confusion over code creates delays.
While high-level languages make it easy to see what code is doing, there is still an art to producing code which communicates its goal and intent. The consensus of multiple readers is nonetheless a reasonably consistent measure of clarity. Therefore, the most reliable way to make code clear is to have multiple colleagues reading it.
When one sees an improvement in readability from merely renaming variables, classes, or functions it is because one has improved clarity without changing any of the other virtues of the code. Clarity is further amplified by other virtues such as simplicity and brevity.
- Easy, as opposed to difficult
Adding and modifying code should not be an arduous process. Ease is largely a matter of how much code must be typed in how many places, and how much configuration must change. In a particularly ugly code base, the easiest way to get code working is to implement a hack in an inappropriate place. In a truly clean and simple code base, putting a correct design into place is often as easy as a hack. Uncle Bob Martin has stated that design has degraded when the doing "the right thing" is significantly harder than making "an ugly hack."
- Developed, as opposed to primitive
A primitive system is not necessarily simpler (fewer parts), nor easier (less thinking and typing), nor more clear than a developed system. Primitive code tends to be characterized by Duplication, Feature Envy, and Primitive Obsession code smells. These make a primitive solution more complex, more difficult, and less clear than one built with a well-developed type system.
In an object-oriented system, the developed type system of an application provides well-thought-out classes whose methods make continued development easy.
A system is well-developed when functionality appears to be just where one might expect it. String methods on strings, account methods on accounts, and button activations and the like merely make calls on "business objects."
- Brief, as opposed to chatty
It is valuable for code to be as brief as possible without sacrificing other virtues. This is part of the reason that language tools like LINQ and list comprehensions and closures have become so popular of late. All programmers, including the one who writes it, benefit from writing and reading less code (as long as this smaller amount of code is otherwise clean).
Code that is long and chatty is much more likely to contain hidden errors. An overly cryptic method is likely to be misunderstood. Either one is hard to take in at a glance and understand.
Playing "programming golf" is actually a meaningful activity. If one can make the solution to a problem smaller without sacrificing clarity (or indeed may improve clarity by reducing the solution to a smaller form), then one is reaching a more brief form. The distance from an ideally brief, clear form is unwanted verbosity (chattiness).
Subscribe to:
Posts (Atom)


