Strategies for Successful Development

Process and technology for small teams building real software

Archive for September, 2008

The No-Spec Spec: Identity

Posted by S4SD (Seth Morris) on 2008/09/24

This piece of the No-Spec Spec defines the what to the Fit document’s why. It is generally owned by the product or program manager and should answer the question "Does this feature/process/change belong in this project?"

It is amazing to me how often the answer to that question is "no" and the company doesn’t discover it until after the feature, process, or change has been implemented.

Again, this should be short. It can be as short as one sentence (such as McConnell’s Vision Statement: "A description of the highest-level objectives of the project") or it could stretch to a page or two, with one section (the "is not" list) potentially growing continuously.

These are the parts you may want to include.

Vision Statement – the key objectives

This is straight from McConnell and the SPSG: What are the objectives of the product and the project? This can include all of the company’s business goals, engineering’s technical goals, the user’s business needs, etc. Keep this to simple statements, bullet lists, etc., and avoid "fluffy" words.

There is all sorts of good advice out there on goal definition. SMART—Specific, Measurable, Attainable, Realistic, and Time-bound—for example, is popular, simple, and useful. I’ll just add/highlight a couple that are often missed.

  • Initiated and maintained by the company or team

    The hope that "our major competitor loses market share each quarter through the new year" is a great wish, but not a practicable goal.

    Initiated by the team means that the ability to make a change (release software, fix bugs, upgrade technology, …) exists within the organization. Outside resources may be necessary; if so, the organization should have the ability to go get those resources.

    Maintained by the team means that the goal has to stay within the organization’s power. This may mean coming into conflict with the company’s history and maturity around follow-through. If only internal causes threaten maintaining the goal then it still meets this criteria (although the chance of success may drop).

  • Has an explicit test for achievement

    If you want to "Improve performance of the system," you need to include a way to test that kind of performance. You don’t have to state how much the project wants to improve performance, unless that is a known goal, but you do need to indicate what kind of measurable performance. Even semi-subjective measurements can be acceptable ("most users in the survey group agree that it feels faster" is a fine goal), but goals that don’t have a way to test are open to misinterpretation.

    I worked on one project to update the base drive image copied onto all new units a customer shipped. We spent weeks tuning the OS install, tweaking the application setup, and researching the data most likely to be useful pre-loaded. Then, being engineers, we went about making the process repeatable: writing scripts to recreate the base image, writing queries to isolate the necessary data, and so forth. The product manager came to me and expressed concern over the time it was taking, especially since he had seen it basically running in the dev pit. I explained and showed him the project plan (which he had seen, but had not discussed in detail) and he asked me a great question: What was our deliverable? I responded that we were giving him a process that produced his drive image reliably and that could accommodate changes to the drive image in days instead of weeks.

    He replied that the image was updated once every 3-4 years and all he needed was a hard drive to stick in a duplicator. The last couple of weeks of the project were useless to him and the repeatability we were building was probably going to be outdated by the next time they tried to do this. Throughout the project, we described the project as "Recreate the source image." Stated as a testable goal from the product manager’s point of view, it should have been "Have a hard drive to duplicate on new boxes." We would have been done weeks earlier.

The Is/Is-Not List – project scope and boundaries

Invariably, someone wants to add something to a project. It’s a normal and often useful instinct: this train is rolling, let’s throw another bag on instead of having to start a whole second train. Some of these will be great ideas; some will be feature creep or attempts to change the product direction.

The Is/Is-Not list works to counter this by listing what is explicitly included in the product and project, by explicitly listing exclusions, and by keeping a hard and clear line between the two.

At the start of the project, you probably know what the project is to some reasonable degree:
– …is the follow-on to version 3.2
– …is minor UI enhancements to almost every screen
– …is the new data layer (formerly code-named "Skippy")
– …is data integration with SQL Server 2008
– …is new charting modules for for the Analytics module

Note that the Is/Is-Not doesn’t have to be as well-structured as the Vision should be. Is/Is-Not should contain the colloquial shorthand your teams use. Feel free to use code names if people like them, or those "cute" names that pop up at every company now and then. If everyone knows what "finally implement Special Sauce" is, giving it another, more detailed name doesn’t do anyone any good at this stage. This isn’t a spec: it’s a list of the areas that are being opened up for change and the kinds of change that are in scope.

At the start, the Is-Not list may be very short, but in practice it is often as long as the Is list.
– …is not implementing the UI redesign hanging in Marketing’s conference room
– …is not a rewrite of the Analytics module flow
– …is not refactoring the GUI engine
– …is not the "Auto-Advise" feature

List the projects, proposals, and pipe dreams that float around often enough and have active champions that you know they might try to shoe-horn into this project1.

As the project proceeds, every time a large change is rejected, add it to the Is-Not list. You don’t want to add every little change or bug, but do list things people feel passionate about—those are the ones that will keep coming back if you don’t do something with them.

In addition to cutting off discussion on revisiting changes, the Is-Not list helps engineers keep their creep and gold-plating closer to scope. But the major value is in giving feature advocates a place to "park" their ideas2. The Is-Not list is more visible and less cluttered than a product backlog, a feature database, or whatever you’re using to plan future work. It ties the proposal to a project and gives the project postmortem/lessons learned a place to see what was excluded and make recommendations to include specific things in the next project.

As features are cut, especially partially- or completely-finished features, definitely add them to the Is-Not list.

Using the Identity document

This doc should be short enough to post on a wall somewhere, but even if it isn’t you should put the project vision everywhere you can: add it to the footer in templates for project docs, put it on the wall, whatever. The Is list shouldn’t be nearly as detailed as a functional spec, and not as detailed as most MRDs, but it is a good start for project planning; development and QA can often start to rough out some plans from it (a good place to start Sliding Window Scheduling).

When the project is closing down, the Is/Is-Not list comes back into the forefront as a check that the project did what it intended to and no more. The Is-Not list also serves to suggest changes that might be important enough to implement soon.

1) If you do decide to make a change and include them, just edit the doc and tell every one. One of the wonderful things about docs is how easy they are to change. Keep a history if you like (highly recommended, actually), but nothing is carved in stone unless you have a very, very specialized plotter.

2) This is similar to the "parking lot" often used in classrooms and at meeting. It has a great effect on people who have a visible indication that their request has been heard and caused action, even if it isn’t being enacted immediately.

Listening to: Steely Dan – A Decade of Steely Dan – Deacon Blues



