Agile methods and continuous integration are not easy to introduce into a larger organization accustomed to SOLID waterfall development. Here are some areas I find it useful to emphasize. * Unit tests * I've tried the gentle approach to persuade other developers to write more tests, arguing that it will make their lives easier. [[Unit_Tests.html]] At some point an organization must insist on tests, for everyone's sake. I've been surprised how often developers have simply refused to write tests, saying "I do not have time. It will hurt my productivity and my creativity." In return, I ask "What about the productivity of everyone else on your team? What about the creativity of those developers who must reverse engineer your code?" The only software metric I personally find essential is test coverage, because tests are a prerequisite for any Agile approach. Tests define what the code is expected to do. Tests let maintainers know when they have broken the expectations of the code. Tests help us avoid a long period of stabilization before we can ship. Testable code is also better written code, even if you threw away the tests when you were done. Testable code must be divided into smaller conceptual units that can be understood and tested in isolation. Large monolithic systems are not only hard to test, but they are hard to understand and maintain. The consequences of any particular change are too unpredictable. Remember the definition: Unit tests are written by developers for the benefit of developers. * Doneness * At the end of a formal Agile iteration, stories are certified as "done" by product owners and testers, with agreed-upon acceptance tests. Many find it difficult to agree on a definition of doneness. Teams used to upfront planning will struggle to define a new feature as perfectly as possible at the beginning of an iteration. Acceptance tests seem impossible. The resulting iteration meetings can take a very long time. During the iteration, developers uncover unexpected implications of new features. Testers discover unexpected side-effects. There is a struggle over whether to address these issues immediately or delay until a later iteration. A narrow definition of doneness would postpone these issues until later, when they would be less efficient to address. An inflexible feature ends up seeming like a broken feature. Stories must evolve intelligently and take advantage of this dialog between user and programmer. Such design decisions can be explained at the end of an iteration. Design is always part of any story. Stories describe what the user wants to do, not necessarily how. The useful definition of doneness stresses the goal of all Agile iterations: the product must remain shippable. __ O All visible features work o as advertised o within the expected environment o in any combination o without degradation over time o with graceful handling of errors _ O Hide all broken or unfinished features _ _ This definition of doneness emphasizes the result: we want a stable app at all times. When we start the app, we know what is expected to work, because we can see it and try it. We can prioritize new features by seeing how they must be reconciled with already visible features. Long iterations also encourage mini-waterfalls. If you continue to struggle with "doneness," try planning stories for one week at a time for a while. * Quality * Code must also meet certain minimal standards of quality before it can be accepted. It is tempting to define arbitrary metrics for acceptable code quality, using static code analyzers, for example. Many projects work well with formal design and code reviews. Metrics of known bad practices can call attention to those bad practices. Most developers spend much more time maintaining existing code than writing new code from scratch. Ultimately, this is the reason we care about code quality. High quality code is maintainable code. Two developers should agree on the design and implementation of any given feature. When possible, assign a non-expert to a new feature so expertise can be distributed more widely. That novice will still consult a previous expert, so you can be sure of at least some code and design review. More suggestions here: [[Pair_Programming.html]]. * Shared code ownership * It is not your code. It is all our code. This is perhaps the hardest cultural change to make. At some point, almost every developer feels that coding discipline is reducing productivity. Writing tests and documentation, inviting peer review, all take time, and arguably reduce the rate at which new features are implemented. But whose productivity are we talking about? The developer who writes the first draft of a page of code, or all those developers who will have to support, maintain, and upgrade that code? Clearly the latter group deserve at least equal consideration, since there are many more of them. Can a company afford to ship code that only one developer will ever understand? Does that developer want to be shackled forever to that one body of code, so irreplaceable that no transfer is ever possible? That's the worst kind of job security, resented by everyone else, and eventually circumvented. When you share ownership, you also share opportunities to learn more and to do more. What you give up in control, you gain in influence. Bill Harlan, June 2009