A lot of books are available on managing the software process, building and guiding teams of various sizes, and software practices. I've bought enough of them to be greeted by instant smiles at my local technical bookstore.
Very few, if any, of the books or big-name methods deal with the issues of one- or two-person teams: the SSEs (Solo Software Engineers). SSE can also stand for Suicidally Sustained Exertion or Smiling, Successful Entrepreneur--it's up to you.
So let's look at software engineering practices for the people who can't afford them. The main techniques I'll discuss involve nothing more formal than keeping a few diaries. This should be simple enough that anyone can make the time, and powerful enough to improve your process.
These techniques have been developed through years of working on my own and with one or two assistants. Major projects have included:
- Replacing the terminal emulation in NCSA Telnet (lots of minor changes in complex, foreign code with possible side effects and so needing excruciatingly tight change control).
- Developing a FORTRAN to Pascal translator (steady incremental development, with lots of checking to make sure nothing is missed).
- Database programming in 4th Dimension (a typical fourth-generation language with bits of code attached to various fields and scripts, so editing can affect many separate locations).
- Developing our object-oriented database management system product (many iterations through design, evaluation of alternative syntax and refinement of code).
- Maintenance over four years of a magazine publishing system (rare forays into a complex Object Pascal program to make very minor changes).
I was fortunate that early in my career I came under the supervision of an "old fashioned" engineering manager (thanks, Bob).
We had a very small support department, and only survived on the strength of our documentation. Detailed records of what happened were life-savers when a similar problem cropped up a year later.
One lesson that sank into my memory, as I drummed it into successive operators, was that searchable content is more important than formatting. I banned the use of the word processor, and we used simple text files on the VAX. Later, we graduated to the online help system because it was still easily searchable but added some structure.
Something else I learned as a system manager was the difference in procedures needed for backup operators, who are usually staggering around at 3 a.m., vs. the wide-awake daytime shift. How many programmers do you know who keep going past the caffeine limit?
Fear, Uncertainty, and Doubt (FUD) is not only a common marketing tactic, but it all too often describes the state of mind of an SSE.
Uncertainty rears its head when you're trying to remember why you made the design decisions leading to the current code.
Fear and doubt emerge within that sinking feeling that the brilliant alternative you just thought of was dismissed three months ago for good reasons.
Unfortunately, programmers often feel that they should be able to remember how their code works. We've had Egoless Programming; I think it's time for "Mindless Programming." This doesn't mean programming without thinking, but programming without feeling that you must remember the context and implications of what you're doing beyond a trivial local level. ("Memoryless Programming" is probably more accurate, but not as catchy a term.)
Put another way, you can't afford to rely on your memory if you can't guarantee how long you'll be working on the same task. The smaller the team, the more likely that your current task will be interrupted for a significant break.
Talking to Yourself
How can one person botch the communication between different phases of an entire project? Hopefully, you don't have any problems talking to yourself (ignoring the snickers of observers), but you're not one person. You are a series of individuals with very similar thinking, stretched over time.
Even when not communicating with others, the formality of writing things down can give you an extra insight, or remind you of a consequence you hadn't fully considered.
You'll feel wonderfully self-righteous when you come back to a project, panic briefly when you can't remember a thing about it, then discover all these clear notes saying where you left off and what you were doing.
Diary-Based Software Engineering
The essence of this approach is a series of diaries. The various diaries have overlapping information but distinctly different purposes. This is like documenting a design with overlapping scenarios and techniques--the redundancy helps you avoid missing any important points. You'll need the following equipment:
- (Mandatory) a text editor that lets you keep several documents open at a time, word-wraps, and also allows minor formatting for emphasis (this last feature is optional).
- (Optional) a second computer or, for Macintosh programmers, a second monitor. Seriously, keeping detailed diaries as you go is a lot easier if you aren't flipping your current work out of view while you record it. Giraffe-necked UNIX programmers with 21-inch monitors are excused.
The Site or Project Diary
The purpose of a site or project diary is to summarize external factors that may affect the project and to track interaction with the client. It contains:
- Major changes in project direction. You can refer to contract documents if the changes are large, but particularly track the little verbal changes
- Changes in the environment, including hardware and incidental software, such as operating systems or anything that can affect your product
- A log of installations
- A log of user bug reports.
The Random Thoughts Diary
This diary tracks ideas without in-depth analysis. Keep it free-format so you can quickly capture ideas before they fade. It contains:
- Ideas for new features
- Problems you may encounter and need to research
- Alternative implementations.
The Design Decisions Diary
This diary provides the basis for a design decision, the supporting arguments, and rejections. This is the key diary that prevents you from wasting time reinventing "brilliant" ideas six months later. It contains:
- Quick descriptions of each issue to be decided--anything where you have to select between alternatives and the choice can't be documented by a comment in your code
- A list of alternative designs
- Arguments for and against the design you chose
- A description of your final design.
The Code Change Diary
The code change diary tracks code changes in enough detail to let you recreate or undo them. It contains:
- Headings indicating the major reason for the change (often the same heading you'd use to store changes into your version control system)
- Usually a line of description for each change to each method or function
- Line-by-line changes where necessary (for example, if you're modifying a complex system with a few key changes--list the actual lines and the new versions).
Using the Diaries
A classic management tactic is to delegate tasks to avoid disrupting your work flow. The thoughts diary can be useful here. Delegate to your future self. As you think of something, jot down a brief note. Don't take the time to explore the feasibility of the idea, just record enough detail to jog your memory.
Make entering code changes a reflex action. As you change a function, flip across to the diary and log the change.
The dated list of ideas in the thoughts diary can prevent "creeping featureitis." Ideas that seem very powerful may be worth postponing to a later version. Go back and annotate your original comments to this effect.
Most important, periodically review the thoughts and decisions diaries. You may have issues in the thoughts diary that have not been resolved. In both cases, rereading entries often provokes more ideas.
User Testing by Self Hypnosis
If you're solo or leading a two-person team, you probably can't afford a testing lab for human interface testing, white coats, video cameras, and a few dozen testers. Don't despair, you can still do some effective user interface testing with little or no budget.
After years of working part-time on a computer science degree, I took a couple of semesters of creative writing for something different. One thing I learned was how to stage a scene in my imagination. I learned to abandon my role as author and sit back and experience the scene I had written as a member of the audience. (I often imagined I was sitting behind one of those annoying types who verbalize every reaction--grunting, chuckling and occasionally tearing apart my masterpiece.)
You can use similar techniques to simulate user interface testing, but it takes practice. I find it helps to close my eyes. If I can see the screen, it's immediately too real for me. Imagine that you're sitting behind your typical user, notebook on your lap, watching them stumble over your interface. Pay attention to every pause, and bite your tongue to avoid crying out "click there, in the bottom-right corner." If you record your observations from this exercise, you'll anticipate many of your users' questions and problems beforehand.
To succeed as an SSE, you need to be multiskilled, or at least aware of your areas of ignorance. A good way to pick up references to books, papers, or techniques is to lurk in places like SDFORUM and CASEFORUM on CompuServe, and the Internet newsgroups comp.human-factors, comp.databases, and comp.object.
Good debugging and code browsing tools can save days. For C++ programming, I'm a fan of MicroQuill's SmartHeap and ACI US's Object Master. SmartHeap provides C++ memory management, and memory validation (a topic unto itself). Object Master is a browser with multiple Smalltalk-style and tree browsers. It is particularly useful when learning today's application frameworks, such as the MFC forest.
Buy a version control system and use it religiously. I use the shareware Voodoo Lite on the Mac (available from most ftp sites), which also handles binary files well. This lets me store documentation and graphics with source code.
The techniques I've discussed could easily be combined into a software product. A cross-referenced database would be nice, as would be reminders linked to the Thoughts diary. However, this simple text-based approach is small enough to be used and powerful enough to be useful.
In these days of outsourcing and downsizing, I'm sure the ranks of the SSEs are growing. Hopefully this article will provoke some discussion amongst us.
- Easy syntax to declare
- Descend from dbField, and have read-only access to calculated values
- Minimal impact on current back-end logic
- Don't have any constructor-based declaration other than field name segments that are assigned in the body of the constructor.
- Breaking any assumptions that dbField::fieldNumber() maps directly to a DODA field number (if people mix-in derived fields, they don't have a DODA slot).
- However, we've already broken this assumption, as we insert extra DODA fields as fillers to get the padding.
FUNC operator<<(dbCompoundField, dbField)
- Added to call dbCompoundField::addSegment
- Added default false
- Added to return true
- Added to return a const dbField* of a segment
- Check fieldsVirtual and don't advance DODA numbers
- Removed unnecessary second retrieval of current field pointer
- Build multiple segment keys for compound fields
- Use fieldLen() calls instead of DODA length in defining segments
- Don't include the terminating nulls on chars! (particularly in compounds)
- Return 1 for compoundFields--they should have no padding
- Skip virtual field