Posted in Dev Process | Leave a Comment »

Hug a Developer Today

Posted by S4SD (Seth Morris) on 2008/09/23

(I could argue the view that this video trivializes homelessness, but I’m not sure I believe it and this isn’t the blog for that. I will argue the view that this video trivializes the effects of bad project management.)

Watch the video, laugh, and share it with anyone you want to before reading on.

If you don’t want to watch the video (it has sound but does not need it), here are the texts of the signs the developers are holding:

  1. I am in pain
  2. We’re 4 months in to a 5 month schedule and I just received the final requirements yesterday. (And they’ve changed again!)
  3. I spend half my days in meetings about how to get more work done (instead of working)
  4. My boss read in a magazine that developers using "___" programming language are twice as productive. So he bought us a copy and cut our schedule in half.
  5. Every day my boss changes his mind about what we’re building.
  6. (Man) People keep asking me to fix their email, so I have no time to code
    (child sitting next to him) My daddy has no more time for me
  7. Some consultants told my boss they could build our next version in half the time, for half the money. He believed them but now they’ve spent all their budget, used all their time and are still only half finished. Now they’re gone and their code is a disaster. We have to fix it and finish what they started.
  8. (After the credits, in color, small child sitting on park bench) I just finished an intensive 6 week Visual Basic course

Sometimes I’m asked why I want to consult instead of taking a higher-paying W2 job with equity and a stronger career path or why I’m committed to project and process improvement in startups and small teams (which don’t have a budget for that kind of consulting). I’m never sure whether to tell them that it’s because I’ve seen the quality of life improvements for everyone on the team when a project is successful and the process is repeatable and predictable.

Engineering teams want to innovate on ideas, technology, and features, not process, and engineers (and artists, and writers, and managers, and marketers, and ….) want and deserve to have energy and time for their family, their personal and professional growth, and their own projects.

A programmer who sent this to me. I’ve known her for years and have been her team lead or manager at three companies. I know she’s experienced all or most of these and I know it has a real effect on her life (as it has on mine and many of my friends). These are the problems in the life of a programmer.

At the risk of killing the frog1, let’s break these down into some categories:

  • Failed Project management. These are the kinds of thing that developers live with every day but feel powerless over. Sadly, developers are sessile by nature; they will often put up with bad management, hating their job, feeling like they are failing, and feeling powerless over their work environment, for a very long time2. [items 2, 5, 7]
  • People in power who have a poor understanding of what development is3. Programming is invisible. QA is almost as invisible when it finds bugs and more invisible when it doesn’t. Programmers spend their time looking at source code, which is a static representation of an abstract process that will occur invisibly at a microscopic scale, or designs, which are an abstract representation of how poorly source code represents the problem domain. Unfortunately, even former developers fall into the trap of thinking that what isn’t tangible must be fungible. [3, 4]
  • The inherent pain in life of a developer. When you can do something, people expect you to do it. You want to do it. Since developers are able to do what they do anywhere and anytime, it can take over life easily; since developers are the most respected experts on an ubiquitous, increasingly-arcane, and increasingly-powerful technology, they are asked—and expected—to use that knowledge on behalf of their friends, family, and coworkers.
    We start out on this life wanting to play with things and to solve problems; we need training to know how not to do that when it costs us something (like time with our family) that isn’t in our faces while the problem is. [item 6; and arguably item 1]

These aren’t just one class of problem, but they are all real kinds of problems that burn out developers and destroy projects and sink companies. A good manager or lead can solve some of them and ameliorate others, but systemic change to address them all is very difficult. It to easy, and too common, to lump them5 together as "pointy haired bosses and bad planning," but we can’t solve them commingled that way.

That’s why I care about dev process at the leads and line managers level. It’s the fulcrum between failed project manager and poor understanding of development and engineers. It’s also one of the levels that can often remind a developer to step back and re-evaluate personal priorities.

So wait for HR to be looking the other way and go ask a developer if s/he wants a hug. (Don’t just hug them; many developers won’t like it… and some may sue.)

1) "Explaining a joke is like dissecting a frog: you understand it better, but the frog dies in the process." – Mark Twain (attributed, I don’t know if that’s accurate)

2) This is true of all people, really. It’s more visible in developers because of the shorter job cycle (longer times unhappy in shorter job lengths) and the how clear the effects of managers’ decisions are on the developers’ lives (ask a room full of developers how many Thanksgivings or Christmases they’ve been able to be home with their families; then ask then if it was because of things within their control).

3) I worked at a video game company for a while. Independent game developers doing the kind of license work we were (games based on TV shows, movies, etc.—I worked on the game Beethoven’s 2nd, based on the movies with Charles Grodin4) were at the mercy of the license holder, who were media companies and didn’t know what they wanted from a game. When I had been there a few weeks, a fellow developer told me that at the end each project they would give out the "flaming sphincter award" to whoever had been forced to redo the most work through no fault of their own (license holders deciding they wanted to add a bird to the game, that kind of thing).

I was warned that I would never receive this award and I should just let it go because "no amount of programmer pain is visible." My coworker was right; recognizing that helped me get through some tough projects and it helps mediate many difficult situations: no amount of developer pain is visible, even to other developers and certainly not to managers who aren’t around the engineers daily. What seems obvious from the engineering side is not misunderstood or ignored, it is invisible.

If you’re going to try and make that pain visible so management can recognize the problems and work on them, also ask what the developers can’t see and make the engineers aware of that. It’s basic mediation, but it’s especially hard when what each group wants is invisibly obvious to them and simply invisible to the other. Someone outside that chain of command is the best to help.

4) Admitting to having written this game is a big step for me. It is not the thing I’m most proud of. If you’d played it (and no one did), you’d know why. 🙂

5) And other classes, of course. If these two types of problems went away life would be much better, but even taken together they aren’t a silver bullet.

Listening to: Billy Idol – Rebel Yell – Rebel Yell


Posted in Opinion | Leave a Comment »

The No-Spec Spec: Fit

Posted by S4SD (Seth Morris) on 2008/09/20

This is part of the series, The No-Spec Spec.

The Fit document is the easiest to create, the hardest to describe, and the most pervasively important piece in the No-Spec Spec. The project’s Fit tells you why you’re doing the project at all.

This is a job for the highest level authorizing the project, or at least the highest level you can get. On a large initiative this would be the executive sponsor, although a head PM or someone in Sales could do it. On an internal feature or a drill-down piece of a larger project it could be a PM or a member of the development organization.

