Skip to main content

Architecture-Oriented or Feature-Oriented - how do you organise your development teams?

Posted by johnsmart on July 11, 2008 at 6:12 AM PDT

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.

Comments

Very good article...I have some comments: When you say : ..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 practises such as Continuous Integration difficult to implement effectively.... I do not agree because since you interfaces between layers are well defined, developers may unit test their methods using mocking techniques. When a layer becomes available, it just disable the mocking code and you have a continuous integration. The second approaches is very appealing to me as a human being but in the reality where you need to deliver good software on time and on tight budget, it seems to good to be true. I really agree with the expression: "jack of all trades and master of none" Your crack team will provide something that is going to be out of date very fast...your idea is against agile techniques. It is a bit like using a 100% waterfall approach and expecting things will never move. Even cracks will find their code being outdated some day... I think a mentoring approach combined with an architecture approach is the best. You keep people where they are good at and ask the pros to help out the juniors to understands other layers. Your preferred approach is not solving the problem you refer to "...The job gets done well, but the high degree of specializations may put the organization at a risk if and when team members leave the organization..." You crack team is just that. If you don't have mentoring techniques, you will have a problem and the cracks will eventually burnout. Anyway...very interesting topic, thanks

Thanks for your comments, Eric - your point about using mock objects to simulate interface layers is a very good one, and it's something I do often. I've even seen entire mainframe backends mocked-out this way! Also, you are correct to imply that the reference implentation cannot be static - of course it needs to evolve, and it should (I don't see it as being separate from the application, actually - it's a starting point to get the team launched). Anyway, thanks again for your feedback.