Geek Noise
Rants, rambles, news and notes by Peter Provost
07

Software Development Teams and Sports

Thursday, 7 August 2008 07:52 by Peter Provost

283716_1341 For a long time I’ve made the analogy that the best software development teams are like basketball or hockey teams, and lately I’ve been thinking more about how you can recognize what kind of a team you have by continuing this analogy and looking for similarities and differences.

In sports there are a few different kinds of teams. There are teams like gymnastics or bowling where the final result of a match is a result of the combined individual efforts of the team members, but the efforts of the team members aren’t combinatorial. In other words, on an Olympic gymnastics team, the team medal is awarded to the team who’s combined individual scores are the highest. On a bowling team, each player’s score is added together and the team with the highest total wins.

Another kind of sports team is the kind you see in American Pro Football. Here we have one team that is subdivided into two or three parts. The offense is a sub-team that works together to score points. The defense is another sub-team that works together to prevent the opposition from scoring points. There are other sub-teams for special activities like punt returns, field goals, etc.

Basketball, hockey, soccer and rugby are examples of yet another kind of team. On these teams the whole team is working together for the entire game to accomplish their task. There may be specialists on the team like goalies, defenders and wings who have focus areas, but if the time came for an offensive player to block a goal or even a goalie to shoot and score, they would do it.

The best functioning agile teams that I’ve worked with have been like that last kind of team. We have specialists who are good at certain things, but when the time comes to do some work, anyone and everyone does what needs to be done. We can talk all day about elimination of roles on agile teams, but we know from experience that the best testers are people with a natural bent for it. There are also people who are instinctive toolsmiths and will take small taxes that affect the team and mitigate them by adding script or a tool that benefits the whole team. But when it is time to signup for a task, or pair with someone, or fix the build server, or write a new test harness, everyone on the team is prepared and empowered to do that work.

I have also seen agile teams that are more like American Football teams. The most prominent indicator of this is a separation of developers (offense) from testers (defense). This can work, and a large number of teams work this way, but as with football, sometimes the defense finds itself with the ball and if they may not really know what to do with it. Or even worse, they may not feel empowered to do something with it.

You will also find that there are development teams that are more like gymnastic teams. Indicators of this are things like “class ownership” or "module ownership”. When you find architects who must design all the details before a developer can “code it up” you are likely seeing a gymnastics team. Almost any time you find architectural, design or process siloing, you are probably seeing one of these teams. As with gymnastics, these teams can be successful, but it creates a different culture than the one I’m a fan of.

One of the key differences between these types of teams is the attitude about work and dependencies between people. On a hockey or basketball team, the team must work together to win. You can put an amazing group of individuals together, but if they don’t play well together, they won’t win. Done well, the work is combinatorial, where the effort of one person improves the people around them and thereby improves the team. If someone falls down on the front line in a hockey game, you will be unsurprised when the defenseman continues forward and attacks the goal.

Each subteam on a football team behaves this way, but they can’t cross the boundaries very well. The people on the field are interdependent, but they are still siloed into certain responsibilities and expectations. Some might say that this is a result of the way the game is played, with each side taking turns, but in some college and most high-school football teams, the players play “both ways”, meaning that the same people play on both offense and defense. On those teams, when the ball is intercepted, you are much more likely to see the person with the ball being someone who knows how to run and/or throw.

On teams like gymnastics teams, though, you see something different. The person doing floor exercise goes and puts up a score, then the person doing parallel bars goes next, etc. One person can’t really help the next person other than by making a strong enough score to boost the overall team.

The next time you’re thinking about your team, about roles, about siloing and ownership, take a look around and think about what kind of team it is. Think about what kind of team you want. And think about what the forces are that are driving your team to be one way or another. You might be surprised what kind of team you’re on.

(Photo by jimmybop)

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
10

Scrum of Scrums Haiku

Thursday, 10 July 2008 06:05 by Peter Provost

Agility (Binshou) Kanji My Scrum of Scrums has
Become something other than
What I want it to be

It should be simply
A coming together of
Technical people

Instead it becomes
Like a management review
I lieu of sharing

What did you do since?
What will you do until we?
Is something blocking you?

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
08

Taking on dependencies from non-agile teams