It should be short. Half a page is just fine; more than a page suggests that someone is going off into inappropriate detail.

What goes in the Fit

Answer these questions:

  • How is this project related to previous projects, strategically?
  • What business or organizational purpose does the project meet?
  • What future plans will this project support?

If this is a large product initiative, the Fit should tie the project to the company’s goals, strategy, and business purpose. If you’re on an internal project, the Fit should describe how the organization’s mission within the company relates to the project. This is the place to reiterate that internal tools are never the product; even for an internal tools project, the Fit should reach all the way to the organization and company’s purpose.

Put another way, Fit is about what is larger than the project and about how the project fits with that. This is an exercise in "chunking up" and seeing the larger environment that contains the project.

A project’s Fit shouldn’t change. If it does, something has fundamentally altered in your whole purpose. Reevaluating the project and its priority becomes the #1 job.

Using the Fit

The Fit is the ultimate criteria: it is the background which allows the project and product to exist. Pin it up somewhere. Any time someone is off in the weeds, walk them over to the printout and ask them if what they’re doing is described on that paper.

It’s amazing how often looking at the reason for a project reminds people to back off, simplify, and propose features instead of trying to sneak them in.

Example Verbiage

None of these are complete Fit statements, but they give a good idea of the kinds of things that wind up in the Fit document.

A rev of enterprise product:

This product update will meet specific demands from 3 of our high-profile enterprise clients:
     <bullet list of demands and clients>
Meeting these on-schedule will raise our visibility in those companies and help the sales team reach new departments in the companies.
Increasing sales within these companies will raise revenue and increase the value of these clients as references.

A shrink-wrap product rev:

This project will get the product to back-of-the-box feature parity with competitor A, version N.
     <bullet list of feature checklist items>
Other aspects of the project should be listed as well, but not intermingled.

An internal feature from engineering:

This feature will reduce development time and number of bugs on all projects that use this module; it will increase QA and Operation’s visibility into the behavior of the system. Specifically, it will (a) reduce the maintenance time on future products by reducing ramp-up time when a developer has to use this module, (b) increase the granularity of logging, and (c) resolve several long-standing bugs that have hampered new feature implementation.
<List the bugs and what resolving them will do for the team overall>

A drill-down piece of a larger project:

This piece will enable features A and B by servicing requests from several features/modules, returning data they need to do synchronous processing. It will maintain state for several business objects and abstract all data storage details of these objects from its clients.
<List the client modules/objects and the business objects this module owns>


As you can see, the Fit piece is about something that includes or contains the project. It describes how the project serves the purpose of something larger than itself; it says why the project exists. Absolutely everything on the project should tie back to the Fit.

Listening to: Pink Floyd – The Piper at the Gates of Dawn – Interstellar Overdrive


Posted in Dev Process | Leave a Comment »

The No-Spec Spec

Posted by S4SD (Seth Morris) on 2008/09/18

Articles in this series:
     The No-Spec Spec: Overview
     The No-Spec Spec: Fit
     The No-Spec Spec: Identity
     The No-Spec Spec: Purpose
     The No-Spec Spec: Assumptions
     The No-Spec Spec: Environment
     The No-Spec Spec: Capability
     The No-Spec Spec: Behavior

Specifying without a spec

There are a lot of reasons why teams don’t get—or write—good specs: fast-changing product definitions, overloaded product managers, no time in the schedule for technical specifications, lack of training on specifying, communication barriers preventing getting information from other departments, etc. Some groups even eschew specs as inappropriate to agile development (although that actually means they have a too-narrow definition of both "agile" and "specification").

Over the course of training teams to create specifications, I’ve come to a humbling realization: some teams/companies just shouldn’t be writing specs yet. In the CMM parlance, they’re maturity level 0 teams/companies and don’t have the ability to produce an artifact as formal as a spec.

Other teams could, but a senior manager or respected developer whose identity is bound up in being "seat of the pants" or in "cowboy development" keeps the culture from supporting the people trying to implement some minimal process. This is often the case in companies very tied to the "cult of the programmer."

So here’s an alternate approach, based on multiple small artifacts. The main goals are:

  • Severable: The process can be implemented piecemeal, although some pieces are better with others finished as a prerequisite
  • Practicable: Each piece is useful on its own
  • Low-cost: No piece requires extensive time to produce
  • Pervasive: Every discipline, from executive sponsorship down, can be involved under their own initiative
  • Guerrilla-ready: No piece requires significant input from multiple disciplines
  • Produces living documents: Each stage artifact is open to revision and the consequences of that revision are clearly and immediately visible
  • Recursive: the process can be applied to whole projects and recursively re-applied to pieces of the project down to code-level design.
  • Supports a sliding-window:  You only have to specify the pieces you are working on next and can increase the level of detail as information becomes available

The No-Spec Spec is designed around Robert Diltz adaptation of Gregory Bateson’s notion of logical levels. Project artifacts are sorted into logical levels with an eye towards what sets the environment for what. If something fundamental changes, every artifact and decision below it needs to be re-evaluated. Changes don’t often propagate the other way, though, unless the change is due to some out-of-band change that should affect a higher level.

Here are the parts of the No-Spec Spec:

Level Describes…
Fit How the product/project fits with the company’s business

This is not usually included in specs. Making this explicit solves many problems that arise over trade-offs, the importance of functionality, the flexibility of schedules, etc.

Identity What the product is in simple language. This forms the core mission of  the project.

This may be included in an MRD, but companies that have trouble producing specs rarely produce MRDs. Those that do produce good MRDs rarely carry their value all the way down to implementation.

Purpose The business need/problem the product/project addresses. The value proposition for the project.

This is the user-centered version of Identity (and, to a lesser extent, Fit). This is the place to start talking about use cases and other customer-centric design methodologies that have become standard.

Assumptions Assumptions that underlie the project. If any assumptions are invalidated, everything in the project needs to be reexamined.

These should include assumptions about the business environment, competitors, technology, regulatory environment, team and company composition, other projects in the company, and anything else that would require re-examining the project from top to bottom.

There is a close relationship between assumptions and risks, but risks are those things you prepare for and monitor for change. Assumptions are generally completely out of your control and are black or white: they don’t have a risk level, although you may be able to estimate a current risk level that an assumption will be invalidated.

Environment What is the environment for the product? Is this for an office? For home? A kiosk in a bar? A PDA? A server product in a Fortune 100 IT room?

