- Pair Programming: Pair Programming provides great feedback to individual developers on code quality, but it is very expensive. It's good for teaching inexperienced devs to code, but not so helpful when your team is already competent. Code review provides much the same benefit at lower cost.
- Code Review: There are automated tools for code review that present the user a visual diff of the modified code, and allow commenting and approval. While these tools are great for
reviewing point-changes during maintenance, they discourage thorough
review of whole interfaces. It's too easy sitting at your desk alone, to take a perfunctory glance at the changed lines, and say, "Looks good. Ship it." Shops using automated review tools have to keep an eye open to be sure all reviewers are taking a decent amount of time to actually read the code. I have had good results from a heavy-weight design review involving actual meetings. The formality
and required prep work for the meetings, and the expectation of
face-to-face feedback from peers induced higher quality even before the
Linters and static checkers are tools you can use for code review too, even if you're only reviewing your own code.
- Unit Test: I love unit test. A good set of unit tests remove much risk from changing software. Unit tests written alongside (not after) developing the code form a check on the consistency and completeness of newly designed APIs. The needs of unit testing focus attention on separation of concerns and isolation of dependencies, which both push up the quality of the resulting code. Unit tests are most effective when devs buy into the idea of testing as you go. If writing the unit tests is just an annoying check-box to a developer, they are unlikely to give it the attention required for a really good result.
- Code as the Only Deliverable: Some agilists suggest that, since the code is the only artifact shipped to customers, no other artifact has any value. Production of requirements lists, design documents, schedules, and other non-executable artifacts should thus be viewed as wasteful.
This advice has merit from an aspirational standpoint, but has practical weaknesses. Code is too voluminous and precise a language for expressing requirements. Code is too low-level to express architectural decisions. Code cannot express schedules at all. Other kinds of documents may be necessary for internal communication and review, even if they aren't delivered to customers.
- Schedules: There is a persistent myth that Agile methods don't do scheduling. This is untrue on many levels.
At the micro level, the effort for individual features must be estimated, and big features broken up into sprint-sized pieces (if you're doing sprints. But otherwise you're doing big-bang development. Hisssss).
At the macro level, Agile projects must do scheduling when stakeholders require it. This happens any time they interact with other projects, when long lead time hardware and mechanical packaging must be designed and ordered, or when the dev organization must release by a calendar date or forego important sales (in time for Christmas, for instance). Only a small subset of Agile projects can safely ignore macro scheduling issues, or refuse to predict completion.
- Refactoring: The world of software development is of two minds on the subject of refactoring. One school believes that any change to released software must be minimal, lest the change introduce bugs. The other school says refactoring is OK if it adds value by making the software more maintainable or more flexible, or better supports new features.
In my opinion, both thoughts are schooled by experience. If the initial design and coding were weak, and there are no unit tests, then any change is risky, so change must be minimized. If, on the other hand, the initial design was well motivated and good unit tests are available, refactoring just makes things better and better.