Bolour Computing logo

October 24, 2006

Some Consequences of Pull

Filed under: process — azad @ 9:37 pm

There’s been a lot of interest recently in the application of lean principles to software development. See for example the 2003 book Lean Software Development: An Agile Toolkit for Software Development Managers by Mary and Tom Poppendieck. A basic principle of lean thinking is pull. In pull, the materials and services required by a given task are requested, or pulled, by workers responsible for that task just in time to make them available when they can be used. Pull devolves power to workers. Workers decide based on the conditions on the ground what they need and when they need it. The role of a plan is de-emphasized in favor of dynamic self-organization.

Pull may be contrasted with command-and-control. A good generic account of this contrast appears in Leadership in Project Management: Time for a Shift From Fayol to Flores. Here is a brief summary of this contrast based in part on that account.

The traditional style of project organization as a command and control regime is rooted in the work of Henri Fayol a century ago. This type of management may be summarized as: make a grand plan; set it in motion; apply thermostatic controls to it to keep it on track; and motivate workers by reward and punishment.

In contrast, an empowering pull style of project organization can be summarized as: have people figure out what they need from others, and make requests for needed materials and services (pull); allow people to volunteer to fulfill those requests; obtain commitments for the delivery of the requests based on mutually negotiated conditions of satisfaction; and foster an environment in which commitments are taken seriously.

Of course, one commitment may require other pieces of work for its satisfaction, leading to additional requests and commitments to fulfill those requests, and so on. The result is a network of commitments, a phrase coined in the eighties by Fernando Flores, a philosopher-turned-management-guru.

The conditions of satisfaction for each commitment, including its time of delivery, are negotiated between a requester, generically called a customer, and a provider. Recognizing that negotiation is a normal part of the customer-provider relationship empowers providers by acknowledging their autonomy.

In an empowering regime, people are motivated by having the freedom to produce things to their standards of quality and utility, by the honor of keeping commitments, and by the need to maintain the respect and trust of their peers. Trust means that people can rely on promised commitments for the fulfillment of their requests, so that they in turn can reliably make dependent commitments to other requests. To develop trust, team members make and keep significant commitments to each other, and they welcome feedback.

Consequences 

Organizing our work around autonomous pulled commitments means:

  1. Incremental commitment. As we commit to and start developing functions and features in an iteration, we need the ability to pull commitments of assistance from other team members to perform specialized sub-tasks, to pair up with area specialists, or simply to obtain more bandwidth for the timely delivery of our commitments. So it must be the case that others leave time on their schedules to provide these types of assistance in a timely manner. This is only possible if we commit our time incrementally and in small chunks, and leave sufficient slack in our schedules. So the scheduling of commitments is an incremental, and highly dynamic affair, and the plan, as such, unfolds on a daily basis.
  2. Local autonomy in distributing work. The overall decomposition of the work of an iteration into primary commitments is a group responsibility. But it is left to the provider of a commitment to divide its work as he sees fit, and to get others to work with him by pairing, sub-contracting, or pulling specific expertise. The best way to collaborate depends on the nature of the work and the sensibilities of the the collaborating individuals. Management does not drive these lower-level work distribution issues.
  3. Provider estimates supersede group estimates. The estimates by which the team tracks the progress of commitments are those furnished after due reflection and negotiation by individual providers. Team members need reasonable time to reflect on what is being committed to, and to line up collaborators and include their inputs into estimates. Providers estimates are furnished dynamically during the course of the iteration as commitments are made. Group estimates arrived at in the planning game are considered as rough measures of required work. Nevertheless, group estimates are of great value. The exercise of group estimation allows all team members to contribute their experience to the planning process. And group estimates provide guidelines for comparison with the ultimate provider-supplied estimates. A large discrepancy between the two has to be understood as part of the negotiation for each commitment.

Unfortunately, software is notoriously hard to estimate. So in an atmosphere of high estimation uncertainty, what does it mean to meet commitments? Basically it means making fuzzy estimates with relatively narrow ranges, and consistently falling within the estimated range in a statistically balanced way.