What is the hardware and software it is expected to run on (note that this is not the same as hardware requirements, but expected environment)?

What is the user’s experience before using the software? What are they going to do after?

Capability The breadth of the project. This includes elements of the product roadmap, the range of applicability (versions, add-ons, integration, etc.)

This is where canceled featured go to resurrect them in a subsequent version. For those of you using SCRUM1, this is not the same as a product backlog. This is for product planning outside the SCRUM process.

1 The project religion of the month when this was written

Behavior The main areas of functionality and what they do. This is the place to go into user stories/use cases.

Keep this to a level of detail appropriate to the rest of the artifacts. An Identity document describing a 20-developer, 6-month project as a whole should not be coupled with a Behavior document listing every error screen and log file format. Save that for another set of documents; otherwise, the Behavior artifacts are likely to hold up the rest of the work.

In general, change flows downhill and the rate of change increases at each lower level. A change in Fit means the entire project needs to be reexamined. A change in Environment means the capability is likely to change, which will in turn affect Behavior, but an environmental change is unlikely to affect Purpose. If it does, then the project Identity most likely changed without anyone noticing.

If any level is changing faster than the level above it, the project has a serious problem and is likely to fail. If the Assumptions don’t stabilize, you won’t ever get clear Behavior; if the Purpose keeps changing, then the bulk of the project is premature. Track how often these docs rev and note whether they are making major revisions and whether they are making changes in response to another change or if they are spinning their wheels.

Despite the fact that change flows (and grows) downhill, you don’t need—or want—to prepare these in order. Most of these documents capture and explicate existing information. If the executive sponsor doesn’t have time to write a Fit statement, you can and should still go ahead and define your Assumptions, Purpose, Behavior, etc. You will only need to change the other documents if the Fit surprises you—and you should reexamine what you’ve prepared anytime you are surprised by something more fundamental.

I’ll go into each of these levels and give examples in later postings. Let me know what you think.

Listening to: Blood, Sweat & Tears – Greatest Hits – You’ve Made Me So Very Happy


Posted in Dev Process | Leave a Comment »

Development “Red Lights”

Posted by S4SD (Seth Morris) on 2008/09/17

Development Red Lights are those things which should stop a programmer in his or her tracks for a second—and maybe a third—look. When you see one, pull another developer over and prove that it’s the right thing to do.

None are wrong and all have uses. They aren’t in the "never do this" category. They are tricks, odd work-around, obscure language and platform features, or even sometimes-correct decisions that won’t break anything, but have some undesirable implication. Many are nightmares waiting to happen to some poor maintenance engineer.

I encourage you to make your own list for your team. Post it. Carry a copy into code reviews and ask the developer to explain why anything on the list is still in the code. There are often good reasons, but at least put a comment on every one.

The list doesn’t need to be long. And ideally you’ll never see anyone try to use something on the list. But it’s well worth having it around.

Here are some of the items that start on my list. After these I add domain- and project-specific items. Include red lights specific to technologies you’re using and any specific to the project’s existing code. This isn’t the place for a list of code suggestions or gotchas; keep it to unreasonable-but-happens code and design that might be necessary sometimes.

If you’re a lead, it’s important that you create your own list and customizing it to your team. I’ve kept my samples short.


  • Classes with "Controller," "Manager," or similar suffixes

These classes often indicate that procedural code has been shoehorned into an object design without any refactoring. They can be appropriate, but check each one and make sure it isn’t actually just wrapping procedural design.

If you want procedural code, go ahead and use it, but make it clear. Don’t try to disguise it as objects.

  • Loose coupling

If you have loosely coupled events (best identified as events where there is no visible relationship between the caller and the callee until run-time), stop and demonstrate that you will use the coupling in a way that makes sense. It’s easy to loosely couple events "on principle" and lose the ability to trace the logic forward. Loose coupling is often appropriate, but it comes at a high cost in maintainability as a system evolves. It is also easier to put loose coupling in than to take it out. Err on the side of the simplest and most easily corrected.


  • Non-public Inheritance

Virtual inheritance is almost always undesirable. It either indicates an inadvertent diamond inheritance or a has-a relationship (composition) modeled as an is-a (inheritance). Consider composition or creating an interface.

Private inheritance means the class is inheriting implementation instead of interface. This is usually undesirable. Again, consider whether composition is a better alternative.

Protected inheritance is just plain wrong. It makes peoples’ heads hurt. Don’t do it.

  • Uncommon Operators

Avoid strange operators and casts, particularly the pointer-to-member operators, >* and .*. These raise the bar for maintenance considerably and can generally be designed-away.

Also be suspicious of overloading the function call operator, operator(). These often indicate gold-plating or overdesign.

In general, operator overloading (other than assignment and maybe comparison) should be limited to classes that behave like data types rather than functional classes. As a rubric, if you have operators as well as functional members (methods) re-evaluate the design and make sure you really mean it.

  • Implicit Casts

Be very careful creating implicit casts. Any c’tor with one parameter creates an implicit cast the compiler will call to coerce a type; this can lead to unexpected behavior that hides a code mistake. Treat c’tors with the same respect you would a cast and consider an explicit cast instead, both in the interface and in the usage.

If a class creates a implicit cast, consider using an OutputDebugString() in debug mode to track it. You can’t search for implicit casting, that’s why it’s implicit 🙂

Not every one-argument c’tor is a warning sign. Watch for conversions from a type that is conceptually similar to the class implementing the c’tor. You want to flag the Red Light when the c’tor may catch a developer using a different class in place of this one.

  • Empty statement blocks

Check that these aren’t a too-clever way to combine logic into a loop test.

Similarly, check that any artificial scope has a reason to exist and is clearly documented.


I don’t yet have a good starter list for C#, VB.NET, or the .NET framework.

Any suggestions?

I have a few items I use for JavaScript code, but they’re pretty obscure. I don’t know if I’ll post them.

Listening to: The Bonhoffs – Manhattan Sleeps – Shiraz


Posted in Dev Leads | 1 Comment »

Dev Leads pt 1: What is a Lead?

Posted by S4SD (Seth Morris) on 2008/09/17

This is part one in a series on the role and practice of the Technical Lead, Lead Engineer, or whatever your company calls them.

What is a lead?

The software industry doesn’t have any standardization of titles, responsibility, team structure, or levels of experience and skill; the industry as a whole is certainly too young and too dynamic for all that. But at many— maybe most— companies, teams have technical people who perform both technical and non-technical leadership. Many companies mark these people out as development leads; at others they may be called technical managers, managers of technology, or even some untitled subset of senior engineers.

