Posted by johnsmart
on July 11, 2008 at 6:12 AM PDT
Organising a development team is always a tricky business. Do you divide the work up by architectural layers or by functionality? Or maybe a bit of both?
Traditionnally, there are two fundamental approaches when it comes to organising your development teams: the Architecture-Oriented approach and the Feature-Oriented approach. The first priviledges teams that focus on the different architectural layers or components, whereas the second prefers to organise teams around deliverable application features.
Architecture-Oriented teams are organised according to the system architecture of the application. For example, in a typical e-commerce application, you might have a web-tiers layer, a services layer and a database access layer. Using an Architecture-Oriented approach, you would have a team (or team-member, for very small projects) dedicated to each layer.
An Architecture-Oriented approach is good if you are a control-freak. Projects that use this approach tend to have a cleaner and more rigourous system architecture, and it is indeed easier to enforce a consistant coding and architecture style using Architecture-Oriented teams. In fact, it becomes natural - each team becomes very good at what they do, and the quality of the code in each layer is often very high. Interfaces between the layers are well-defined, clean and consistent, and it is easier to design and implement reusable components this way.
However, this approach does have some drawbacks. Building a software system this way requires a very high degree of upfront design and planning, which can lack in flexibility. On the one hand, integration is simpler because the interfaces between the layers are well-defined early on in the piece. But on the other hand, this integration is often untestable until very late on in the piece, because all the layers need to be finished before any feature can be properly tested. This makes practices such as Continuous Integration difficult to implement effectively.
An Architecture-Oriented approach also tends to lead to Taylor-like specialisation, and to a certain degree of knowledge-siloing. For example, only the database team really knows how the database layer works, and for everyone else it's a bit of a black box. This may or may not be considered to be a good thing. The job gets done well, but the high degree of specialisation may put the organisation at a risk if and when team members leave the organisation.
Feature-Oriented teams are organised by feature, or use case, or user story, or some other tangible and deliverable unit of functionality. For this iteration, Team A will take care of the Shopping Cart Checkout feature, whereas Team B will implement the full-text catalog search. Each team implements their feature from A to Z, so they usually have to touch all the layers of the application architecture.
Feature-Oriented teams are more dynamic - in effect, they are reorganised at the start of every iteration. This tends to encourage a broad knowledge of the system. In a Feature-Oriented approach, each team delivers tangible, fully-working and fully-testable chucks of functionality. Integration can be more complex, as the demarcation between individual teams is more fuzzy in terms of the actual source code, but Continuous Integration can be used much more efficiently to provide quick feedback about integration issues. And since each team is the master of all of the application layers, as far as their feature is concerned, change requests can be catered for much more easily. This makes a Feature-Oriented approach much more flexible.
However, as this is the real world, and nothing is black or white, a Feature-Oriented approach also has some drawbacks. This approach may foster a "Jack of all trades, but master of none" culture, where developers have a superficial knowledge of all system layers rather than an in-depth knowledge of one. This can also lead to architectural compromises, and the risk of poor or inconsistant code slipping into an area in which a developer is not fully familiar. In general, architectural integrity is harder to guarantee with a Feature-Oriented approach.
Personally, I prefer the flexibility of the Feature-Oriented approach, but keep a healthy respect for the clean architecture that is fostered by an Architecture-Oriented approach. One possible compromise that I have used on some of my projects goes along the following lines:
First, a crack team of experienced developers designs and documents a set of high-level architectural design guidelines along with a clean reference implementation that illustrates the target architecture in practice. This reference implementation is designed to provide examples to other team members as to how things are meant to be done. Eliminate the guesswork and arbitrary design decisions wherever possible.
Once the reference implementation is completed, the real project work can start, and the rest of the project team members can come on board. From here-on it's pretty much a Feature-Oriented approach, using a SCRUM-like agile development methodology. Continuous Integration and thorough unit testing help to smooth out the integration process. However, architectural integrity is still a potential issue. So informal code reviews and automatic code quality metrics (in particular, dependency analysis) help to keep an eye on the code quality in each layer. The crack team also stays on to act as recognised "gurus" in various domains, and to mentor the newer developers on the tricks of the trade.
And hopefully, this leads to a little of the best of both worlds.