It is unnecessary and counter-productive to measure estimation accuracy and judge people by that measurement. But estimation accuracy is one area for self-evaluation. And in a tightly-knit team, people will come to know the reliability of different people’s estimates soon enough, and to balance that with other variables that go into the trust equation, such as propensity to collaborate, amicability, and so on.

Upper management tracks the progress of the team as a whole by using burn charts: comparing group estimates for fully-completed commitments at a point in time to actual effort up to that point. Lower management tracks each individual commitment by comparing its actual effort with its provider-supplied estimate, raising a flag when actual effort approaches the pessimistic end of the provider-supplied estimate.

© Copyright 2006 Bolour Computing.

Task Dependencies in Plans

Filed under: process — azad @ 7:32 am

The GANTT chart, as embodied in Microsoft Project, has become the de facto method of representing software development plans in many organizations. This is unfortunate. For, the precise temporal positioning of all tasks within a timeline is seldom necessary for managing the progress of a software project.

GANTT charts reinforce two false assumptions about development plans: that each task must be completed within an estimated duration and effort, and that each task must be completed by a particular time. The pre-assignment of developers to tasks in specific time periods breaks down because there is significant estimation uncertainty in software tasks.

Agile methodologies recognize these shortcomings, and use simpler means of planning that de-emphasize precise temporal positioning of tasks and people in development plans. Agile developers can generally work in many different areas of the code base, partly because they can easily pair with area specialists. Since most developers can then work on most of the code base, the necessity to pre-assign developers to tasks in time is considerably diminished.

Of course, the breakdown of a release, or an iteration, into distinct tasks typically results in temporal dependencies between those tasks. But then a PERT chart representing these dependencies that also includes just effort/duration estimates for each task is a more appropriate means of depicting the task breakdown.

Still, agile methodologies can generally get away with simpler plans than even such PERT charts. So what gives? Is it important to represent task dependencies in the development plan? I believe it is. At the same time, there are simple ways to avoid the explicit representation of many dependencies in the development plan.

As development teams, we need to make and keep delivery commitments to the rest of the organization. A crude projection of the delivery of a release is obtained by estimating effort for individual tasks, summing up the estimates, and dividing the total by the available manpower. A better projection is obtained by taking task dependencies into account and by exposing critical paths.

Finessing Dependencies by Phasing

A simple strategy for ensuring the correct temporal ordering of dependent tasks is the use of temporal phases. For example, the Rational Unified Process defines four phases of the development process: inception, elaboration, construction, and transition. So the dependency of construction work on inception tasks, like baselining the release’s vision and architecture, is automatically satisfied.

Phasing has gotten a bad wrap because of the well-known shortcomings of the particular phases of the waterfall model. But it is not necessary to use waterfall phases in our plans.

An earlier blog in this series talked about a pipelined phasing model of iterative development, in which the (short) pipeline stages of R&D, construction, and deployment occur in sequence for each iteration of an iterative and incremental development project. In that model, the dependency between the program design+construction of a feature, and the R&D work needed to conceive that feature, is implicitly satisfied by the temporal ordering of the stages in which these activities are scheduled. Phasing provides a simple and intuitive method of covering dependencies without directly representing them.

But clearly phasing cannot cover all dependencies.

Service Dependencies

The most prominent example of dependency in software is the dependency of one piece of functionality on another. I will call this type of dependency a service dependency. In a service dependency, a client task is dependent on a service task.

There are times when the developer(s) providing the dependent function will also develop some of its dependencies as a side effect. In that case, from the point of view of the development plan, there is no need to track the dependencies folded into the dependent task. But folding the development of a dependency into the development of a dependent is not necessarily the right approach. Sometimes the dependency is a whole separate abstraction, and it makes sense to use a separate task for its development.

For example, a web site registration system generally depends on an email service to send opt-in confirmation messages to registering users. If we actually have to build the email service ourselves on top of a standard email package, say because our email service has special requirements, then the email service is considered to be a separate component, and the registration component becomes dependent on the email service.