These people are in roles with duties they have not been trained for; they are often neither appreciated nor compensated for the role; and they often have no explicit authority to perform many of the day-to-day tasks required of them. The dev lead’s job usually falls to them for non-technical reasons: the respect of their peers, their ability to communicate and mediate within the team, and their appreciation of the entire project context and business needs, as opposed to just technical skill.

At many companies, the people in lead roles are never told exactly what is expected of them as the lead, where it can go as a career within the company, or how their performance as a lead will be evaluated. And very, very few companies provide any real training in being a lead.

To make matters worse, most leads are also expected to continue owning crucial sections of code, but the work of the lead requires an interrupt-driven and meeting-heavy day showing a level of confidence that is in direct opposition to the requirements of deep coding: uninterrupted time, introspection, and repeated failure. Many leads work much of the regular workday as a lead, doing procedural things, answering questions, and firefighting; then they work into the evening or night writing their code. 


Working Styles




Work day



Attention direction



Focus on

many things

one thing at a time

Primary context

the project

one piece of the project


big picture



external (see/hear evidence that the project is running well)

internal (individual work known to be good by internal judgement)

Temporal structure

perceives time from outside for comparison and planning

varies, but generally contains a strong component of immersion in the moment of work (c.f. "Flow")

Motivation direction

often identifying risk or problems and motivating away from them

often motivating towards a planned course of action (function contract, workflow, test plan, etc.)

Responsible for



If leads are to get the support they require—if you, as a lead, are to get the support you need—we need to identify what a lead is, what a lead does, and why almost every company comes to a similar recognition of a special technical-cum-leadership role but we as an industry still fail to articulate and support it.

Who is a lead?

The role of development lead isn’t always spelled out to the team. Who is a lead? At different companies, different job titles may have the de facto lead role. Sometimes, several titles at the same company are leads, depending on the team or individuals. Sometimes, the lead isn’t recognized by any title or even acknowledged by management. Some leads are self-selected and lead by personal authority.

Commonly, development leads can be found with these titles:

· Dev Lead

· Technical Lead

· Technical Manager

· Senior Software Engineer (although not all Sr Engineers act as leads, of course)

· Manager of Technology

A lead is recognized by the role s/he performs, however poorly that role may be articulated; the title is secondary. As an industry, software is averse to titles, established levels of skill, defined strata of experience, or other standardizations common in some industries.

What isn’t a lead?

A lead isn’t a manager. Some managers are also leads, and some leads are acting or de facto managers, but the role of being a lead is about the project and the technology, not managing the people.

People go to a manager as a liaison with the company: other departments ask to know who is assigned to do what, team members get their priorities and deadlines, or team members ask use the manager as their primary interface to company policies and HR. The manager role operates in a framework of company needs and company policy. Who has sick time available? How is the new hire doing in his or her first 90 days? The scope of the management role includes the project, but is focused more generally on the company and its rules. Managers may insulate team members from too-rapid change outside the team or from maneuvering and posturing that would just distract the team, but the manager role doesn’t have to have to have anything to do with the details of the project.

The Role(s) of the Lead

Leads, on the other hand, are the interface to the project. The lead represents the team to people who don’t interact with the project daily—and the lead interprets and translates the rest of the company back to the team. On a technical front, the lead maintains the state of the project: what is complete, what is at risk, what piece is necessary for what other piece and provides guidance on the implementation as a whole, maintaining consistency, training less-experienced developers, and keeping the broad view of what-impacts-what so other developers can focus on individual pieces.

(Click for full-size image)

Leads perform many roles within a team: designer, communicator, negotiator, mentor, taskmaster, and more. Not every lead has the same responsibilities and every company has a slightly different mix of tasks a lead spends time on. Often these tasks have conflicting needs: uninterrupted time versus interrupt-driven behavior, alone versus interactive, short-term versus long-term. Balancing these tasks is the art of being a good lead, and it varies from company to company and from project to project.

Why does the role vary so much? Because a lead fills in gaps that the organization has institutionalized.

Larger view, split attention

The common themes of the lead’s roles are larger view and split attention. The lead must take a larger view than just one section of the code, or even just the code, and the lead’s attention is split between the project and its goals, the team members and their activities, the lead’s own development, and the business situation and business purpose of the project.

The lead has to communicate the business purpose of the project to the developers and moderate between the project’s business needs and the team’s technical desires. The lead also balances the technical activities and needs of individual team members.

It is the lead’s job to bring this larger view and understanding of the whole situation—technical and non-technical—to technical discussions with the team and planning and status discussions with management.

Technical decisions

The most obvious responsibility of a dev lead—and the one that usually gets mentioned first by their managers—is to mediate and lead technical decisions. This requires knowing the technology and its capabilities, knowing the abilities and experience of the team members, and knowing the requirements and specifications of the product. It also requires an understanding of any sales and marketing limitations on technology, assessing schedule impact, predicting risk, and navigating interpersonal politics on the team.

In addition, the lead must often make quick, confident decisions an present them convincingly to the team.

Owns shipping

On most teams, the lead is the one looked to by management to see that the team’s piece ship. This involves knowing what’s working, what isn’t, and what’s risky. The lead needs to raise problems with management quickly, predict technical problems before they happen, and keep the team focused on shipping the product.

Managing up

The dev lead is the voice of the team to management on anything technical. The lead is responsible for bringing technical problems, hardware, software, or facilities needs, ideas for new approaches, or anything else requiring the company’s assistance to management. Even if the lead is not also to titular manager, personnel issues will often become apparent to the lead first or manifest as technical issues; the lead is often the only way management is informed about what’s actually going on with the team.

It is the job of the lead to "manage up" for the team: to reduce the amount of overhead management requires, to filter management’s activities to only those relevant to the team, and to convince management to listen to the team’s concerns and needs.

Interpret management

As the flip side of being the voice of the team, the lead interprets management’s directives and business needs into technical needs. This includes developing development plans, validating technical specifications, and making technical decisions. This puts the lead in a position of influencing how the team reacts to management’s decisions and communications.

Oversee design

The lead oversees design. This can lead to a tension with team members depending on how much autonomy the team members have to do their own design. It can also lead to conflict with team members over the design decisions. The lead needs strong technical decision-making skills, but also needs good skills to communicate the reasons for decisions and the requirements decisions are made on, as well as good communication, rapport, and influencing skills.

