April 12, 2010

Makers vs. Managers

[[ It's been a while since I posted, and to a small extent that's because I've changed jobs. Now I'm a Development Lead (a manager of software developers), and so the things I tend to spend a lot of time thinking about have changed. This topic is a reflection of that. ]]

I recently read an article about the sharp divide between how different people use their time. It divided people into two general camps: the "maker" and the "manager". People who fall into the former camp have work which requires large blocks of time which they can dedicate to a single concentrated task. Engineers, authors, designers and the like all fall into this camp. On the other hand, people in the "manager" group have work which requires them to constantly shift their focus from one task to another fairly quickly. Program managers are the quintessential profession here in the software industry, but supervisors in nearly any field, people managers, and executives all of this pattern of work.

Unfortunately, makers and managers often need to work closely together, and don't really respect (or possibly even understand) the differences in each other's mode of operation. Managers will disrupt makers by scheduling meetings at whatever time works best to get the meeting scheduled soonest, without regard for leaving two funny 30min chunks on either side of the meeting (which does a lot to kill the maker's productivity). On the other hand, makers will frequently drive managers right up the wall by failing to respond to a requests in a timely manner, or getting buried in one task and letting the schedule on another one slip.

There are two specific practices I've used which work well to smooth things out between these two groups: "Daily/Weekly War Team Meetings" and "Maker Time".

A war team meeting is a routine standing meeting which the decision-makers of the team are required to attend, and which everyone is invited to attend. The agenda for the meeting is decided in the first few minutes of the meeting. Everyone present is welcome to add an item to the agenda, and request a certain amount of time for it (e.g., 5 minutes for a fast time, and up to 15 minutes for a long one). The facilitator will put it up on the whiteboard. Once the agenda is set (i.e., no one has any further items to suggest, or the duration of the meeting is spoken for), the facilitator starts walking through the items on the list. His job is primarily to keep the discussion on topic, capture items for future discussion, and keep things running on schedule. If an issue cannot be resolved within the allotted time, it can either be settled privately between a few individuals who become empowered to settle the issue, or it can be brought back to the next meeting. Once all of the items which interest a person have been discussed, that person is welcome to leave.

This technique works fantastically well when coming up to a release, but is generally a good practice at any time (the closer to release, the more often you generally want to have the meeting). The first positive effect is that it gives everyone on the team a forum and a voice on how decisions are made. They don't get to make the decision, but they can be part of the process. That goes a long way toward improving morale on the team (especially one with really passionate, dedicated people). The second effect is that it tends to consolidate hours of meetings into a much shorter span. The vast majority of meetings take much longer than is required because they don't have a really tight agenda, and because there is no strict timekeeper to keep things on track. The third effect, and most important to makers, is that it makes the time of meetings *PREDICTABLE* and *CONSOLIDATED*. This technique virtually eliminates the need for most other meetings, and therefore gets rid of those odd little chunks of time which are hard for makers to use effectively. Finally, and this is most important to managers, it creates a forum in which blocking issues can be resolved *QUICKLY* and *OFTEN*. If your team does this daily, then the majority of issues which require a meeting can wait until the already-scheduled meeting the next day.

The second technique I've used for this kind of issue is "Maker Time". This is where makers are invited to block their calendars, reject meeting invites, close their doors, put on headphones or whatever else they need to do to put the world on hold for a few contiguous hours each day. On one team I ran, we decided that we would prohibit meetings after 14:00. In other situations, the team would pick a "meeting-free" day of the week (i.e., no meetings at all on Thursdays every week). Whichever way, the leadership of the group made it clear to makers and managers alike that this time was to be set aside for makers to get their jobs done, and no one was to interrupt them (except for clearly defined emergencies). This allows makers to have their dedicated time without completely blocking out managers for long periods of time.

What other examples of makers and managers working together have you seen? What other ways have you dealt with the maker/manager divide?

December 07, 2008

Exceptions

Before Object-Oriented programming (OOP), error conditions were commonly reported via a return code, an OS signal, or even by setting a global variable. One of the most useful notions introduced by OOP is that of an 'exception' because they drastically reduce the mental load of handling error cases.

In the old style of error handling, any time a function was called which could result in an error, the programmer had to remember to check whether an error occurred. If he forgot, the program would probably fail in some mysterious way at some point later down the line. There was no mechanism built into the language to aid the programmer in managing all the possible error conditions. This often meant that error handling was forgotten.

The situation is much improved with Exceptions, primarily because they offer a fool-proof way to ensure that error handling code is invoked (even if it is code for reporting an unhandled exception). This both makes it unnecessary to remember to check for errors, and it increases the cohesion of such code (i.e. it can be gathered into 'catch' blocks instead of mixed in with the logic of the function). Both of these help preserve the Unit Economy of the author and reader of the code.

Unfortunately, despite being such a useful innovation, exceptions are often abused. We've all seen situations where one must catch three different exceptions and do the same thing for each. We've all seen situations where only a single exception is thrown no matter what goes wrong, and it doesn't tell us anything about the problem. Both ends of the spectrum reflect a failure to use exceptions with the end user of the code in mind.

When throwing an exception, one should always keep two questions in mind: "Who is going to catch this?" and "What will they want to do with it?". With this in mind, here are a number of best practices I've seen:

Each library should have a superclass for its exceptions.

Very frequently, users of a library aren't going to be interested in what specific problem occured within the library; all they're going to want to know is that the library either did or didn't do its job. In the latter case, they will want the process of error handling to be as simple as possible. Having all exceptions in the library inherit from the same superclass makes that much easier.

Create a new subclass for each distinct outcome.

Most often, exception subclasses are created for each distinct problem which can arise. This makes a lot of sense to the author, but it usually doesn't match what the user of the code needs. Instead of creating an exception subclass for each problem, create one for each possible solution. This may mean having exceptions to represent: permanent errors, temporary errors, errors in input, etc. Try to consider what possible users of the component will want to do with the exception, not what the problem originally was.

Remember that exceptions can hold data.

In most languages, exceptions are full-fledged classes, and your subclasses can extend them like any other parent class. This means that you can add your own data to them. Whether it is an error code for the specific problem, the name of the resource which was missing, or a localization key for the error message, including specific data in the exception object itself often is an invaluable means for communicating data which would otherwise be inaccessible from the 'catch' block where the exception is handled.

What other tips and tricks would you suggest?