The nice thing about a service dependency is that the client can be isolated from the service by using an abstract interface. Then the service may be mocked to enable the client development task to proceed in parallel with the service development task. Because the implementation of a service dependency can often be mocked, once a service interface is drafted, work on the client and the service may proceed in parallel. Later, when the production implementation of the service becomes available, the client and the service are integrated.

When all service functions needed by the client can easily be mocked, the client can be built and tested separately in its entirety, and integration with the production implementation of the service can be expected to be a simple matter. One might then forgo the explicit representation of the integration task.

But significant integration work can result from the infeasibility of mocking every last nuance of the service interface that is used by the client. At integration time, client tests that exercise the hard-to-mock functions of the interface have to be written, and these tests have to be made to pass with the production implementation of the service. In this case, the integration task needs to be tracked separately from the client, since work on it is not necessarily contiguous with work on the mock-based client.

Here is a sketch of the resulting tasks and their dependencies embodied in an activity on node PERT chart with effort/duration estimates (assuming, for simplicity, that effort and duration are the same).

Figure-1
parallelized client and server tasks and their dependencies

Clearly the benefits of parallelism come at the price of a more complicated task structure. But the benefits are often worth the price.

Of course, if we can anticipate service dependencies during the R&D stage of an iteration, then we just draft up a service interface right there and then, and the dependencies of the client and service on that interface will be implicitly satisfied.

Summary

There are clearly a variety of ways of avoiding the explicit representation of dependencies in the development plan: phasing, folding dependencies into dependent tasks, ignoring trivial integration dependencies, or not including dependent tasks in the plan until their dependencies are satisfied. But every so often, a dependency structure will crop up that cannot be finessed, as illustrated by non-trivial service integration dependencies. These dependencies may be represented in a PERT chart for critical path analysis, and to aid in anticipating the likely division of labor between developers.

© Copyright 2006 Bolour Computing.

October 23, 2006

Code Stewardship

Filed under: process — azad @ 7:52 pm

The benefits of collective code ownership are well-known. Everyone in the team needs to be able to contribute to every part of the code base. But collective code ownership has an Achilles heel. The quality of the code can degrade as team members try to evolve unfamiliar parts of the code base under schedule pressure. As innovators and craftsmen, programmers take pride in their work. And they need the satisfaction of seeing their carefully crafted designs evolved by the rest of the team without losing their conceptual integrity.

There is, of course, an ideal of a gelled team in which communication is so rich that all team members will do the right thing instinctively as they evolve different parts of the code. But it is a fact of life that differences in sensibility and skill exist, and persist, in many teams. And not every team member can be expected to be familiar enough with every part of the code base to preserve its integrity as it evolves.

The upshot is that mechanisms are needed to allow team members with different sensibilities and different levels of skill to work with confidence on pieces of code that they are not necessarily intimate with, while preserving the integrity of those pieces of code, as conceptualized by the team members who created them, and who have invested energy and craftsmanship to perfect them to their current state.

One mechanism to prevent code degradation is what I call code stewardship: having each module be looked after by a single steward, even as all team members are allowed to contribute to that module. The steward is the custodian of the integrity of a module. He maintains intimate knowledge of the module. But he does not necessarily work at all times on just the modules he stewards. The same developer is at the same time steward to some modules, and developer of features touching modules stewarded by others.

Stewardship is a temporary privilege delegated by the team to a volunteer for each module, generally someone who has worked in a sufficiently focused manner on a particular module. The steward serves the team, which retains community ownership of the code base. Stewardship is rotated every few quarters to spread knowledge, and to bring fresh ideas to bear on each module.

It is important to have just one person steward each module. Accountability for the integrity of that module then falls squarely on that one person.

How do we practice stewardship with minimum ceremony? The key is informal advice and consent throughout the development process. Developers pull advice and consent from stewards on a regular basis in the process of developing features impacting different modules.