Tuesday, 8 July 2008 03:58 by Peter Provost

After a spirited discussion this week on one of our internal agile aliases, Eric Gunnerson wrote a post on his blog that wraps up his thinking (and mine) about how to deal with taking dependencies on a non-agile team when your team is running in an agile manner:

Eric Gunnerson's C# Compendium : Taking on dependencies

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
30

Inherit to Be Reused, Not to Reuse

Monday, 30 June 2008 13:26 by Peter Provost

I'm surprised how often I have to say this to other developers and engineers, but violations of this simple object-oriented mantra seems to be everywhere. Almost every time I look at a class inheritance hierarchy, I find this principle violated.

Why is this use of inheritance bad? First of all, let's talk about what inheritance is good for:

  • Polymorphism - In OOP, this means that you can treat derived classes as if you had been passed an instance of the parent. This was formalized by Barbara Liskov in her 1988 paper "Data Abstraction and Hierarchy". Another way to say is is, "Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it." [Martin-96]
  • Categorization - The process in which ideas and objects are recognized, differentiated and understood. Categorization implies that objects are grouped into categories, usually for some specific purpose. Ideally, a category illuminates a relationship between the subjects and objects of knowledge.

Let me refer you to the wonderful book, C++ Coding Standards: 101 Rules, Guidelines, and Best Practices by Herb Sutter and Andrei Alexandrescu:

Despite two decades of object-oriented design knowledge, the purpose and practice of public inheritance are still frequently misunderstood, and many uses of inheritance are flawed.

Public inheritance must always model "is-a" ("works-like-a") according to the Liskov Substitution Principle: All base contracts must be fulfilled, and so all overrides of virtual member functions must require no more and promise no less than their base versions if they are to successfully fulfill the base's contract. Code using a pointer or reference to a Base must behave correctly even when that pointer or reference actually points to a Derived.

...

Public inheritance is indeed about reuse, but not the way many programmers seem to think. As already pointed out, the purpose of public inheritance is to implement substitutability. The purpose of public inheritance is not for the derived class to reuse base class code to implement itself in terms of the base class's code. Such an is-implemented-in-terms-of relationship can be entirely proper, but should be modeled by composition—or, in special cases only, by nonpublic inheritance (see Item 34).

Let me call out one of the more importance sentences in that quote:

The purpose of public inheritance is not for the derived class to reuse base class code to implement itself in terms of the base class's code.

The inheritance relationship is one of the strongest coupling relationships we can have in OOP. Everyone knows that coupling is bad and cohesion is good, but we still couple like mad via inheritance. We do this for a number of reasons, but one of the big ones is that very few college grads seem to get taught this in school. It makes me wonder how many undergraduate compsci teachers actually get it. Daniel Pietraru wrote a bit about this and how he has used inheritance questions as interview questions.

The other reason I think it is so common is that our languages and tools make it look so easy and so proper. Even Fowler-esque Refactoring has refactorings called "Pull Up Method/Field/etc." that seem to be all about putting shared code into the base class. There is also the Abstract Test Pattern in TDD which specifically describes using base classes as "a way to reuse test cases".

Whenever possible, you should look to use composition instead of inheritance in your designs. The problem is that composition is harder to do, even though it results in cleaner more modular designs. Despite that, composition has a number of benefits over inheritance. Again, I'll let Messrs. Sutter and Alexandrescu tell it (remember that some of the techniques for pointers and such are very C/C++ centric and aren't relevant here, but the underlying meaning is still true):

Composition has important advantages over inheritance:

  • Greater flexibility without affecting calling code: A private data member is under your control. You can switch from holding it by value to holding by (smart) pointer or Pimpl (see Item 43) without breaking client code; you would only need to change the implementations of the class's own member functions that use it. If you decide you need different functionality, you can easily change the type of the member or the manner of holding it while keeping the class's public interface consistent. In contrast, if you begin with a public inheritance relationship, it is likely that clients have already come to depend on the inheritance; you have therefore committed your class to it and cannot easily change your base class decision later on.
  • Greater compile-time insulation, shorter compile times: Holding an object by pointer (preferably a smart pointer), rather than as a direct member or base class, can also allow you to reduce header dependencies because declaring a pointer to an object doesn't require that object's full class definition. By contrast, inheritance always requires the full definition of the base class to be visible. A common technique is to aggregate all private members behind a single opaque pointer, called a Pimpl.
  • Less weirdness: Inheriting from a type can cause name lookup to pull in functions and function templates defined in the same namespace as that type. This is very subtle and hard to debug.
  • Wider applicability: Some classes were not designed to be bases in the first place. Most classes, however, can fulfill the role of a member.
  • Great robustness and safety: The tighter coupling of inheritance makes it more difficult to write error-safe code.
  • Less complexity and fragility: Inheritance exposes you to additional complications, such as name hiding and other complications that can arise in the presence of later changes to the base class.