As a corollary to this, the lead determines the criteria used to make technical decisions. Internal conflict can be reduced by making these criteria explicit at the outset. (But that’s the subject of another post.)

Mentor juniors

The lead is the person junior engineers look to for technical growth, evaluation, and inspiration. The lead is in a position to shape their expectations, their work ethic, their interaction with their peers and with management, and their career path.

How the lead interacts with juniors can be especially important when there are other senior, non-lead developers who do or do not want to mentor juniors.

Model engineer

The lead is the model engineer for the team. He or she is the example of what is expected. The lead’s code and design must be of acceptable quality, the lead’s communication must be acceptably clear and helpful, and the lead’s focus sets the tone for the team and tells them what is important. Leads are in between developers and managers. Even if they are also managers, when they are acting as a lead they are a developer as well. Leads must be familiar with the complete design and much of the code the teams produces.

As a developer, different leads have different levels of code-producing involvement. Some leads take critical pieces of code and keep them to themselves; others refuse to take code on the critical path. This usually depends on the amount of time and attention other tasks are requiring of the lead.

The lead’s code has to be of acceptable quality, but it doesn’t have to be the best on the team. There may be brilliant developers who aren’t leads for many reasons. As the holder of the project state, the lead needs to acknowledge that someone else’s code is a better model for junior developers to learn from.

Implement technical process

The lead implements the technical, team-facing portion of the development process. The lead sets the pace, tone, and structure for code reviews, design walk-throughs, and technical documentation. How the process is reified comes from the lead.

Listening to: Dusty Springfield – Dusty in Memphis – The Windmills of Your Mind


Posted in Dev Leads | Leave a Comment »

Timeline Postmortems

Posted by S4SD (Seth Morris) on 2008/09/12

I wrote this article in 2004 for, the website of STQE (Software Testing and Quality Engineering) magazine*. It was reprinted in the April, 2005 issue of Projects & Profits magazine.

* The magazine is now called Better Software.

Timeline Postmortems

by Seth Morris


We want to use project postmortems to improve our software process, but few teams do them. And fewer teams reliably learn from them. You can introduce postmortems to your team easily with timeline postmortem process. If you are already doing postmortems, a timeline-based approach may improve your results.

This process:

· Takes little time (a few hours or less of team time)
· Has a high degree of engineer acceptance
· Provides immediate practicable feedback into your development process
· Increases team cohesion and rapport
· Reduces finger-pointing

Postmortem Goals and Problems

You’ve got to accentuate the positive
Eliminate the negative
Latch on to the affirmative
Don’t mess with Mister In-Between

— lyrics by Johnny Mercer

Inevitably, on projects, something goes wrong. Ideally, something else goes right. On the next project, you want to prevent the one from reoccurring and reproduce the other. This is the goal of postmortems.

However, most teams don’t do postmortems. And the teams that do don’t always get value from them. Frequently, postmortems turn into "the blame game" or whitewash mistakes. A bad postmortem can create dissension and institutionalize failures.

A good postmortem builds team rapport, rewards project successes, and improves the next project after it. Good postmortems are rare, but they don’t have to be. Whether you’re introducing postmortems to a team that doesn’t use them, rescuing a failed postmortem process, or improving a successful one, a few simple steps will help.

The complete timeline postmortem process takes 3-4 hours of team time plus a little preparation for the moderator. The process produces results that are immediately applicable and focuses on low-hanging fruit. With it, you introduce incremental change that the team can adapt to rather than reinvent the entire development process.

In keeping with this philosophy, the process elements can be separated and introduced one at a time.

Process Outline

The basic steps of a timeline postmortem are:

1. Create the project timeline. This is a record of the “official truth” of what happened when, at a granularity that allows team members to see the entire project as a whole.

2. Walk through the timeline, identifying successes, failures, and "themes" of the project.

3. Group successes, failures, and themes by project phase. You will focus on process change one phase at a time. Don’t redesign the delivery phase if you haven’t made it past design; it’s just spinning wheels and it’s unlikely to be successful.

4. Adjust your software process to address the failures and recreate the successes.

5. Only implement process changes that affect the immediate future. Keep constant, public feedback on new process to inform the next postmortem. This also assures team members that their concerns will be heard and allows them to “disagree and commit” for the time being.

6. Revisit the postmortem when your subsequent projects enter a new phase. Finalize your notes on the ending phase and reiterate the process changes, if any, in the new phase.

Process Elements

If you’re mixing and matching, the key elements of the process are:

  1. Separate "what happened" from interpretation, and stay away from fuzzy "why" questions.

Creating a timeline of project events allows the team to talk about events and process without pointing fingers. Getting agreement on the timeline first, without any analysis, keeps the later discussions from devolving into "did not/did too" exchanges.

In addition, the timeline becomes the "official truth" for the team. Shared history increases "team-lyness." Just the act of creating the timeline can resolve esprit issues after a difficult project.

  1. Give equal attention to each part of the project. Postmortems can easily focus on the pain of the final phases of a project because that’s the most fresh in the team’s minds. A good timeline will remind the team of successes and failures from the beginning of the project, which are the most important to address while the next project is beginning.
  2. You want to do your postmortem right after the project is over, but you can use the timeline process before that if a project is stalled or failing. Waiting until another project is beginning gives some useful perspective.

On failing projects, creating a timeline sets up the recommitment meeting. It implies that any issues are part of the past and focuses attention on the results rather than the difficulties.

  1. Always have an impartial moderator/facilitator. This moderator only asks questions and writes down answers the team agrees on. The moderator should not be contributing opinions.

If your company doesn’t have someone impartial, hire an outsider.

If you have to fake impartiality, create a clear distinction between providing facilitating and providing your opinion. One good approach is to use standing and sitting: when standing, only ask for information and repeat what the team says. Sit down and wait a second before giving your opinions. Have someone ready to interrupt if you step out of role.

  1. Describe events and proposed process in terms of behavior, not intent. You can use the TOTE for this
          What is the trigger? (Initial Test)
          Who does what? (What is the Operation)
          What causes it to end? (Completion Test)
          What happens next? (After completion, Exit to where?)
  2. Address technical decision making as well as traditional development process. Be sure to discuss technical decisions in terms of criteria and results. This is an area to watch for finger-pointing and dogmatism.
          You can address dogmatism (and, to a degree, finger-pointing) by using clear project and development criteria. If you have clear criteria, put them on the wall during the postmortem. Actually, put them on the wall at the start of the project and just leave them there. Shared criteria makes for cohesive teams.