Code stewardship requires that before checking a change to a module into the production branch, the code be subjected to the advice and consent of that module’s steward. It would be normal and expected for such advice and consent to result in significant refactoring, unless, of course, the steward was kept in the loop as the change was considered and developed.

Stewards need flexibility in their schedules so that they can quickly respond to requests for advice and consent. And developers need to anticipate the need for advice and consent and pro-actively request pair time with stewards.

To enhance the process of communication between the feature developers and the stewards, it is useful to give stewards visibility into actual code changes in their modules, as these changes are being developed, and before the final checkin to the production branch. The changes may be shared by using provisional code branches, with automatic notification of changes to corresponding stewards. Provisional code sharing allows the steward to reflect on pending changes and to research issues and alternatives in his own time. This type of off-line communication augments, but in no way replaces, face-to-face advice and consent sessions.

Finally a trivial one-line change should never require ceremony in a small team. Just check it in to the production branch, and have the steward be automatically notified.

In summary: It is the prerogative of each developer to be able to work in each module, subject to code stewardship. Therefore, developers are expected to pull advice and consent from stewards. It is the prerogative of the stewards (and ultimately the architect) to protect the integrity of the code base. Therefore the stewards and the architect get veto power over production code. Veto power is used judiciously and sparingly.

© Copyright 2006 Bolour Computing.

Iteration Pipelining

Filed under: process — azad @ 3:19 am

Iterative and incremental development (IID) is the established practice for dividing software projects in time. IID is often interpreted to mean a succession of complete development cycles, meaning that each iteration includes within its temporal boundaries the analysis, design, implementation, and deployment of the features produced in that iteration.

But practically speaking, some analysis, and some interaction design generally precedes the bulk of the program design and construction work in each iteration. Customers don’t normally come to the planning game of an iteration with a blank slate. They do at least some homework on functions they need built, and on how users might interact with the system to access those functions. In fact, by the time we get to the planning game, there may well be a draft PRD outlining, albeit briefly, the required functions and user interactions for that iteration. I call the analysis of required functions and the design of the associated user interactions, functional design.

If we accept that it makes sense for functional design work to be front-loaded for each iteration, it is then a short step from there to a two-stage pipeline that includes a functional design stage, and a development stage. Because different sets of people generally do functional design and development, and because it makes sense for much of functional design to precede development for each iteration, the activities of functional design and development may, to a large extent, be parallelized in a two-stage pipeline.

In a recent project we put in place this kind of a pipeline, and we found it worked quite well for us in streamlining our work. During the development of the n’th iteration, the PRD for the n+1’st iteration would be researched and produced.

The practice of pipelining functional design and development is not uncommon in IID projects. But there is concern that pipelining can lead to disruptive cross-iteration interruptions. For example, while the functional designers are busy designing the functions of the next iteration, the developers need bandwidth from them for the clarification of the functions of this iteration. In our experience, interruptions in this direction, while frequent, were welcomed.

Interruptions in the other direction turn out to be more serious. Let’s see why, and consider how to reduce their impact.

As our functional designers come up with the functions of the next iteration, it is necessary at the same time to consider the technical feasibility of these functions. It would be futile to pursue the functional design of some cool feature, if its implementation is not feasible. That means that a level of engineering R&D work has to happen in conjunction with functional design. Who does engineering R&D? Developers, of course. That is, the same people who do development. But if the same people do engineering R&D and development, it becomes harder to parallelize these activities, and pipelining them can result in a loss of focus and productivity as developers multi-task between them for two successive iterations.

In order to allow for pipelined parallelism between engineering R&D and development with minimal disruption, we must free ourselves of the ingrained notion that all developers build production code all the time. As argued in an earlier blog on development roles, one way to do this is to use two distinct development roles: designer/builder and R&D engineer. Designer/builders concentrate on designing and developing the production system. R&D engineers concentrate on feasibility issues and exploring alternative solutions to hard technical problems. It is, of course, not necessary to typecast team members into these roles. People can move between them. What is important is that being responsible and accountable for different kinds of things, people in these roles are each allowed to focus on their areas of responsibility, and to work at a pace appropriate to their work product.