In essence, inheriting for code reuse makes your design brittle. Changes in strange places manifest themselves in even stranger places. If your language doesn't support multiple inheritance (like C# and Java), then if you use an form of class-based inheritance in your code, you are effectively preventing good Liskov-style inheritance by people who consume your code. Bad bad bad bad.

When you do use inheritance from a base class in your design, look for these gotchas:

  • Protected methods in the base class - This is the stink that is the smell that Herb talks about above.
  • Calling public methods in the base class from the derived class - Slightly less smelly, but still not good.

Honestly, it makes me want to try to eliminate all nonabstract inheritance in my code. In languages with good duck typing, I'd say eliminate inheritance entirely, because in those systems the only good reason to use inheritance is for derived class code reuse. I know this is an over aggressive reaction but I do wonder what our code would look like if we had good composition constructs in the language (we don't) and if we either went with pure duck typing (ala Ruby) or interface-only inheritance.

Like that's gonna happen...

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
27

Replacing ExpectedException in NUnit 2.4

Friday, 27 June 2008 06:14 by Peter Provost

Jim Newkirk, Brad Wilson and I have been in agreement about the evils of ExpectedException for a long time. When Jim and Brad wrote xUnit.net, in fact, they left it out and opted instead for a new Throws method that lets you be a lot more precise about what and when you are testing the exception.

But NUnit 2.4.x doesn't have this feature (2.5 will). Fear not! Jim has written a nice little sample of the Throws method for NUnit 2.4.x that provides this same experience in his new post Replacing ExpectedException in NUnit.

If you are using NUnit today, I would really suggest you read the post and consider changing the way you test exceptions in your unit tests.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:  
Categories:   Agile Software Development
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed
29

Tracking Actual Work Done vs Estimated Work Remaining

Thursday, 29 May 2008 02:51 by Peter Provost

I see this get discussed all the time on some of the agile aliases I'm on.

I care how much time is left, not how much time you spent on it.

I know people like to talk about “using the data to make our estimating better” but there are flaws in that argument that just can’t be ignored:

  1. Nobody ever does it. In fact, I don’t even know of a process to achieve this. Hollering at people who over/under estimate is not an improvement process.
  2. It assumes you can make developer estimates better. More experienced developers estimate better, that I’ll take as a given, but can you accelerate this with novice/junior developers or testers? I don’t think so.
  3. Software is NOT like mechanical engineering. It is a craft. Every activity you do is very likely the first time you’ve done it exactly that way. So our inability to accurately and precisely estimate shouldn’t be all that surprising.

At least that’s how I see it. :)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
13

Simulated Agile Team Rooms

Tuesday, 13 May 2008 05:32 by Peter Provost

Today on an internal agile alias, a discussion came up about simulating agile team rooms for disbursed teams. I've played around with this for years and had some suggestions for them:


