Martin Fowler blogs about a recent workshop where people were asked to rank principles for layered architectures. Interestingly, the concept of organizing teams around layers in the architecture emerges as an anti-pattern. I've heard this before often from people who should know better. I've also watched a colleague (back in 1999) - Peter Durcansky (some of you will know him as the developer of Playground, the Coad-Yourdon Notation modeling tool) - who had to rescue a project which went wrong mostly for this very reason - teams were organized to code in vertical slices. The code was poorly coupled and lacked cohesion.
Many agile developers believe that vertical slices are best. In fact the standard advice of "pick a pair, pick a story, TDD-it, and deliver it working" suggests vertical development across layers in the architecture. So why, when I generally believe in agile approaches, do I believe this is an anti-pattern?
Firstly, I do admit it works on smaller projects and for small tasks such as change requests. At 4thpass/Motorola in Seattle we did assign individuals or teams to do vertically partitioned development for change requests and minor upgrades. However, I do believe it is an anti-pattern on larger projects with more than one team (i.e. more than 6 people) on a project intended to run for quarters or years where the software will grow into a large code-base. Why? There are two reasons.
The first is rooted in a pattern identified as good in the ranking, "low coupling between layers, high cohesion within layers." Equally, it's good organizational skill to create teams which are highly cohesive and loosely coupled. Hence, if the teams doing the work are highly cohesive and loosely coupled, and the layers are highly cohesive and loosely coupled, shouldn't these be aligned? If the team spans the layers then it encourages poor cross layer cohesion (between code from different teams) and poor coupling between layers (as teams won't feel compelled to enforce loose coupling within their own code). [XP with its refactoring and shared code ownership allows an anyone goes anywhere policy and this in theory fixes the problem. However, with large code bases, teams tend not to wander all over the code base, refactoring other teams' code. So the problem remains.] Code cohesion will suffer when the organization and the architecture do not align. This is yet further evidence that to be an effective manager of software development, you must understand how code is built.
The second reason relates to scheduling and the uncertainty or variation implied by another principle agreed as good in Fowler's survey, namely "separation of concerns". The reason this makes sense is that it allows things to vary independently and the degree of variation, change and uncertainty will be different for each class or component. We "separate concerns" because we know they vary independently. There is another advantage to understanding and separating out variation. It lies in Critical Chain theory. The size of a buffer can be smaller when the uncertainty is smaller. Hence, in a project schedule for a network of components being developed in parallel by more than one team, the schedule can be shorter if the uncertainty is isolated effectively. Reinertsen explained, in Managing the Design Factory, that coupled tasks assume the uncertainty of the greatest element. Hence, cross-layer tasking maximizes the effect of uncertainty. Separating teams across layers, having them work only on code in that layer, facilitates minimal uncertainty. You achieve minimal uncertainty with a schedule that has tasks for each layer in the system, as shown here.

It is certainly true that an immature team cannot run with a Critical Chain schedule. The concept of tightly synchronous iterations such as Scrum Sprints works much better. However, once you've controlled chaos, the next step is to look for continuous improvement. One way to achieve better throughput is to switch to asynchronous scheduling and reduce buffering by separating out differing degrees of variation in the architecture and the task network for the schedule. Hence, small teams doing vertical slices is probably the right answer for chaotic teams on smaller projects. Longer term, the most productive answer is to separate out teams across layers.