FunctionOwnerAndComponentOwner

...the functions in your project tend to cut across the components of your project. You recognize the importance of organizing according to the architecture of the project (ConwaysLaw), but things aren't simple.

★ ★ ★

If you organize teams by components, functions suffer, and vice versa.

You may be organized by function or use case, with no component ownership. On the other hand, you may be organized by class or component, with no function or use case ownership. In either case you the the same question: "What happens when two people need to program the same function?"

You want ownership and consistence in the functions, but also in the components. And the components must be shared across the teams.

If you just assign function owners, the components become shared, and lose their identity and integrity. But if you have only component owners, the functions become orphans. Who makes sure they get done?

Therefore:

Make sure every function has an owner and that every component has an owner.

Make sure every component has a responsible owner and make sure every delivered function has a responsible owner. The component owner answers for the integrity and quality of the component. The function owner ensures that the function gets delivered. If the component owners all refuse to incorporate something needed to deliver end functionality, the function owner sees that the missing code is put in a function-specific place.

★ ★ ★

There may be friction between component and function owners. You may find the need for the Envy/Developer model of ownership, in which there is a common part to each component or class, and an application-specific part.

No conflict resolution is needed in this strategy, since the component owner has right of refusal to any request, and the function owner has recourse to another to get the job done.

Related patterns:

OwnerPerDeliverable - the general form of this pattern.

TeamPerTask - where a task is the unit of ownership and conflict.

Sample situations:

A. Project Reginald, among others, started out with teams centered around classes or components. At delivery time, the end function did not work. Each team said, "I thought you were taking care of that. It doesn't belong in my class."

On Project Reginald, each function ended up with one responsible owner. That person had to negotiate between the teams to see if some team was willing to pick up the gap, or to see that some extra, special code was created to cover the gaps between the classes.

B. Project Winifred, among others, started out with teams centered around use cases. They soon found that with nobody responsible for cleaning up a class, it develops into an arbitrary collection of state variables and functions. At that point, nobody can clean it up. In one team of three, the entire team sat around one workstation one day to clean up their classes. All three people were needed to understand the code.

C. Brooklyn Union Gas, Project Othello, and eventually Project Winifred were organized with both class and function owners. This changed people's responsibilities, so that a class owner would refuse to put a requested function into a class. They would say it was not part of the class's responsibility, only a special need for an isolated function. The function might end up in the class for the use case.

Fortunately, there are tools such as Envy/Developer that allow a method/functions to be attached to a class just for a specific application. They support creating ownership around common parts of a class, and application-specific parts of a class.

D. Envy/Developer. This model is straightforward to apply to Smalltalk code since Envy/Developer directly supports it. The presence of that tool and this pattern changes the economics of the argument that view classes are needed separately from model objects. While view classes are still valid, Envy/Developer makes it straightforward, safe and local for one application team to add their function-specific methods to the class.

A version of this pattern first appeared in [BibRef-Cockburn1998].