The Process

1. Preparation

To implement the process, you need some preparation:

· One impartial moderator

Too many postmortems are run by project managers or executive sponsors. The team members are unlikely to be honest about successes and failure in this environment. When the facilitator is not a manager, s/he may have a preferred software process methodology to push (dogmatism or “technical/process religion”), skewing the postmortem results.

If possible, get someone outside of the group—or even outside of the company—to lead the postmortem. The facilitator needs a basic understanding of development process, but doesn’t have to be highly technical or intimately familiar with the project. In fact, a degree of unfamiliarity will help.

»The moderator has final ownership of all postmortem deliverables, including the preparation.

· A (mostly) blank project timeline

Begin with some basic research.
      When was the project begun?
      When were major visible milestones, like first QA drop and final ship?
      Were there any personnel or company changes during the project?
      Major holidays?

» Put all of these on the project timeline to begin.

· Project phases

Use project phases to contextualize successes and failures. During implementation, focus on the current and upcoming phases.

Phase definitions will depend on your team’s development methodology.
      A typical waterfall project may have spec, design, development, and testing phases.
      An iterative project may have several iterations, with spec, design, and test in each one.
      Prefer to define phases that are generally present in your projects, rather than phases that will never occur again, but be willing to violate that rubric as needed. Be descriptive, not prescriptive.
      Phases may overlap or repeat. The QA group may be in one phase out of sync with development and it is likely that Product Management will have phases that differ from everyone else. Use phases that are useful to the groups they affect. This is the time for empirical, not theoretical, analysis.

During the meetings, the team may adjust the definition and dates for the phases. This is normal.
      The team is always right about this. Phases are a tool to help people group activities together; what the team considers related or grouped is related or group.

» Put a pass at the phases on the project timeline.

· Gathering the whole team

Get as much of the team as possible present for the first two meetings. This includes at least development, QA, and product management, as well as any support, release, documentation, or other groups as may be appropriate.

Managers and executives are useful in the first meetings, but be prepared to send them out of the room if people seem reluctant to talk around them.
      If you have to send a manager out of the room, do it openly in front of the team. Tell the manager that his or her presence is impeding communication. The team already knows this; acknowledging it increases rapport and openness. It may also be a useful lesson for the manager.
      If a manager refuses to leave, stop the postmortem. It will not be successful and any good ideas that come out of it, but do not come from the manager, are unlikely to be effected.

2. Timeline creation

» 60-75 minutes. Whole team.

The meeting goal is to establish the project timeline.

1. Put the timeline on a whiteboard where everyone can see. Leave plenty of room for adding events and activities.

2. Establish the major dates for key events: specs begun, estimates delivered first code fork, first delivery to QA, project completion (if possible), etc.

3. Get buy-in on the project phases.

4. Add project activities and events. Use language like, "During the design phase, what else happened?" Mark what features were affected when.

5. For each event or activity, ask "does everyone agree that this happened?" Watch the team when you say this and look for nods or head shakes. Agreement is more important than precision.

Keep this to an hour. An hour should be sufficient to get a level of detail appropriate to the length of the project.

Do not include any analysis in this meeting. No one should say "why" anything happened, or state any consequences of anything. When someone starts (and they will), interrupt them.

3. Project analysis

» 60-90 minutes, whole team.

You can run the analysis meeting right after the timeline meeting, but put at least a 10 minute break in between and make everyone stand up and leave the room. Get yourself a drink of water.

Lead the team through the project timeline from start to finish, phase by phase. Identify key themes, successes, and failures on this project. Start at the beginning of the project if you can; don’t let the team use up all the time on the phase most recent in memory.

Successes? Failures? Themes? Let’s define some terms:


A project success is something that reduced risk or improved the project’s result.


Failures increased risk or reduced the project’s success. Definitely include failures that are repeated from project to project. Those are the best to address.

Some teams don’t like to use the word "failure." This isn’t the time to use words like "challenge" or "opportunity." If you need to use a different word, make up something, like "lamppost."


Themes are neither successes nor failures. Instead, they provide context for successes and failures that can’t be considered part of the timeline. Often, a success on one project would be a failure on a project with different themes.

» If the half the team thinks something was a success and the other half thinks it was a failure, then it’s probably a theme.

Key points to the analysis meeting:

· Work from the timeline.

· Ask questions by phase, but be prepared for people to offer comments on other phases.

· Keep separate lists for Successes, Failures, and Themes. I use three flip charts taped next to the whiteboard, preferably on different walls.
      » If you use flip charts and whiteboards together, use whiteboard markers for both.

· Use behavioral questions only. "In this phase, what worked or didn’t work?" "What was different from previous projects?" Do not ask "why" questions.

· Successes, Failures, and Themes should all be described in terms of "When X, then Y, which caused Z." Ask for any parts you don’t get. If a team members offers "We didn’t follow the bug process," ask when and whether that was a Success or a Failure.

· Repeat every Success, Failure, and Theme before writing it down. Get agreement from the team before listing the item.

· Write down the exact words you repeated to get agreement. Do not "translate." Analysis, synthesis, and clean-up will happen later.

· Keep the meeting moving. Try to limit it to an hour.
» If you can’t get through in a reasonable amount of time, stop and either reconvene another day or finish the process on the phases you did complete. If that is useful, either convene another meeting on the rest of the project or abandon that and start with the next project, depending on scheduling and availability.

· Watch who doesn’t participate. Ask them directly if they have any comments. Language like "What worked or didn’t work for you?" is often effective. Be willing to wait in relaxed silence for an answer.
» Other good questions: 
      What did you do that wasn’t part of the official process? 
      What parts of the process did you skip or try to skip?
      What was a process step you trusted and didn’t have to worry about at all?
» Note that these questions all presuppose that there is an answer.

After the analysis meeting, deliver a document containing the timeline and the project analysis. Organize Successes, Failures, and Themes into project phases. Give the team a few days to digest it.
      This is the time for synthesis. Group Successes, Failures, and Themes into related sets and call out any that crossed many or all phases.
      Expect a small amount of feedback. This is not the stage where most team members will put in solo time.

4. Process design

» 60-90 minutes, all leads and manager plus all interested team members.

Get the leads and managers as well as interested individuals. This is not the meeting to force people who don’t want to participate.
      » Do try to get someone from every discipline.

