Visual Basic

Dancing in Step

One of the most serious problems facing us in the battle against bugs is project size and its implications. As the size of a project team grows linearly, the number of communication channels required between the team members grows factorially (in fact, almost exponentially once the numbers reach a certain level). Traditionally, personal computer projects have been relatively small, often involving just two or three people. Now we're starting to see tools such as Visual Basic 6 being used in large-scale, mission-critical projects staffed by ten to twenty developers or more. These project teams can be spread over several locations, even over different continents, and staffed by programmers with widely varying skills and experience.

The object-oriented approach is one attempt to control this complexity. By designing discrete objects that have their internal functions hidden and that expose clearly defined interfaces for talking to other objects, we can simplify some of the problems involved in fitting together a workable application from many pieces of code produced by multiple developers.

However, programmers still have the problems associated with communicating what each one of hundreds of properties really represents and how every method and function actually works. Any assumptions a programmer makes have to be made clear to any other programmer who has to interact with the first programmer's objects. Testing has to be performed to ensure that none of the traditional implementation problems that are often found when combining components have cropped up. Where problems are found, two or more developers must often work together for a while to resolve them.

In an effort to deal with these issues, which can be a major cause of bugs, many software companies have developed the idea of working in parallel teams that join together and synchronize their work at frequent intervals, often daily. This technique enables one large team of developers to be split into several small teams, with frequent builds and periodic stabilization of their project. Small teams traditionally have several advantages over their larger counterparts. They tend to be more flexible, they communicate faster, they are less likely to have misunderstandings, and they exhibit more team spirit. An approach that divides big teams into smaller ones but still allows these smaller groups to synchronize and stabilize their work safely helps to provide small-team advantages even for large-team projects.

What is the perfect team size? To some extent, the optimum team size depends on the type of project; but studies typically show that the best number is three to four developers, with five or six as a maximum. Teams of this size communicate more effectively and are easier to control.

Having said this, I still think you need to devise an effective process that allows for the code produced by these small teams to be combined successfully into one large application. You can take several approaches to accomplish this combination. The process I recommend for enabling this "dancing in step," which is similar to the one Microsoft uses, is described here:

  1. Create a master copy of the application source. This process depends on there being a single master copy of the application source code, from which a periodic (often daily) test build will be generated and released to users for testing.
  2. Establish a daily deadline after which the master source cannot be changed. If nobody is permitted to change the master source code after a certain time each day, developers know when they can safely perform the synchronization steps discussed in detail in the rest of these steps.
  3. Check out. Take a private copy of the code to be worked on from the master sources. You don't need to prevent more than one developer from checking out the same code because any conflicts will be dealt with at a later stage. (See step 8.)
  4. Make the changes. Modify the private copy of the code to implement the new feature or bug fix.
  5. Build a private release. Compile the private version of the code.
  6. Test the private release. Check that the new feature or bug fix is working correctly.
  7. Perform pretesting code synchronization. Compare the private version of the source code with the master source. The current master source could have changed since the developer checked out his or her private version of the source at the start of this process. The daily check-in deadline mentioned in step 2 ensures that the developers know when they can safely perform this synchronization.
  8. Merge the master source into the private source. Merge the current master source into the private version of the source, thus incorporating any changes that other developers might have made. Any inconsistencies caused by other developers' changes have to be dealt with at this stage.
  9. Build a private release. Build the new updated private version of the source.
  10. Test the private release. Check that the new feature or bug fix still works correctly.
  11. Execute a regression test. Test this second build to make sure that the new feature or bug fix hasn't adversely affected previous functionality.
  12. Perform pre-check-in code synchronization. Compare the private version of the source code with the master source. Because this step is done just prior to the check-in itself (that is, before the check-in deadline), it will not be performed on the same day that the previous pretesting code synchronization (which occurs after the check-in deadline; see step 7) took place. Therefore, the master source might have changed in the intervening period.
  13. Check in. Merge the private version of the source into the master source. You must do this before the daily check-in deadline mentioned in step 2 so that other developers can perform their private code synchronization and merges safely after the deadline.
  14. Observe later-same-day check-ins. It is essential that you watch later check-ins that day before the deadline to check for potential indirect conflicts with the check-in described in step 13.
  15. Generate a daily build. After the check-in deadline, build a new version of the complete application from the updated master sources. This build should be relatively stable, with appropriate punishments being allocated to project members who are responsible for any build breaks.
  16. Test the daily build. Execute some tests, preferably automated, to ensure that basic functionality still works and that the build is reasonably stable. This build can then be released to other team members and users.
  17. Fix any problems immediately. If the build team or the automated tests find any problems, the developer responsible for the build break or test failure should be identified and told to fix the problem immediately. It is imperative to fix the problem before it affects the next build and before that developer has the opportunity to break any more code. This should be the project's highest priority.

Although the above process looks lengthy and even somewhat painful in places, it ensures that multiple developers and teams can work simultaneously on a single application's master source code. It would be significantly more painful to experience the very frustrating and difficult bugs that traditionally arise when attempting to combine the work of several different teams of developers.

Some final thoughts Split your larger project teams into smaller groups, and establish a process whereby these groups can merge and stabilize their code with that of the other project groups. The smaller teams will produce far fewer bugs than will the larger ones, and an effective merging process will prevent most of the bugs that would otherwise result from combining the work of the smaller teams into a coherent application.