Now that the first stage of the pipeline includes both functional design and engineering R&D work, I prefer the name R&D stage for this first stage. And since development includes engineering R&D as well as program design and construction, the name development stage is no longer appropriate for the second stage of the pipeline. I will call the second stage the construction stage.

The R&D stage of the pipeline is the time to figure out the functions to be built, and to come up with feasible approaches to their implementation, away from the day-to-day pressures of building production code. This type of work is exploratory in nature, and it has a very different pace and expectation of success than the more or less clockwork pace of construction activity in most shops. The construction stage of the pipeline includes normal program design and construction.

Of course, not all risk can be eliminated before construction begins. But to the extent that conceptual and technical issues can be anticipated and explored before the construction stage of an iteration, interruptions, task switches, and tensions due to surprise under deadline pressure may be mitigated in the normal program design and construction work for the features of the iteration.

To recap: An initial R&D pipeline stage for each iteration enhances workflow by allowing work on functional design and normal development to proceed in parallel, and by reducing the risk of hiccups in the middle of normal program design and construction, so that most developers may work on designing and building the features of an iteration at a consistently high clip most of the time.

Similarly, a final deployment stage can help parallelize the nitty-gritty work associated with getting all acceptance tests to pass and deploying the final system, thus freeing most developers to start working on the features of the next iteration.

Here is a schematic of the resulting 3-stage development pipeline.

figure
3-stage iterative and incremental development pipeline

By the end of the construction stage, all automated tests, including automated acceptance tests, would be passing. What remains is for acceptance testers to run through the remaining manual tests one last time. This activity can be time-consuming. But if there is significant test coverage by automated tests, the bug yield from this last pass through manual tests is likely to be modest.

In that case, for a small development team, a single developer can usually be shunted to do release engineering work, including defect investigation, for the deployment stage of the pipeline. This release engineer (with expanded responsibility for defect tracking) buffers developers from interruptions by acceptance testers. The release engineer, being a developer, can also track down and isolate defects to particular areas of the code before involving the area specialists in the fix. That frees the area specialist from the burden of tracking down and pinpointing bugs, which is often the more time-consuming and disruptive part of bug fixing.

Of course, this function may be rotated between members of the team, to spread the pain, if that is how it is viewed.

© Copyright 2006 Bolour Computing.

October 19, 2006

A View of Development Roles

Filed under: process — azad @ 8:46 pm

Specialization in teams allows team members to do what they are good at and what they like to do. There are at least three types of specialization in software development teams: functional specialization, subsystem specialization, and technology specialization. Here I’d like to focus on functional specialization. A role is a specialized function in a team: a locus of responsibility and authority to perform certain types of functions.

All software development methodologies pay special attention to roles. As an example, the Crystal Clear methodology of Alistair Cockburn defines the roles of sponsor, expert user, lead designer, designer-programmer, business expert, coordinator, requirements gatherer, tester, and writer.

Clearly, the way we divide our work into roles has a major effect on our team’s health and productivity. One way to choose the roles appropriate for our teams is to start with a suitable methodology, and to try and fit the team to that methodology. Another is to simply follow precedent in our organizations. A different way is to consciously decide what roles make sense for our teams, by drawing on the body of knowledge in different software traditions, and by using our own experience and intuition.

The teams I work in are generally small development teams, typically working on vertical commercial applications. So here are some role basics, based on my experience, that might inform the conversation about what roles actually make sense for our particular teams.

The way I look at it, there are three basic functional areas, or disciplines, in development teams.

  • Functional design. The functions of the system have to be conceived and their externally visible form has to be designed.
  • Engineering R&D. Feasible approaches to implementing the required functions have to be figured out.
  • Construction. The required functions have to built in a production implementation.

This view of the world is informed, but not necessarily constrained, by the ideas of Alan Cooper (see, Imagine This, a 2002 talk by Cooper at SDForum).

