It's all ones and zeros

Agile, Tribal Knowledge, and the Trail of Documentation

When I encounter a software company that claims to be “agile,” I often also hear something like this: “We’re an agile shop. We don’t do documentation because we don’t need to.  Documentation goes obsolete quickly.”

Yeah, right.

Whenever I hear such things, there is a part of my brain called the bullshitathalamus that quickly utters some uncharitable terminology such as “Weak.  Lame.  Lazy.”

Thankfully, I am disciplined enough that my mouth does not usually spew forth in the same manner.  Instead, what comes out is more like this: “I respectfully disagree.  Meaningful documentation is worth its weight in gold, and it need not be difficult to create and maintain.”

Agile: Dooming Us to Repeat History

While I enjoy the iterative nature of agile approaches to software development, one side effect seems to have been an erosion of disciplined practices.  I have personally entered many an agile fray, only to find that the waters of tribal knowledge are cold and deep.

I can understand why. In the absence of turnover, a technical team will gradually learn all it needs to know as iterations progress toward a working (or not working, as the case may be) product. They make good decisions, bad decisions, and bump into enough walls to get a product out the door. They will be just expert enough to complete the tasks, and no more.

Without capturing some of those all-important “lessons learned,” they are simply lessons not learned, and the team’s collective skill is only as good as its own organizational memory.

Ah, but we have user stories, the agile folks say.  User stories are completely unsatisfactory for capturing project history.  They are usually written in the moment, relevant for a sprint or two, and then they are thrown into a bucket in a tracking tool, never to be seen again.  In addition, user stories are usually written by the business or by business analysts – they aren’t used for describing the technical aspects of a software system.  I’ve written more than my share of user stories.  When I look back over several hundred – or thousand – user stories, I shudder to think of how any poor soul could consume them after the fact.

The Tribal Knowledge Effect

Although it is rarely discussed, and barely even recognized by non-technical business folk in the software industry, tribal knowledge can be very expensive.  Imagine hiring five high-powered software developers to take over a hundred thousand line-of-code product after a mass layoff.  The business person thinks “Well, they should just pick it up and be productive.  After all, they are world-class, and this software stuff is just ones and zeros.” Ones and zeros indeed.  Billions are spent to put those ones and zeros in the right order.  It can be a very challenging and yet poorly-understood dilemma.

In reality, those five people could be little more than expensive boat-anchors unless there is some serious reverse engineering happening, or unless there is a very standardized framework involved.  There are other related penalties such as frustration and product instability – possibly serious defects – while the new staff gain the expertise that is required.

The reality is that building software is complicated and difficult.  In my experience, a major design decision is made every couple hundred lines of code.  That’s an awful lot of historical design decisions over the life of a product. Without the vision of the previous generation of engineers, the knowledge of past decisions, and the trade-offs made for the business direction, the entire ecosystem of software becomes either greenfield or a minefield depending on its maturity level.

Writing is Important

Early on in my software life, I heard someone say “design without documentation is not design.”  I heard the words, but I did not know what they meant at the time.  As my skills evolved, I noticed a strange thing whenever I would put pen to paper:

The act of writing down my ideas causes a change in my understanding of those same ideas.

When I draw design-ish diagrams, or describe what I am doing in writing, my brain is processing the topic.  It is rotating the concepts in different ways as it looks for methods of description.  Over and over again, I have found that the simple act of either writing, drawing, or describing technical systems actually improves my understanding, and in some cases, my own decision making.

The usual statement that documentation is worthless simply because it is quickly outdated seems oblivious to this point.  Not everyone is a great writer, myself included.  There are plenty of ways to write, draw, and record that need not be limited by ones writing talent.

As an aside, I have made the same observation about writing tests before, during, or immediately after coding.  The code under test will be more decoupled, likely easier to read and understand, and will have a much cleaner interface.  I think this is part of the reason I like the evolving microservice trend: the scope of a decoupled service is small enough to where one can truly master it, describe it, understand it, evolve it, and so forth.  It is a very fulfilling feeling when that happens.

My Documentation Practices

After all this, you might think that I favor reams of remedial documentation, just for its own sake.  But I tend to take a pragmatic view of the topic. One does not need to be a TOGAF expert just to get the point across.  Here are the key pieces of my own personal Counter-Tribal Knowledge (CTK) policy.

A Concept Document

A concept document is a concise, no-fluff document that discusses the business purpose of the software, and breaks that purpose down into the major system components, business objects, and relationships between them.  When I write a concept document, I try to adhere to commonly understood terminology any avoid injecting any confusing nomenclature (sometimes that means eschewing UML notation as I have mentioned in other posts) or arbitrary redefinition of business terms.

I will often have my work reviewed by someone else, because I will doubtless think it is completely clear on the first revision, yet it is seldom so.  I know, Dear Reader, this is difficult to imagine.

Such a document contains consumable block diagrams of the software’s static structure, its deployment architecture, its dependencies, and so forth.  Where interfaces between components are critical to success, sequence diagrams are added to help the reader understand what is significant, what is not, and how the interactions were intended to work.  A good concept document is an enormous help in ramping up on a new project.

Tests As Documentation

Since I was reared in the military and avionics software world where “proper requirements management” is a Really Big Deal, I have always reached for a close coupling between requirements and system-level tests. When properly done, a solid suite of tests represents the truest description of system behavior outside of the code itself.

I have witnessed first-hand the challenges of requirements management in the commercial world, so I have become a much larger fan of integrating testing directly to the implementation on as many levels as practical, in a noninvasive manner.  Modern CI tools and automation support are a terrific help in this regard.

Where documentation management is challenging, automated tests can come to the rescue, because they are the only technically-coupled description of proper behavior.  Want to know if your API returns standard status values?  Look at your tests.  At the very least, existing tests are the first line of defense against regression.

Code for the Reader, Not Yourself

You knew that I would mention code at some point, right?  Low-level implementation practices can  help reduce tribal knowledge and also hedge against regression, provided some simple conventions are followed.  By “conventions,” I mean things like this:

  • Important classes, interfaces, or algorithms can be augmented with concise, direct comments.
  • Small README markdown files can be placed alongside the code to explain the reasoning behind certain packages, directories, or components.
  • Self-describing classes, methods, and functions go a long way to helping someone understand the intentions around the implementation details.
  • Comments can be placed on database columns.  Although I rarely see teams do this, the practice takes very little incremental work, yet it is extremely useful in producing a data dictionary later in the project.
  • Decoupling of services along domain boundaries will influence the way a new technical staff member views the overall design.  This can be a positive or negative, depending on the maturity of the design.

Leaving the World a Better Place

I’ve always left some kind of knowledge trail at every company I have been involved with.  Sometimes it is for my own selfish use, because my memory can be short at times.  But it means that I leave the organization in a slightly better place than when I started.

As a result of practicing these things, I always put some written content in place so that a new person can consume it to aid their own knowledge; I rarely have to document a bunch of items at the last minute before my departure from a team.  I greatly appreciate it when someone else has shown the same attention on projects that I inherit.

There is no silver bullet to replace professional diligence.  Management of knowledge takes creativity and hard work.  I have found the results to be well worth the effort.