Two years ago, I managed an e-commerce development project without ever seeing 90 percent of my team. I was located in New York. The analysts and half of the developers were in Maryland. The rest were in Colorado, along with the architects. The client was in Pennsylvania.
Managing teams that are spread among multiple locations poses challenges in communication, coordination, development quality, and many other areas. I’ve learned some lessons in methods and techniques for managing remote teams that you can apply when you must manage a far-flung project team.
The client had had a Web site up and running for a few years, and we were undertaking the first round of major upgrades. When the teams were arranged for the project with the Pennsylvania-based client, they were set up as shown in Figure A.
The client worked mostly with me, the project manager, as the primary point of contact. The team in Maryland was responsible for the business and systems analysis and half of the development. The Colorado team architected the solution and handled the rest of development. The user interface was developed by a team split between New York and Maryland. Two more roles were filled in New York: a technical lead and a librarian.
An administration challenge
The first lesson I learned managing the remote teams was that administration was going to be more burdensome than it had been on contracts in which everyone was centrally located. With the development teams—because they were in locations separate from me—I had less control of the teams’ daily tasks and less influence with the actual code that was written. Less communication between the teams meant that lessons learned by one team were not easily taught to others.
Project plans and task assignments had to be communicated to several places. We primarily communicated information via e-mail and conference calls. The difficulty of assembling the teams, or even several key individuals, because of distance and time zone differences, began to slow decisions and make coordination more difficult.
This became even more complicated as development progressed, requirements changed, and details became more specific. The effect needed to be assessed across multiple locations, and changes had to be communicated and coordinated the same way. I defined two roles—the technical lead and the librarian—to assist in managing these issues.
The technical lead
The technical lead assumed the responsibility for coordinating technology among the teams. He became the person who knew the most about the architecture, design, and programming details of all aspects of the system. In this case, the system architect filled this role. This team member was originally located in Maryland, but relocated to New York for the duration of the project. This was done to bring the manager, technical lead, and librarian—the project’s management team—into the same office. Having them in the same office provided a single point of management communication for every other group involved in the project.
As changes to parts of the application became necessary, the technical lead worked with the remote teams to assess the effect of the change and coordinate actions among the teams.
Although the application was designed to maximize the independence of the various components, certain changes did affect each team. For example, during development, the client requested changes to the search functionality, which affected the user interface, the search logic component, and the database. Coordinating the redesign, impact, and implementation fell to the technical lead.
The technical lead was also responsible for code reviews. These are important in any software development project, and take on added significance when your teams are spread out. The technical lead reviewed the code, and then all the project members discussed it in weekly meetings.
The librarian assumed the remainder of the administrative responsibilities. Managing source control and document repositories became more important and more difficult with remote teams. We used three environments to develop the application. One was a pure development environment, which is where all coding took place. The second environment was for integration and system testing. The third was a client-acceptance environment.
As code was ready for testing, it was moved from the development to the testing environment. Every two weeks, a new, tested version was moved to the client environment for testing and feedback. The librarian coordinated the migration of code between the environments and the coordination of feedback from the client and the testing environments to the developers.
The librarian was also responsible for the management of all documents created during the life of the project. This included ensuring all documents were created, reviewed, and maintained as needed.
The daily checklist
Each morning began with a conference call attended by a lead developer from each team, the technical lead, the librarian, and myself. The meeting was kept as short as possible. The status of the previous day’s tasks was reviewed, new issues were brought up, and the current day’s tasks were assigned.
The meeting typically lasted 15 minutes, and it gave me a good sense of each team’s progress. It also provided each team with its guidance for the day and gave them a chance to see how the other groups were progressing.
Each day ended with a check in, usually enforced by the librarian. Each item that every team member was working on was checked back into the file repository and source control system each day at a set time. This happened no matter what state the item was in (incomplete document, code with bugs). This step:
- Provided a daily backup of every item in the project.
- Gave each project member the opportunity to review the most current version of any item in the project.
- Allowed me to assess the progress made by each member that day.
We implemented a collaboration platform to provide better ways of sharing information among the team members. There are many good products that provide collaboration functionality. For this project, we used Groove. It provided an easy way for team members to share information using tools such as chat, threaded discussions, a file repository, a whiteboard, document sharing, and source control.
Chat and threaded discussions improved the communications among teams and also provided a searchable archive for knowledge gained and lessons learned. The group whiteboard improved information sharing and brainstorming at meetings.
The file repository and document sharing made it easy for the teams to consolidate and share all the artifacts generated by the project, while source control became easier to use because it was integrated into the same tool.
Overall, Groove greatly improved communications among all the teams and provided an excellent tool for the managers to stay abreast of the entire project.
Dealing with change
Of course, as the project progressed, changes were required. Certain assumptions that were made at the initial stages turned out to be invalid and, as with every project, the client’s wants and needs changed too. All requests from the client came to me and the technical lead assessed the effect and determined the best course of action. In most cases, the additional work of isolating the components and tiers contained the impact to a single component or a group of components being developed by one of the remote teams. Only in a few instances did the changes require the work of teams in more than one location.
Most of the lessons we learned on this project apply to all software development, but because the teams were in multiple locations, their impact was magnified.
Duplication began very quickly and in a very simple way on this project. We missed something very simple during the design: tracking the users' names throughout their shopping session. Before long, each team had written its own function for retrieving it from the e-commerce engine. One team even had three separate functions to do this.
Although this seems trivial, had we let this pattern continue, the effect could have been tremendous. This was one of the events that led to the creation of the technical lead role. Our goal became to have every data element represented only once. Each should reside in the database in one location and be read/written from the database in only one database access object. This extended to related groups of data also. For example, a shopper should be represented by a shopper object and every software element that needs shopper information should get it from that object.
This led to the development of a core group of objects to represent the shopping framework, which would be used by each of the development teams as needed.
We also ran into the problem of incomplete code. Because development was phased but the component interfaces were designed up front, each component had many methods that could be called but hadn’t been coded yet.
At times, this resulted in a number of error messages or buggy situations and a lot of communication with the client during development about which features weren’t available yet, even though they were shown on the user interface. It also fostered the attitude that incomplete code and non-graceful error handling were acceptable.
The problem was magnified because of the reduced communications between teams. The time necessary to debug problems increased, which subsequently increased the development time.
To remedy the situation, we changed incomplete functions to return dummy data or gracefully exit, not crash. We took a step back from development to ensure all errors were handled in the same way and logged. It would have been a good idea to get into the habit of logging error messages early on in the development process, rather than adding it as a feature implemented just prior to delivery.
Multiple points of contact
At the beginning of the project, I didn’t control client communication as well as I could have. Each team lead had access to the client. The technical lead also had client access. This became confusing to the client and problematic. Feedback from the client became decentralized and wasn’t correctly reported to management or the other development teams.
Once I created the role of the technical lead, client communication was centralized in the technical lead and myself. Feedback was analyzed, logged, and assigned to the correct team. From the start, the client should have had one primary contact for all items. This kind of mistake can happen in all sorts of projects, but was exacerbated by having teams in multiple locations.
The last lesson I learned had to do with rogue programmers—people who always think they know the better way of doing something. They use their own standards and practices. Often, their code uses custom functions they wrote themselves in place of methods used by core components or other modules of the system. Although their code usually works, their components are often left incomplete and are a maintenance nightmare. Frequently, they become the only programmers capable of maintaining and enhancing the code (job security at its best).
I’ve had to work with programmers like this on several projects, but it's even more difficult when they are working in a different city from their management. Code reviews highlighted what they were doing in their code, but they were reluctant to make the necessary changes. “Why waste time changing it if it already works?” was the argument I heard most frequently.
Solutions that were suggested ranged from “let them be, they’re doing no harm” to “have them taken off the project and write it into their reviews.” Neither extreme helped our development. The solution for this project was to have their work reviewed daily by their team lead and to limit their task list to the module they were working on. This kept them focused on the task at hand and didn’t allow them any additional work until the current work was completed. This didn’t foster goodwill, but it did get the work done.
Development will continue to become more and more decentralized as projects grow, technology improves, and companies increase their reach. New tools and methodologies will continue to be released to support this trend. But the ideas of communication and division of responsibilities will always be essential to the success of these projects.