Work in various disciplines occurs throughout each iteration. The term discipline comes from the Rational Unified Process (RUP), which defined its own set of disciplines. As explained in the RUP literature, disciplines and phases are orthogonal concepts.

Functional Design versus Construction

In 1970, Winston Royce in his influential paper, Managing the Development of Large Software Systems, proposed that the most basic activities in software development are analysis and coding. Functional design and construction are somewhat more general incarnations of Royce’s analysis and coding disciplines. This type of distinction is also present in all major traditions of software development, including agile methodologies, though the details vary considerably from one methodology to the next.

Functional design as defined here includes both requirements analysis and the design of the external interfaces through which the system’s required functions are realized. Because these activities are tightly coupled, they belong to the same discipline.

Another activity that is tightly coupled with the conception of a system’s required functions and its user interface is acceptance testing. Clearly, it is up to the functional designers of a system to verify that what is constructed is what was conceived. So acceptance testing as a function fits into the functional design discipline.

It is fairly non-controversial to separate out the activities of functional design into their own roles, such as product manager, GUI designer, and acceptance tester. The main point of departure here from established mainstream practice is to organize acceptance testing under the functional design discipline.

Construction versus Engineering R&D

In most other technical fields, there is a fairly clear line between engineering R&D and the production of the end product. In software, this line is blurred. Nevertheless, there are compelling reasons, I believe, to consider differentiating between these activities in our teams. To recap, engineering R&D has to do with figuring out feasible approaches to implementing the functions of a system; and construction has to do with building robust working systems.

Engineering R&D can easily be mistaken for what we have come to know as design, which reminds us of the outdated waterfall-era separation of design and coding. In fact, engineering R&D does involve design, of course, but also much coding to try out ideas, prototype, simulate, benchmark, and so on. Similarly, construction involves coding, of course, but also much design to model the domain, to minimize coupling and maximize cohesion, to design for testability, and so on.

The distinction between engineering R&D and construction leads to the roles of R&D engineer and designer/builder.

Engineering R&D per se is not a phase. It is a type of function performed in software development. This type of function may be correlated with stages of development. But that is a different topic for a different day.

In my mind, the principle reason for differentiating engineering R&D and construction is that they each run on a different clock. Engineering R&D is experimental and uncertain in its outcome. R&D schedules need to tolerate a large degree of uncertainty and failure. In contrast, construction work is less risky. Construction is generally amenable to more systematic and accurate estimation. And management has much stricter expectations of timeliness and success from construction work than from engineering R&D.

Alan Cooper made this type of distinction a number of years back between what he calls engineers and programmers. He argues that these two types of practitioners need certain distinct sensibilities, and that it is probably easier to find world-class people in each of these areas, than people who are world-class in both. At the risk of oversimplification, one might say that, while there is considerable overlap between the two disciplines, R&D engineers gravitate towards the challenges of problem solving, while builders gravitate towards the challenges of creative craftsmanship to make real working systems.

Be that as it may, the fact that engineering R&D and construction each has its own pace, alone, I think, motivates an R&D engineer role in our teams. The R&D engineer is relatively free of the intense demands of building production code under aggressive schedule pressure, and can spend time researching high-value/high-risk ideas, and alternative solutions to the non-obvious requirements of the system. Of course, people need not be typecast into the roles of R&D engineer or designer/builder. One can certainly move between the two.

For many vertical applications, the ratio of R&D engineers to designer/builders would be small. I consider the role of the traditional hands-on software architect as an engineering R&D role. And in some projects, the architect may be the sole R&D engineer.

Summary

Here is a summary the basic roles motivated by this world-view.

figure
software development roles and disciplines

Each basic discipline has a lead, or coordinator. The coordinator of the functional design discipline is the product manager. The coordinator of the engineering discipline is the traditional hands-on architect. And the coordinator of the construction discipline is the master builder, the supervisor on the ground with ultimate responsibility for the construction of the production system. All team roles report to a single team lead with ultimate responsibility for all team functions. The team lead is in easy access for escalation and resolution of issues between the different disciplines.

