Maintaining a Project: Interacting with Developers

Once you have gotten your project started, you have overcome the most difficult hurdles in the development process of your program. Laying a firm foundation is essential, but the development process itself is equally important and provides just as many opportunities for failure. In the next two sections, I will describe running a project by discussing how to maintain a development effort through interactions with developers and with users.

In releasing your program, your program becomes free software. This transition is more than just a larger user base. By releasing your program as free software, your software becomes the free software community's software. The direction of your software's development will be reshaped, redirected, and fully determined by your users and, to a larger extent, by other developers in the community.

The major difference between free software development and propriety software development is the developer base. As the leader of a free software project, you need to attract and keep developers in a way that leaders of proprietary software projects simply don't have to worry about. As the person leading development of a free software project, you must harness the work of fellow developers by making responsible decisions and by responsibly choosing not to make decisions. You have to direct developers without being overbearing or bossy. You need to strive to earn respect and never forget to give it out.

Delegating Work

By now, you've hypothetically followed me through the early programming of a piece of software, the creation of a website and system of documentation, and we've gone ahead and (as will be discussed in the Section called Releasing Your Program) released it to the rest of the world. Times passes, and if things go well, people become interested and want to help. The patches begin flowing in.

Like the parent of any child who grows up, it's now time to wince, smile and do most difficult thing in any parents life: It's time to let go.

Delegation is the political way of describing this process of "letting go." It is the process of handing some of the responsibility and power over your project to other responsible and involved developers. It is difficult for anyone who has invested a large deal of time and energy into a project but it essential for the growth of any free software project. One person can only do so much. A free software project is nothing without the involvement of a group of developers. A group of developers can only be maintained through respectful and responsible leadership and delegation.

As your project progresses, you will notice people who are putting significant amounts of time and effort into your project. These will be the people submitting the most patches, posting most on the mailing lists, and engaging in long email discussions. It is your responsibility to contact these people and to try and shift some of the power and responsibility of your position as the project's maintainer onto them (if they want it). There are several easy ways you can do this:

In a bit of a disclaimer, delegation need not mean rule by committee. In many cases it does and this has been proven to work. In other cases this has created problems. Managing Projects the Open Source Way argues that "OSS projects do best when one person is the clear leader of a team and makes the big decisions (design changes, release dates, and so on)." I think this often true but would urge developers to consider the ideas that the project leader need not be the project's founder and that these important powers need not all rest with one person but that a release manager may be different than a lead developer. These situations are tricky politically so be careful and make sure it's necessary before you go around empowering people.

How to delegate

You may find that other developers seem even more experienced or knowledgeable than you. Your job as a maintainer does not mean you have to be the best or the brightest. It means you are responsible for showing good judgment and for recognizing which solutions are maintainable and which are not.

Like anything, its easier to watch others delegate than to do it yourself. In a sentence: Keep an eye out for other qualified developers who show an interest and sustained involvement with your project and try and shift responsibility toward them. The following ideas might be good places to start or good sources of inspiration:

Allow a larger group of people to have write access to your CVS repository and make real efforts toward rule by a committee

Apache is an example of a project that is run by small group of developers who vote on major technical issues and the admission of new members and all have write access to the main source repository. Their process is detailed online.

The Debian Project is an extreme example of rule by committee. At current count, more than 700 developers have full responsibility for aspects of the project. All these developers can upload into the main FTP server, and vote on major issues. Direction for the project is determined by the project's social contract and a constitution. To facilitate this system, there are special teams (i.e. the install team, the Japanese language team) as well as a technical committee and a project leader. The leader's main responsibility is to, "appoint delegates or delegate decisions to the Technical Committee."

While both of these projects operate on a scale that your project will not (at least initially), their example is helpful. Debian's idea of a project leader who can do nothing but delegate serves as a caricature of how a project can involve and empower a huge number of developers and grow to a huge size.

Publicly appoint someone as the release manager for a specific release

A release manager is usually responsible for coordinating testing, enforcing a code freeze, being responsible for stability and quality control, packaging up the software, and placing it in the appropriate places to be downloaded.

This use of the release manager is a good way to give yourself a break and to shift the responsibility for accepting and rejecting patches onto someone else. It is a good way of very clearly defining a chunk of work on the project as belonging to a certain person and its a great way of giving yourself room to breath.

Delegate control of an entire branch

If your project chooses to have branches (as described in the Section called Stable and Development Branches), it might be a good idea to appoint someone else to be the the head of a branch. If you like focusing your energy on development releases and the implementation of new features, hand total control over the stable releases to a well-suited developer.

The author of Linux, Linus Torvalds, came out and crowned Alan Cox as "the man for stable kernels." All patches for stable kernels go to Alan and, if Linus were to be taken away from work on Linux for any reason, Alan Cox would be more than suited to fill his role as the acknowledged heir to the Linux maintainership.

Accepting and Rejecting Patches

This HOWTO has already touched on the fact that as the maintainer of a free software project, one of your primary and most important responsibilities will be accepting and rejecting patches submitted to you by other developers.

