I believe there are two main types of “teams”: those working together, focusing on doing their best as a team and those working individually, focusing on doing their best on their own. (Yes, some teams are in between.)
I think you can guess based on my wording of those two options, that I prefer working as a team toward a combined goal. By working together, we can accomplish much more. We must be careful along the way, however, to make sure that we don’t do anything that can hurt the teams abilities to work as a team.
Building a good, cohesive team is my greatest achievement in my software development career. Being a part of this team as it achieves great things is what I have received in return. – Brendan Enrick (March, 19, 2012)
I am always trying to make sure that the team is doing well. I try to keep them focused and working together. Most of all, I try to make sure that the things I do don’t hurt the team. It’s important to recognize that decisions and choices we make affect the team a great deal.
Building strong teams requires a lot of work. This post focuses on considerations that I believe are important to creating strong teams. These considerations include: communication, co-location, combined interest, respect, and commitment consensus. I focus on these when trying to create good, cohesive teams.
Communication
Creating great software depends heavily on communication. This is important for the whole team. It’s important that all members of the team be communicating with all other members of the team. If communication breaks down, the team is soon to follow.
It’s important for the whole team to be talking, writing, documenting, and sharing their ideas. Make sure that your team feels safe working together and communicating with each other.
Communication is so obvious as an important aspect of a good team, that I am not going to spend a great deal of time discussing it.
Co-location
There is no easier way of getting a team to work together than to have them located together. Keeping the team close together keeps communication high. Not only does this mean that asked questions will be answered quickly, it also means that questions will be asked. If the team were not together, someone might not have asked the question. This keeps the communication barrier low and the feedback loop short.
I said this was an easy thing to achieve, and it can be. Sometimes there are difficulties with logistics of your space, people not wanting to move, etc. These can happen and can also be worked through. If you don’t have a team room, you can still set up a “command center” in an unused conference room.
I’ve seen both introverts and extroverts do well in co-located teams. When the conversation is on-topic it allows everyone to tune in to what the team is doing. The team will start answering questions immediately, knowing what everyone else is working on, chiming in with assistance on an area of expertise.
Combined Interests and Goals
It’s extremely important that a team have a shared goal. If you fragment the goals of your “team”, you will be fragmenting the “team”. You run the risk that the team will have no incentive to work together. Yes, you might say that since everyone gets along, they’ll work together still, but you’re driving in a wedge that will pull them apart.
I don’t want my team to have individual goals, this will cause them to work on their own and make it harder for them to work together. Anyone spending their time helping someone else would be in danger of not finishing their own work, but I want them working together to achieve more.
Nothing is as detrimental to a team than making them behave less like a team.
By combining the goals and interests of the team, you force them to work together. They get the idea that they’re being graded together and being rewarded together. This will keep everyone on the team at their most productive, because they will all have each other to lean on.
Respect
This word gets four uses here. It is important that members of a team treat each other with respect, it is important that members of a team respect each other, it is important that each member respects oneself, and it is important that everyone respect the code being written.
If one member of the team doesn’t respect another of the team members, the team will not be cohesive. If one member of the team doesn’t show respect to one or more members of the team, the team will not be cohesive.
If one member of the team doesn’t respect oneself, the team will not be cohesive. If one member of the team doesn’t respect the code being written, the team will not be cohesive.
When the team has respect for each other, they will strive to not hinder the rest of the team. This means that they will try not to break the code base. They will try to make sure that they build good, simple designs that everyone can appreciate. And communication will also flourish.
When the team has respect for themselves and the code they’re writing, they will strive to write clean, simple, well-tested code. The team will care about the work they’re doing and will avoid creating a big messy codebase.
Commitment Consensus
Making any commitment as a team must be done with a consensus among the group. One of the worst things that can be done to a team is to set their commitments for them. You can’t tell someone else what they are required to commit to.
Commitments have to be made willingly or the commitment might as well not be made at all.
This mistake is commonly made by people assigning work for the team to work on without getting their feedback on it. If you assume that a team can get X amount of work done without asking them, you’re asking for trouble. First, you’re making their decisions for them. This is going to make you into the opposition of the team. Second, you’re not soliciting their opinions or feedback.
Often this means that someone who is not going to be doing the work has estimated the time the work will take to complete and has assigned this work to individual team members. This will break the combined interest, encourage the team to break from their co-location, and cause the team to feel the person making those decisions isn’t taking them into consideration.
The right way is to work with the team. If you do need a commitment on something, you should work with the team to create that commitment. This usually means sitting down and working with them on it. Get them to decide what they can accomplish in an amount of time. Work with them to decide what will be worked on. This means that the person deciding the direction of the project should be directly talking with the development team doing the work.
Getting people together, working together, collaborating, is what makes teams effective. Don’t try to force them into doing something they don’t want to do. It will backfire on you. Plus, they’re likely not going to uphold that commitment. It wasn’t their commitment anyway. Not really.
The Team
If you manage to get the team working together effectively, keep it up. Try new things, but don’t let it destroy the team. If it looks like it’s hampering the team’s togetherness, quit doing it. Find another way of doing whatever you’re doing.
Don’t force the team into processes they don’t like. Let them create a process that works for them. Give them the tools and enable the team to make the right choices. Empower your team! Make sure that you never become the opposition of the team. Try to be part of the team. Align your interests with theirs.
So as a bit of fun, since I just wrote a post about
duck typing and foreach loops, I thought I would take a look at what’s happening under the hood when we use this trick. To start with, I will have two classes, which each have GetEnumerator methods. The first one is using DuckTyping, so it doesn’t implement any interfaces. The second one is implementing the IEnumerable interface. Finally, I have a third class with a method that just uses a foreach loop over instances of the other two classes.
<p>The code for my little example looks like this:</p> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; max-width:660px; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> DuckCollection<br>{<br> <span style="color: #0000ff">public</span> IEnumerator GetEnumerator()<br> {<br> <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> NotImplementedException();<br> }<br>}<br><br><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> EnumerableCollection : IEnumerable<br>{<br> <span style="color: #0000ff">public</span> IEnumerator GetEnumerator()<br> {<br> <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> NotImplementedException();<br> }<br>}<br><br><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> ForEacher<br>{<br> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> DoForEach()<br> {<br> var duckCollection = <span style="color: #0000ff">new</span> DuckCollection();<br> <span style="color: #0000ff">foreach</span> (var thing1 <span style="color: #0000ff">in</span> duckCollection)<br> {<br> <br> }<br><br> var enumerableCollection = <span style="color: #0000ff">new</span> EnumerableCollection();<br> <span style="color: #0000ff">foreach</span> (var thing2 <span style="color: #0000ff">in</span> enumerableCollection)<br> {<br> <br> }<br> }<br>}<br></pre>
After I compile this code, I’ve opened it up with IL DASM, so I can see what the generated IL is for this code.
.method public hidebysig instance void DoForEach() cil managed
{
// Code size 146 (0x92)
.maxstack 2
.locals init ([0] class DuckTypingILCode.DuckCollection duckCollection,
[1] object thing1,
[2] class DuckTypingILCode.EnumerableCollection enumerableCollection,
[3] object thing2,
[4] class [mscorlib]System.Collections.IEnumerator CS$5$0000,
[5] bool CS$4$0001,
[6] class [mscorlib]System.IDisposable CS$0$0002)
IL_0000: nop
IL_0001: newobj instance void DuckTypingILCode.DuckCollection::.ctor()
IL_0006: stloc.0
IL_0007: nop
IL_0008: ldloc.0
IL_0009: callvirt instance class [mscorlib]System.Collections.IEnumerator DuckTypingILCode.DuckCollection::GetEnumerator()
IL_000e: stloc.s CS$5$0000
.try
{
IL_0010: br.s IL_001c
IL_0012: ldloc.s CS$5$0000
IL_0014: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_0019: stloc.1
IL_001a: nop
IL_001b: nop
IL_001c: ldloc.s CS$5$0000
IL_001e: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0023: stloc.s CS$4$0001
IL_0025: ldloc.s CS$4$0001
IL_0027: brtrue.s IL_0012
IL_0029: leave.s IL_0048
} // end .try
finally
{
IL_002b: ldloc.s CS$5$0000
IL_002d: isinst [mscorlib]System.IDisposable
IL_0032: stloc.s CS$0$0002
IL_0034: ldloc.s CS$0$0002
IL_0036: ldnull
IL_0037: ceq
IL_0039: stloc.s CS$4$0001
IL_003b: ldloc.s CS$4$0001
IL_003d: brtrue.s IL_0047
IL_003f: ldloc.s CS$0$0002
IL_0041: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0046: nop
IL_0047: endfinally
} // end handler
IL_0048: nop
IL_0049: newobj instance void DuckTypingILCode.EnumerableCollection::.ctor()
IL_004e: stloc.2
IL_004f: nop
IL_0050: ldloc.2
IL_0051: callvirt instance class [mscorlib]System.Collections.IEnumerator DuckTypingILCode.EnumerableCollection::GetEnumerator()
IL_0056: stloc.s CS$5$0000
.try
{
IL_0058: br.s IL_0064
IL_005a: ldloc.s CS$5$0000
IL_005c: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_0061: stloc.3
IL_0062: nop
IL_0063: nop
IL_0064: ldloc.s CS$5$0000
IL_0066: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_006b: stloc.s CS$4$0001
IL_006d: ldloc.s CS$4$0001
IL_006f: brtrue.s IL_005a
IL_0071: leave.s IL_0090
} // end .try
finally
{
IL_0073: ldloc.s CS$5$0000
IL_0075: isinst [mscorlib]System.IDisposable
IL_007a: stloc.s CS$0$0002
IL_007c: ldloc.s CS$0$0002
IL_007e: ldnull
IL_007f: ceq
IL_0081: stloc.s CS$4$0001
IL_0083: ldloc.s CS$4$0001
IL_0085: brtrue.s IL_008f
IL_0087: ldloc.s CS$0$0002
IL_0089: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_008e: nop
IL_008f: endfinally
} // end handler
IL_0090: nop
IL_0091: ret
} // end of method ForEacher::DoForEach
Yes, it’s a bit ugly, but you will notice that other than naming, the code is just repeated twice. This is of course what we would expect, since the code should treat it the same regardless. All the foreach loop needed was to be able to get the object from the GetEnumerator method. Once it has that, it just uses the enumerator to do all of the work. This means that either class should work just as well.
This is the repeated line of code that shows up in two places to get the enumerator it will be using for its MoveNext() and GetCurrent() methods.
IL_0009: callvirt instance class [mscorlib]System.Collections.IEnumerator DuckTypingILCode.DuckCollection::GetEnumerator()
IL_0051: callvirt instance class [mscorlib]System.Collections.IEnumerator DuckTypingILCode.EnumerableCollection::GetEnumerator()
Now if you’re really paying attention, you will have looked at the Try-Finally block that is in the code to handle our IDisposables. That’s another neat thing happening behind the scenes, but that’s another blog post entirely.
If you would like to see another cool thing in the .NET Framework, you should check out what else you can do with Null Instance methods if you change those callvirts.
The coding dojo at CodeMash 2012 was a blast this year. I ran two events in the dojo: a group exercise doing the Gilded Rose kata and the Ball Flow agile game. I thought the gilded rose kata we did as a group exercise was a great success. We had a good group of people, which was impressive considering that even with floor decals, people had trouble finding the coding dojo.
The coding dojo at codemash is a great place for actually doing things at CodeMash. If you’re tired of sitting there having someone talk at you, head to the coding dojo. It’s a place for writing code, learning, experimenting, and having a great time. We did katas, programming exercises, and some educational games in the dojo this year. If you did not make it to the dojo this year, we hope to see you next year!
Ball Flow
The Ball Flow game is an Agile exercise where a team of people work together in an experiment in self organization. The team will do some estimation, some planning, some retrospectives, and they will be trying to continually improve their process while aspects outside of their control continue to change. The team has to adapt and figure out how to keep working together effectively.
Object of the game:
Pass each of the 20 balls to each person in the group.
Rules of the game:
- A person may touch a ball more than once, but doing so isn’t ideal.
- Two people may not be touching the ball at the same time.
- You may not pass the ball to your nearest two neighbors
- If the ball touches walls (including floor and ceiling) or any furniture it must start over.
- The person who first picks up the ball must be the last to touch the ball.
What this group did
Our group started out by figuring that if they created an oblong shape, they could pass across pretty easily. They got in this shape and began passing around. They had two tall people stand back a step so that they could launch the ball over everyone else across the group. Their final pass went behind the backs of one side of the group back to the starting person who removed the ball from the game.
They spent some time planning and adjusting between each iteration. They made sure not to make big changes fearing the catastrophe that could occur. Each time they made modest improvements to their time.
As the game went on we added challenges, in one round we added a large number of pens that needed to be passed around as well.
In the final round we added in bags of potato chips, which were harder to throw across the room. Each time the group still managed to make slight adjustments to accommodate these changes and still slightly improve their times.
The CodeMash 2012 Ball Flow team was awesome! Great job everyone!
During my Software Craftsmanship Precompiler session, I heard one of the students say, “all you need is an IEnumerable to use a foreach loop”. This sparked a bit of fun when I asked Steve Smith, my co-presenter, if that was correct. He confirmed that it was, and I disagreed. Being the scientists that we are, we decided to try it and see what happened. I of course knew that duck typing in C# should allow the Foreach loop to compile without anything having the method required by the IEnumerable interface. This means that we just need a GetEnumerator method.
We wrote the code that did this and it compiled!
Duck typing is awesome, because it allows the language to treat my type the way I want it to because it has the right tools to do the job. The term duck typing comes from the idea that if it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.
In the foreach loop example, duck typing assumes that what you have here is able to be enumerated, because it has a method to get the enumerator. If we look at the IEnumerable interface, we can see that this is what we are required to implement.
public class MyCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
Now that we have our collection written and implementing IEnumerable, we can write a foreach loop that uses our collection.
var myCollection = new MyCollection();
foreach (var thing in myCollection)
{
// Do something with the thing
}
Finally, because of the duck typing in C#, we can remove the interface from the code, but keep the method.
public class MyCollection
{
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
It still compiles!
One of the many cool things about C# that I love. It’s a fun language, so go experimenting!