1. Group Successes and Failures into any obvious categories: intra-team communication, scheduling, making technical decisions, etc.

2. For each category or item, identify the project phase to address it. Identify existing processes which affect it.

3. For each phase, develop new process or process changes to address the highest-value items.

When designing development process, keep in mind:

A process requires the TOTE:
· A cue to start
· An operation or behavior
· An end point
· Process(es) to switch to

» Write all of these down.
      Try to include a way to measure progress and any events that would call a recommitment or change meeting.

You may not be able to address every success or failure. Focus on phases and changes that will be immediately useful on current projects.

» Process will change
» No team follows every process it expects to
» No team follows every process the same way every time
Since you know this, don’t design in too much detail and let evolution happen. Evolution means something was getting in the way of work. Don’t fight it.

If the team has a split about a process, just pick one side. Let the team try it one way and change if needed. Be willing to be wrong and be sure the team understands that.

5. Implementation

When the next project starts–if it hasn’t already–you’re ready to implement new process.

Only implement pieces that affect the project phase you’re on.
      For example, don’t spend time re-tooling your release process before the specs are written.
      When each project phase ends, review the previous project’s postmortem and implement process for the new phase.

Write down new processes and post them in a public place.
      » People will be confused and make mistakes. Always refer them to a written description of the process.

If something doesn’t work, acknowledge it and move on. Make a change if you have to, but if you can muddle through with a broken process it’s best to save the redesign for the next postmortem.

» Always remember that the process is not the product. You have software to ship.

No matter how successful your current project is, I hope your next one is even better.

And may you never mess with Mister In-Between.

Listening to: The Players – Pippin (Original Cast Album) – Finale -The Player


Posted in Dev Process | Leave a Comment »

Custom searches in your toolbar. Or, Desktop tools mashup, too.

Posted by S4SD (Seth Morris) on 2008/09/10

When I saw Windows Live Search Macros only a few hours after finishing a writeup for a client on the new search provider features in IE8b2, I was pretty excited.

If you don’t know Live Search Macros (I certainly didn’t), they are pretty simple. You go to and build a search string to modify search results. You can use all the operators available on Windows Live, such as filetype, hasfeed, contains, language, site, and the all-important prefer. If you save the results, you can go back to a page created for you to run a Windows Live search with those modifiers already added.

For example, presents a Windows Live search screen that restricts results to several popular science fiction sites. And on each of these pages you get the little orange arrow that indicates you can add a new search provider.

This is all very nice, but you don’t need that to make a Windows Live Search Macro to get a custom search provider that does this, and you can use any search engine (including site-specific engines like Amazon or IMDB) and any syntax that engine supports.

Let’s say I often search for information on a .NET programming concept or term. I know searching on “select” alone won’t give me very useful results, even if I use a categorizing search engine. I need to give the engine some more context, so I add terms that aren’t specific to my query, but instead are general to my query domain. This is exactly what we shouldn’t have to do.

I probably use a search like .NET C# (WinForms or LINQ) +select 

This is the same problem Windows Live Search Macros were created to solve, but I don’t want to go to a web page every time I do it (and maintain a list of these pages) and I also don’t want to be restricted to Windows Live Search.

So let’s solve the problem on the desktop using IE7 (or IE8). Click arrow by the search box and select Find More Providers…. You will be taken to this page, with a list of companies that have convinced Microsoft to surface them and a box to create your own provider. What isn’t obvious is that the search string you use to create a provider doesn’t have to be minimal: any legal search string for your search engine of choice will work, as long as the MS website can find the word TEST in it.

So I go to a search engine, let’s say, and enter the domain-specifying query I use often enough to want to automate. automate. I get this url:

By putting that into box 3 of the form naming it “General C# Search” I have a search provider on my drop-down that does what I want.

It isn’t any better than the Windows Live Search Macros, other than letting me choose my search engine and it let me get into the details a little bit and feel like all the moving parts were under my control. And sometimes, that’s enough.


Listening to: Laurie Anderson – Strange Angels – The Day The Devil


Posted in Tips, Tools, and Tricks | Leave a Comment »

Article Summary

Posted by S4SD (Seth Morris) on 2008/09/01

Major series and articles I find most useful to hand to people. This is not a list of all posts; use the Summary View or the Archives for that.

Miscellaneous process articles:

The No-Spec Spec:

The Dev Leads series, including planned articles:

  • Dev Leads pt 1- What is a Lead?
  • Dev Leads pt 2: Becoming a Lead
    Do you really want to be a lead?
    Routes to a lead position. Stepping into a lead role, either as a recognized or a de facto lead. New lead, old team. Transitioning from developer to lead. Leading from the outside.
  • Dev leads, pt 3: Forming teams
    From a group to a team. Establishing roles. Creating unity of purpose. New team members. Measuring team-ness. Giving feedback. Taking feedback.
  • Dev leads, pt 4: Existing teams
    Changing roles: from member to lead. Coming in from outside. Identifying existing culture Knowing when to make changes. Articulating change. Special concern: development responsibility as a newly-promoted lead.
  • Dev leads, pt 5: Leading technology
    Criteria. Design. Feasibility. Guidance.
  • Dev leads, pt 6a: Leading development – process items
    Technical specs. Requirement changes.
  • Dev leads, pt 6b: Leading development – Planning
    Estimates/costing. Scheduling. Research phases. When plans are vague.
  • Dev leads, pt 6c: Leading development – Tracking status
    Reporting changes. Interrelations. Checking in. Knowing what’s in the code.
  • Dev leads, pt 6d: Leading development – Shipping
    Integration. The QA/Dev relationship. Quality code.
  • Dev leads, pt 6e: Leading development – The Team
    Establishing team culture. Mentoring. Morale.
  • Dev leads, pt 7: Implementing process
    Code reviews/inspections. Postmortem/PLL. Documenting implementation. Dealing with other leads. Interacting with non-developers.
  • Dev leads, pt 8: Meetings
  • Dev leads, pt 9: Managing risk
  • Dev leads, pt 10: Managing your career
  • Dev leads, appendix: Special topics
    Position and person. Sending and seeking information. Being wrong. "I" and "We." Serving the company. Serving the team. Serving yourself.
  • Dev leads, appendix: Documents
    Templates, examples, and tools for leads.
  • Dev leads, appendix: The Dossier

(This post was back-dated so it doesn’t appear in the middle of the postings)

Posted in Uncategorized | Leave a Comment »