Encouraging Good Patching

As the person managing or maintaining the project, you aren't the person who is going to be making a lot of patches. However, it's worth knowing about ESR's section on Good Patching Practice in the Software Release Practices HOWTO[ESRHOWTO]. I don't agree with ESR's claim that most ugly or undocumented patches are probably worth throwing out at first sight--this just hasn't been my experience, especially when dealing with bug fixes that often don't come in the form of patches at all. Of course, this doesn't mean that I like getting poorly done patches. If you get ugly -e patches, if you get totally undocumented patches, and especially if they are anything more than trivial bug-fixes, it might be worth judging the patch by some of the criteria in ESR's HOWTO and then throwing people the link to the document so they can do it the "right way."

Technical judgment

In Open Source Development with CVS, Karl Fogel makes a convincing argument that the most important things to keep in mind when rejecting or accepting patches are:

  • A firm knowledge of the scope of your program (that's the "idea" I talked about in the Section called Choosing a Project);

  • The ability to recognize, facilitate, and direct "evolution" of your program so that the program can grow and change and incorporate functionality that was originally unforeseen;

  • The necessity to avoid digressions that might expand the scope of the program too much and result and push the project toward an early death under its own weight and unwieldiness.

These are the criteria that you as a project maintainer should take into account each time you receive a patch.

Fogel elaborates on this and states the "the questions to ask yourself when considering whether to implement (or approve) a change are:"

  • Will it benefit a significant percentage of the program's user community?

  • Does it fit within the program's domain or within a natural, intuitive extension of that domain?

The answers to these questions are never straightforward and its very possible (and even likely) that the person who submitted the patch may feel differently about the answer to these questions than you do. However, if you feel that that the answer to either of those questions is "no," it is your responsibility to reject the change. If you fail to do this, the project will become unwieldy and unmaintainable and many ultimately fail.

Rejecting patches

Rejecting patches is probably the most difficult and sensitive job that the maintainer of any free software project has to face. But sometimes it has to be done. I mentioned earlier (in the Section called Maintaining a Project: Interacting with Developers and in the Section called Delegating Work) that you need to try and balance your responsibility and power to make what you think are the best technical decisions with the fact that you will lose support from other developers if you seem like you are on a power trip or being overly bossy or possessive of the community's project. I recommend that you keep these three major concepts in mind when rejecting patches (or other changes):

Bring it to the community

One of the best ways of justifying a decision to reject a patch and working to not seem like you keep an iron grip on your project is by not making the decision alone at all. It might make sense to turn over larger proposed changes or more difficult decisions to a development mailing list where they can be discussed and debated. There will be some patches (bug fixes, etc.) which will definitely be accepted and some that you feel are so off base that they do not even merit further discussion. It is those that fall into the gray area between these two groups that might merit a quick forward to a mailing list.

I recommend this process wholeheartedly. As the project maintainer you are worried about making the best decision for the project, for the project's users and developers, and for yourself as a responsible project leader. Turning things over to an email list will demonstrate your own responsibility and responsive leadership as it tests and serves the interests of your software's community.

Technical issues are not always good justification

Especially toward the beginning of your project's life, you will find that many changes are difficult to implement, introduce new bugs, or have other technical problems. Try to see past these. Especially with added functionality, good ideas do not always come from good programmers. Technical merit is a valid reason to postpone an application of a patch but it is not always a good reason to reject a change outright. Even small changes are worth the effort of working with the developer submitting the patch to iron out bugs and incorporate the change if you think it seems like a good addition to your project. The effort on your part will work to make your project a community project and it will pull a new or less experienced developer into your project and even teach them something that might help them in making their next patch.

Common courtesy

It should go without saying but, above all and in all cases, just be nice. If someone has an idea and cares about it enough to write some code and submit a patch, they care, they are motivated, and they are already involved. Your goal as the maintainer is make sure they submit again. They may have thrown you a dud this time but next time may be the idea or feature that revolutionizes your project.

It is your responsibility to first justify your choice to not incorporate their change clearly and concisely. Then thank them. Let them know that you a appreciate their help and feel horrible that you can't incorporate their change. Let them know that you look forward to their staying involved and you hope that the next patch or idea meshes better with your project because you appreciate their work and want to see it in your application. If you have ever had a patch rejected after putting a large deal of time, thought, and energy into it, you remember how it feels and it feels bad. Keep this in mind when you have to let someone down. It's never easy but you need to do everything you can to make it as not-unpleasant as possible.

Stable and Development Branches

The idea of stable and development branches has already been described briefly in the Section called Choosing a Method of Version Numbering and in the Section called Delegate control of an entire branch. These allusions attest to some of the ways that multiple branches can affect your software. Branches can let you avoid (to some extent) some of the problems around rejecting patches (as described in the Section called Accepting and Rejecting Patches) by allowing you to temporarily compromise the stability of your project without affecting those users who need that stability.

The most common way of branching your project is to have one branch that is stable and one that is for development. This is the model followed by the Linux kernel that is described in the Section called Choosing a Method of Version Numbering. In this model, there is always one branch that is stable and always one that is in development. Before any new release, the development branch goes into a "feature freeze" as described in the Section called Freezing where major changes and added features are rejected or put on hold under the development kernel is released as the new stable branch and major development resumes on the development branch. Bug fixes and small changes that are unlikely to have any large negative repercussions are incorporated into the stable branch as well as the development branch.

Linux's model provides an extreme example. On many projects, there is no need to have two versions constantly available. It may make sense to have two versions only near a release. The Debian project has historically made both a stable and an unstable distribution available but has expanded to this to include: stable, unstable, testing, experimental, and (around release time) a frozen distribution that only incorporates bug fixes during the transition from unstable to stable. There are few projects whose size would necessitate a system like Debian's but this use of branches helps demonstrate how they can be used to balance consistent and effective development with the need to make regular and usable releases.

In trying to set up a development tree for yourself, there are several things that might be useful to keep in mind:

Minimize the number of branches

Debian may be able to make good use of four or five branches but it contains gigabytes of software in over 5000 packages compiled for 5-6 different architectures. For you, two is probably a good ceiling. Too many branches will confuse your users (I can't count how many times I had to describe Debian's system when it only had 2 and sometimes 3 branches!), potential developers and even yourself. Branches can help but they come at a cost so use them very sparingly.

Make sure that all your different branches are explained

As I mentioned in the preceding paragraph, different branches will confuse your users. Do everything you can to avoid this by clearly explaining the different branches in a prominent page on your website and in a README file in the FTP or web directory.

I might also recommend against a mistake that I think Debian has made. The terms "unstable," "testing," and "experimental" are vague and difficult to rank in order of stability (or instability as the case may be). Try explaining to someone that "stable" actually means "ultra stable" and that "unstable" doesn't actually include any unstable software but is really stable software that is untested as a distribution.

If you are going to use branches, especially early on, keep in mind that people are conditioned to understand the terms "stable" and "development" and you probably can't go wrong with this simple and common division of branches.

Make sure all your branches are always available

Like a lot of this document, this should probably should go without saying but experience has taught me that it's not always obvious to people. It's a good idea to physically split up different branches into different directories or directory trees on your FTP or web site. Linux accomplishes this by having kernels in a v2.2 and a v2.3 subdirectory where it is immediately obvious (after you know their version numbering scheme) which directory is for the most recent stable and the current development releases. Debian accomplishes this by naming all their distribution with names (i.e. woody, potato, etc.) and then changing symlinks named "stable," "unstable" and "frozen" to point to which ever distribution (by name) is in whatever stage. Both methods work and there are others. In any case, it is important that different branches are always available, are accessible from consistent locations, and that different branches are clearly distinguished from each other so your users know exactly what they want and where to get it.

Other Project Management issues

There are more issues surrounding interaction with developers in a free software project that I can not touch on in great detail in a HOWTO of this size and scope. Please don't hesitate to contact me if you see any major omissions.

Other smaller issues that are worth mentioning are:

Freezing

For those projects that choose to adopt a split development model (the Section called Stable and Development Branches), freezing is a concept that is worth becoming familiar with.

Freezes come in two major forms. A "feature freeze" is a period when no significant functionality is added to a program. It is a period where established functionality (even skeletons of barely working functionality) can be improved and perfected. It is a period where bugs are fixed. This type of freeze is usually applied some period (a month or two) before a release. It is easy to push a release back as you wait for "one more feature" and a freeze helps to avoid this situation by drawing the much needed line in the sand. It gives developers room they need to get a program ready for release.

The second type of freeze is a "code freeze" which is much more like a released piece of software. Once a piece of software has entered a "code freeze," all changes to the code are discouraged and only changes that fix known bugs are permitted. This type of freeze usually follows a "feature freeze" and directly precedes a release. Most released software is in what could be interpreted as a sort of high level "code freeze."

Even if you never choose to appoint a release manager (the Section called Publicly appoint someone as the release manager for a specific release), you will have an easier time justifying the rejection or postponement of patches (the Section called Accepting and Rejecting Patches) before a release with a publicly stated freeze in effect.

Forks

I wasn't sure about how I would deal with forking in this document (or if I would deal with forking at all). A fork is when a group of developers takes code from a free software project and actually starts a brand new free software project with it. The most famous example of a fork was between Emacs and XEmacs. Both emacsen are based on an identical code-base but for technical, political, and philosophical reasons, development was split into two projects which now compete with each other.

The short version of the fork section is, don't do them. Forks force developers to choose one project to work with, cause nasty political divisions, and redundancy of work. Luckily, usually the threat of the fork is enough to scare the maintainer or maintainers of a project into changing the way they run their project.

In his chapter on "The Open Source Process," Karl Fogel describes how to do a fork if you absolutely must. If you have determined that is absolutely necessary and that the differences between you and the people threatening to fork are absolutely unresolvable, I recommend Fogel's book as a good place to start.