It goes without saying that roles are open: actively seeking feedback and collaboration from other roles and other disciplines. Also, of course, the same individual may play more than one role at any given time.

© Copyright 2006 Bolour Computing.

October 18, 2006

Culturetecture

Filed under: process — azad @ 1:53 am

Team culture and software architecture have this in common: once the basic patterns have been established in each, it is relatively hard to change them, even though, at the same time, incremental change is a necessary part of their growth.

To set the stage, here are some examples of hard-to-change team patterns I have recently experienced:

  • Rigid individualized work schedules. Strict nine-to-fivers would have little to do with fitting their schedules to the conditions and priorities on the ground and to the rest of the team.
  • Team division into engineering and product management. The lowest common manager was high up in the management chain. So differences between the groups could not be resolved quickly and amicably by escalation to an engaged team lead.

Coplien and Harrison report in their book Organizational Patterns of Agile Software Development that the decomposition of team functions into roles, and the endowment of responsibility and authority to these roles, tends to get quite ingrained early on, and to remain relatively stable for long periods of time.

A similar tension between established patterns and change exists in software architecture. There are design decisions that are hard to change incrementally: the basic layering stack and the associated layering design patterns of a web application, for example. It is important at least to try to get such decisions right early on, even as we recognize that we may fail, and that the decisions will evolve over time.

The duality between establishing sustainable patterns and welcoming change is a fact of life. Different trends and methodologies tend to emphasize one or the other pole in this duality. In fact, both poles are important. And for each pole there is an obvious take-away.

First, because changing established norms often requires a major effort, the team culture should encourage extensive initial due diligence in setting cultural ground rules and in basic architectural design.

Second, because requirements and external conditions can change, and because our established norms may turn out to be wrong after all even for the conditions for which they were designed, the culture should encourage systematic incremental change over time.

There is nothing new nor I hope controversial here. And yet, it is not uncommon for teams to miss one or the other of these basic themes in team culture or in system architecture. I believe that the recognition of this duality and its simple consequences is fundamental to the development culture.

In establishing an initial team culture and in its incremental improvement, there are two dysfunctional extremes of leadership: command and control and laissez-faire. In a command and control regime, management decrees, and the troops are expected to follow. The shortcomings of this regime in terms of hindering innovation and lowering team morale are well-known. At the other extreme is laissez-faire: You throw a bunch of people together in a team and leave them to their own devices to evolve, with little leadership. Unfortunately what you may end up with is a Survivor culture, where political manipulation rules.

In both these extremes, standards end up being established without a serious opportunity for critical evaluation.

Even though the shortcomings of these approaches are well-known, development organizations in which elements of these extremes are palpable and sometimes even dominant are not uncommon.

Fortunately, autocratic command and control is considered politically incorrect nowadays, although management railroading with token nods to rank and file opinion is not that rare. Far more common these days is laissez-faire, disguised in the positive spin of self-organization. Of course, self-organization is a good thing, as long as leadership is exercised to keep it fair and amicable.

My bias is for a process of initial and incremental due diligence which may be called deliberative cultural evolution, meaning that to the extent possible, the culture would be driven by conscious deliberation. This type of due diligence has been talked about for years by people like Alistair Cockburn (see, for example, the techniques of methodology shaping and reflective workshop in Crystal Clear, A Human-Powered Methodology for Small Teams). At its best, deliberative cultural evolution allows everyone’s collective experience to be molded into a coherent and accepted set of norms of behavior in the team, with proper respect for all opinions, but with enlightened deference to experience and accomplishment. It takes skilled leadership to keep this process on track.

Too often in my experience, the team is so excited, or pressured, by the challenges of the work at hand, that it fails to treat the establishment and evolution of its culture deliberately, until it is too late. At other times, teams buy into particular popular methodologies of the day without much discussion. Far better, I think, is to be prepared to learn from all great traditions of development teamwork, and to make conscious collaborative decisions on patterns of culture.

© Copyright 2006 Bolour Computing.

Powered by WordPress