It can be simulated, but it is hard and requires extra discipline by the team. A few key things:

  1. Think about how to simulate the “in the room” experience where you can overhear and participate in conversations going on around you? Team void chat software like Ventrilo, Team Speak or our own Corporate Conference Calling system can work. Can you have an “open mic” in the team room? You also can give up on audio and use team room chat software like IRC. I’ve used them all. There are plusses and minuses to each.
  2. Think about the changes you may need to make to development practices. Do you use Pair-Programming and TDD? If so, you may want to take a look at Micro-pairing as a technique for coordinating the TDD/Pair handoffs. (Micro-pairing was actually created in response this exact scenario. I was pairing with another developer who was remote.)
  3. In addition to practice changes, think about how to deal with remote desktop sharing. Live Meeting works, but can be a bit heavy. Virtual Server and the standalone Virtual Server client actually let two people connect to the same desktop. I know that VNC, an open source remoting tool, also allows this, but I would recommend you to be cautious with that tool. It has some known security bugs and your network admins may not allow it. Check with them first.
  4. Make sure everyone on the team has all the necessary access they need to be a full team member. Access to version control, portals, file shares, email aliases, etc. all must be available.
  5. Think carefully about how you do your team meetings. When you have only 1 or 2 people who are remote and the rest of the team is in a room, the person on the far side WILL feel out of the loop unless you run the meeting as if everyone were remote. One thing I’ve heard of is to actually have everyone go into their individual offices and dial-in to the meeting so everyone is on an equal footing.
  6. Drastic time zone differences can make this very very hard on some team members. Ultimately this can be make-or-break for successful disbursed teaming. If people are 8 hours apart, when do you schedule standups and IP meetings? My rule of thumb is that more than 3-4 hours apart will kill you and you should split it into two teams that are closer in time to each other.

These are based on 3-4 years of playing around with these concepts at P&P. YMMV.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
10

xUnit.net 1.0 RC3 Released Today

Thursday, 10 April 2008 05:23 by Peter Provost

See Brad Wilson's post: http://bradwilson.typepad.com/blog/2008/04/xunitnet-10-rc3.html

Technorati Tags: ,,,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
26

Agile Chronicles: Leading Volunteers with Agility

Tuesday, 26 February 2008 04:36 by Peter Provost

I found this nice article today in this month's Agile Chronicles:

Agile Chronicles: Leading Volunteers with Agility

I found it particularly relevant because I am an officer in a club and have often felt that I could better apply some of the agile values to that organization and not just to my work as in software development.

Enjoy!

Technorati Tags: ,,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
12

TDD with PowerShell - Mocking Things

Monday, 12 November 2007 02:04 by Peter Provost

Recently, I’ve been dabbling with doing TDD in PowerShell. I think there may be a TDD Framework brewing in my head, but at this point I haven't done enough to figure out what such a framework would look like. Often I find that the functions I’m writing depend heavily on built-in cmdlets and BCL types and there can be issues mocking them out when the underlying .NET type isn’t easy to mock out. This isn’t so much an issue with PS as it is an issue with .NET, but since PS is very close to the edge of the world (where the code touches the user), it can be hard to mock.

That said, as with most dynamic scripting evnironments, you can mock out a lot of things. Suppose you want to test a function that depends on get-childitem. Because functions evaluate before cmdlets, you can actually replace it by defining a function with that name:

function get-childitem() 
{ 
return @()
} 

Now you have a naked stub get-childitem that returns an empty array. All is good so far. Next you need a gci that returns a single FileInfoObject and for your test you want to have the “archive” bit set on this file. You try to create a new replacement function for get-childitem:

function get-childitem() 
{ 
$fi = new-object System.IO.FileInfo(“bogus.txt”) 
$fi.Attributes = [System.IO.FileAttributes]::Archive 
} 

But at this point you discover that you can’t set the Archive bit, because the file doesn’t exist.

This is actually a common problem we run into when we TDD up against another API that isn’t mock friendly. In an OO language like C#, I will typically wrap it up in another class & interface that I own and then mock out the interface for my code. This is do-able in PS, but a little more complicated because you may have to implement a fair amount of extra code to create and return a PSObject that has the interface you expect to find in your calling code. (This code can be a lot smaller, but less clear if you want… I opted for clarity):

function get-childitem() 
{ 
$fi = new-object PSObject 
$getter = { return [System.IO.FileAttributes]::Archive } 
Add-member –inputObject $fi –memberType ScriptProperty –name Attributes –value $getter $secondValue $setter 
Return $fi
} 

The challenge with this approach is the amount of code it takes to mock out all of the parts that you need. For example, if you need the Mode script property that comes built in to PowerShell for DirectoryInfo and FileInfo, then you will have to add them to your mock. If you also need to support the setter for the Attributes property, then you will need to add that (and possibly a Note member to hold the data).

As with all mocking exercises, this gets complicated when interacting with real things and since PowerShell is really about interacting with real things, it is hard.

Enjoy!

Technorati Tags: , , ,

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5