In a post last week I talked about the Anti Team. It was sarcastic, snarky, negative, and generally kinda fun to write. I didn't want to leave it like that though, so I want to talk about my ideal software development team. If you read both posts you'll probably notice that the bad extreme is largely drawn from traditional waterfall shops and my ideal is borderline XP propaganda. There's a simple cause for that: I've simply had far more positive experiences working in Agile teams and that's the atmosphere and culture that I think gives me the best chance for success. Anyway, here's my attempt at being positive and describing the qualities and structure of my ideal team.
See the Whole
The first ideal is that the team is all working toward a common goal — making the customer happy by shipping working software. One of the powerful ideas from Lean Development is the "Fallacy of Local Optimization." Instead of making decisions to optimize the individual workflows of requirements, coding, and testing in isolation, look at the larger goal of shipping software and work towards that goal instead. Let's do a deeper dive into the various workflows and see how a local optimization of each could hurt a project overall:
- If the business analysts define their job solely as creating requirements specification documents, they will certainly act to get the requirements sewn up and signed off as quickly as possible. I would prefer that the analyst role be defined as determining and communicating the requirements to the rest of the team. That's a subtle shift in goal, but it might cause the analysts to drastically change the manner and mechanisms for interacting with developers, testers, and customers.
- Coding is the bottleneck in throughput right? Not exactly. Code cannot be shipped until it is tested and deployable. As anybody who reads my blog regularly knows, I'm a big believer is comprehensive test automation. That kind of test automation can only happen through very close collaboration with the testers. I think that testability is a first class design consideration because it directly impacts the throughput of the entire team. By the same token, testers cannot work if they can't get the latest version of the code onto their desktops. Ease and reliability of installation is a major contributor to project success, but it only happens with the developers making it so. Making testable code and easily deployable code might burn more developer hours, but it will get the code out faster.
- Testing isn't about finding defects, it's about removing the defects from the code. A tester that works hand in hand with developers to explain reproduction steps and expected results does more good than a tester who simply files defect reports in whatever awful bug tracking tool you use.
I've worked for over ten years (how did that happen?) on team oriented projects. One of the first, and most important, lessons I had drilled into me was that it was important to understand the other disciplines on the project. We spend a lot of time interacting with people that do different jobs than us, and our software doesn't make it out the door without contributions from these folks. The more you understand about their jobs, the better you can interact with them and support their activities. As a developer, I can contribute more to the project if I understand and accommodate the needs of my project manager, analysts, and testers.
Know the Why
I'm going to adamantly stand by this statement: creating a good design and architecture is easier than socializing that same design throughout the team. As I've said before, the more specific your instructions are to another developer, the worse the results are going to be. You'll get far better results if the team as a whole understands the reasoning behind design decisions. Case in point, I'm doing a WinForms project and that almost automatically means splitting the screens into Passive View's and Supervising Controllers (that's a mouthful, thanks Martin). Simply telling the other developers that were new to these patterns to avoid putting logic into the UserControl's didn't take because it seemed arbitrary and senseless. Take the team aside and explain the rationale for the design decision (better testability, splitting behavior from display), and they will be far more able to follow the design because they can make qualitative judgements themselves as they work. As a technical lead you know you're doing well when everybody, right down to the junior most person, is contributing to your design with suggestions to improve the design.
Requirements handoff can be a major source of risk and churn. Even assuming that the requirements are perfect upfront (puh-leeze), the developers' and testers' understanding of those requirements may not be. No matter how hard the analysts or customers try, the upfront requirements will not cover all possibilities and angles. At some point the developers are going to have to exercise their own judgement about what the clients want. Even better yet, developers should be thinking of ways to improve the user experience and contribute back. That understanding and ability to act happens best as a result of understanding the rationale for requirements decisions.
Maybe all "Know the Why" is about is just keeping your eyeballs on the end goal instead of being buried by day to day minutiae.
Maximize Communication Bandwidth
I believe that the best way to See the Whole and Know the Why is to maximize the flow of communication within the team. Check out this graphic from Alistair Cockburn's seminal paper Characterizing people as non-linear, first-order components in software development:
The most effective form of communication is two (or more) people talking at the whiteboard. The least effective form is documentation. Why? Let's think about what's different in the two extremes. When I'm discussing a design problem with a colleague at the whiteboard we're able to interact, ask each other questions, convey information through body language, and illustrate our ideas on the whiteboard at will. Exchanging documentation is static and one way. A great deal of contextual information is potentially lost as the document goes from the author to the people downstream. There's no room for interaction at all.
Given a choice, I want the entire team collocated in a single space. Offices, cubicles, and generally isolation choke off communication and collaboration. Collocation offers vastly more opportunities for the more effective forms of communication. I've never particularly found the extra noise of an open office space to be a problem, but maybe I'm just used to it.
The key point is that I want to talk to all the members of my team.
Small and Self Contained
I want my team to be as close to self-sufficient as possible. Call me paranoid, but I dread any dependency on any person that does not have a direct stake in my project's success. It takes a significant amount of overhead to coordinate a project when you have to depend on people outside your project that are getting tugged and pulled in many different directions. You potentially lose a lot of the advantages of adaptive planning and iterative development if you have to coordinate with outside teams whose schedules are not flexible. I've always thought projects went smoother when I could make adjustments to our database or other infrastructure instead of having to wait for an external group to do it for us — usually after some sort of artificial paper process.
Last summer I got to see Bruce Tate give a very good talk about building good teams. One of his key points that resonated with me was controlling the size of your team to an ideal of 4-6 developers. A lot of the overhead of doing a software project is creating and nurturing a common understanding and a shared vision throughout the team. You simply have less communication latency on a smaller team. Now, to get there with a smaller team of developers, those developers must be able to perform what might have been multiple roles in a traditional project structure. Personally, I think that makes for a much stronger team. It definitely makes scheduling much more flexible as one iteration may be 80% database work and the next iteration is all user interface enhancement. Give me utility infielders over left handed middle relievers any day.
And another thing, it's vastly better to have a small team of people who are dedicated (100% allocated) to the project than a dozen people who are working on 3-4 different projects simultaneously. I can't imagine any thoughtful person arguing with me about that statement, but splitting people across projects seems to be fairly common (in a past life, I was once the responsible architect for 7 projects, at least on paper). Whatever organizational flexibility you think you might be buying by splitting people across projects is more than lost by inefficient context switching. Put another way, when I have requirements questions, I want to go ask a business analyst that's 5-10 yards away and completely immersed in the project. Contrast that to the waterfall experience of tracking down the BA on the other side of the building that wrote up your requirements 3 months ago and has no recollection of why the requirement reads that way.
The Project Manager as Fullback
For you unenlightened folks who don't follow American football, a fullback tries to blast through the holes ahead of the ballcarrier and pick off any would be tacklers so the halfback (us developers of course) can scoot through on his way to glory. In an iterative process, you want the developers and testers to be like a machine that runs continuously at a steady hum. At the start of every iteration a set of detailed requirements is ready to feed into the machine. I want a project manager who deals with external forces and processes as they come up to avoid stopping the machine. The best way to keep the machine running is to have Joel Spolsky's Developer Abstraction Layer, and a major part of that is a Project Manager acting as an offensive line looking ahead of the development to proactively deal with any issue that could slow down the developer/tester machine.
I worked with a project manager years ago that didn't know squat about our process or Microsoft Project. Quite frankly, the customer and I drove the project as a skunkworks project and she was more than a bit flustered by that. She might have thrown up her hands trying to rein in a headstrong young technical lead charging ahead, but the one thing she did was get out in front and take care of all the external process stuff so everybody else could concentrate on making the system be good. To this day, that project is by far and away the most satisfying and successful project I've ever been a part of. It's only recently that I've come to realize the contributions the project manager made — even though most other project manager's at that company would have scoffed at the role she played.
Trust, Transparency, and Reflection
I owe my teammates a degree of honesty about the progress I'm making and the roadblocks I'm facing. I need the same from the other developers. If a project manager is going to be my lead blocker, I need to be very open and tell him or her the problems that we're having or expecting. If things aren't going well, or taking longer than expected, the PM needs to know sooner rather than later to start making contingency plans. In turn, I need to be able to trust my PM to admit problems.
Needless to say, a blame culture is self-defeating. The only way to get better as a team or organization is to openly face your problems and find better solutions. If you're afraid of reprisals from above, those problems are going to be swept under the carpet and fester.
Of course, eliminating a blame culture isn't enough. As a team you must be willing and able to be reflective. Pay attention to what works and do more of it. Talk through what isn't working, and find and apply better ways. If there's one single thing I've contributed to my current client's practice, I hope it's conducting retrospectives on a regular basis.
Own the Process
In the Anti Team, I blasted centralized process and methodology groups. The best way for a development team to optimize is to be empowered to own their own practices. The process should work for the team, not the other way around. Since each project is different, I think every team should have some leeway to organize their own practices and do so responsibly. I despise the interpretations of CMMI that require bureaucratic rigamarole before you can make any deviations from the proscribed process.
I worked on a nearly fullblown Extreme Programming project with an elite group of consultants that I think would have failed completely — except for a small change in the way we did iteration planning. That was the first time I realized that process was a tool that could be consciously wielded instead of some sort of arbitrary set of nonsensical rules.
Here is a quote from a post by Rocky Lhotka that I think is potentially short sighted (emphasis mine):
Agile is just Waterfall in random order, and with a few different techniques and tools. In the end it all comes down to gathering requirements, analyzing them, translating that into a design, doing some coding and some testing and away you go. You can rearrange the pieces on the board, but they are the same pieces.
Forget for now any comparison between the polar extremes of Agile versus Waterfall development, it most certainly does matter when and what order these activities occur. Think about the game you play in elementary school where you line up and you try to relay a message down the line by whispering in the next person's ear. Inevitably the original message is distorted by the time it gets to the last person in the line. That's a perfect analogy for sequential development. What I would advocate is simply hearing the message at exactly the same time. I think there's an efficiency gain by simply blurring the traditional waterfall phases. Do all of the workflows for the active features/stories at nearly the same time to maximize the collaboration between all of the disciplines on the project.
A huge, but common, source of project churn is the testers coming to a different interpretation of a requirement than the developers. Divergent interpretation always leads to trouble. By simply having testers and developers start a feature at roughly the same time, and shortly after the analysts for that matter, you can come away with a shared understanding upfront. Even better yet, if you can get the testers just a bit ahead of coding, the developers can code to unambiguous acceptance tests and know when their code meets the requirements.
Human beings don't have perfect recall. It's easier for me to fix bugs in code I wrote this week as opposed to code I wrote 2 months ago, and it's definitely going to be easier for an analyst to talk over the details of a user story that is fresh in their memory.
Eric Evans introduced us to the idea of a Ubiquitous Language for all team members. Roughly defined, the team can communicate quicker with greater ease and less misunderstanding if the entire team is using a common vocabulary to describe the concepts in the system domain. The lack of a shared ubiquitous language hampers a team when the analysts and developers struggle to understand one another because they're using different terms for the same concepts (or the same terms for different concepts). Unsurprisingly, I think the best way to found a ubiquitous language is close collaboration between analysts and the rest of team starting very early on and continuing to the end of the project.
Back to "Know the Why." The best way to understand the requirements or proposed design is to participate in their formulation. It's extremely valuable to have the developers and testers involved during requirements and analysis. The developers can be much more effective if they were there for the early design discussions. Specifications are just too "loss-ey" to act as a medium for communication.
Thinking and learning on a project never stops, even if it's only directed at getting better for the next project or release. Good teams challenge their approach every single day and keep up a constant dialogue. That constant dialogue drives improvement and the shared understanding of the project.
And they lived happily ever after…
It's late, and I've got to get in early to kick off a 90 minute build before the rest of the team comes in. Good night all you princes of software development, you kings of code slinging.
I'd completely (and blessedly) forgotten about this one. Here's another great example of an Anti Team.