From: Subject: How to be a Programmer: A Short, Comprehensive, and Personal Summary Date: Sat, 19 May 2012 17:02:32 +1000 MIME-Version: 1.0 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Location: http://samizdat.mines.edu/howto/HowToBeAProgrammer.html X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6109 =EF=BB=BF How to be a Programmer: A Short, Comprehensive, and = Personal Summary

How to be a Programmer: A = Short,=20 Comprehensive, and Personal Summary

Robert L Read

Copyright =EF=BF=BD 2002, 2003 Robert L. Read =

Copyright=20

Copyright =EF=BF=BD 2002, 2003

by Robert L. = Read. Permission is=20 granted to copy, distribute and/or modify this document under the terms = of the=20 GNU Free Documentation License, Version 1.2 or any later version = published by=20 the Free Software Foundation; with one Invariant Section being = =E2=80=98History (As of February, 2003)=E2=80=99, no = Front-Cover Texts, and=20 one Back-Cover Text: =E2=80=98The original version = of this document=20 was written by Robert L. Read without renumeration and dedicated to the=20 programmers of Hire.com.=E2=80=99 A copy of the license is = included in the=20 section entitled =E2=80=98GNU Free Documentation = License=E2=80=99.=20

2002


Dedication

To the programmers of Hire.com.

Table of Contents

1. Introduction
2. Beginner
Personal=20 Skills
Learn=20 to Debug
How=20 to Debug by Splitting the Problem Space
How=20 to Remove an Error
How=20 to Debug Using a Log
How=20 to Understand Performance Problems
How=20 to Fix Performance Problems
How=20 to Optimize Loops
How=20 to Deal with I/O Expense
How=20 to Manage Memory
How=20 to Deal with Intermittent Bugs
How=20 to Learn Design Skills
How=20 to Conduct Experiments
Team=20 Skills
Why=20 Estimation is Important
How=20 to Estimate Programming Time
How=20 to Find Out Information
How=20 to Utilize People as Information Sources
How=20 to Document Wisely
How=20 to Work with Poor Code
How=20 to Use Source Code Control
How=20 to Unit Test
Take=20 Breaks when Stumped
How=20 to Recognize When to Go Home
How=20 to Deal with Difficult People
3. Intermediate
Personal=20 Skills
How=20 to Stay Motivated
How=20 to be Widely Trusted
How=20 to Tradeoff Time vs. Space
How=20 to Stress Test
How=20 to Balance Brevity and Abstraction
How=20 to Learn New Skills
Learn=20 to Type
How=20 to Do Integration Testing
Communication=20 Languages
Heavy=20 Tools
How=20 to analyze data
Team=20 Skills
How=20 to Manage Development Time
How=20 to Manage Third-Party Software Risks
How=20 to Manage Consultants
How=20 to Communicate the Right Amount
How=20 to Disagree Honestly and Get Away with It
Judgement
How=20 to Tradeoff Quality Against Development Time
How=20 to Manage Software System Dependence
How=20 to Decide if Software is Too Immature
How=20 to Make a Buy vs. Build Decision
How=20 to Grow Professionally
How=20 to Evaluate Interviewees
How=20 to Know When to Apply Fancy Computer Science
How=20 to Talk to Non-Engineers
4. Advanced
Technological=20 Judgment
How=20 to Tell the Hard From the Impossible
How=20 to Utilize Embedded Languages
Choosing=20 Languages
Compromising=20 Wisely
How=20 to Fight Schedule Pressure
How=20 to Understand the User
How=20 to Get a Promotion
Serving=20 Your Team
How=20 to Develop Talent
How=20 to Choose What to Work On
How=20 to Get the Most From Your Teammates
How=20 to Divide Problems Up
How=20 to Handle Boring Tasks
How=20 to Gather Support for a Project
How=20 to Grow a System
How=20 to Communicate Well
How=20 to Tell People Things They Don't Want to Hear
How=20 to Deal with Managerial Myths
How=20 to Deal with Organizational Chaos
Glossary
A.
B. History=20 (As Of February, 2003)
C. GNU= Free=20 Documentation License
P= REAMBLE
A= PPLICABILITY=20 AND DEFINITIONS
V= ERBATIM=20 COPYING
C= OPYING=20 IN QUANTITY
M= ODIFICATIONS
C= OMBINING=20 DOCUMENTS
C= OLLECTIONS=20 OF DOCUMENTS
A= GGREGATION=20 WITH INDEPENDENT WORKS
T= RANSLATION
T= ERMINATION
= FUTURE=20 REVISIONS OF THIS LICENSE
ADDENDUM:=20 How to use this License for your = documents

Chapter=EF=BF=BD1.=EF=BF=BDIntroduction

Table of Contents

To be a good programmer is difficult and noble. The hardest part of = making=20 real a collective vision of a software project is dealing with one's = coworkers=20 and customers. Writing computer programs is important and takes great=20 intelligence and skill. But it is really child's play compared to = everything=20 else that a good programmer must do to make a software system that = succeeds for=20 both the customer and myriad colleagues for whom she is partially = responsible.=20 In this essay I attempt to summarize as concisely as possible those = things that=20 I wish someone had explained to me when I was twenty-one.

This is very subjective and, therefore, this essay is doomed to be = personal=20 and somewhat opinionated. I confine myself to problems that a programmer = is very=20 likely to have to face in her work. Many of these problems and their = solutions=20 are so general to the human condition that I will probably seem preachy. = I hope=20 in spite of this that this essay will be useful.

Computer programming is taught in courses. The excellent books: The Pragmatic Programmer [Prag99], Code Complete = [CodeC93], Rapid = Development [RDev96], and Extreme = Programming=20 Explained [XP99] all teach computer = programming=20 and the larger issues of being a good programmer. The essays of Paul=20 Graham[PGSite] and Eric Raymond[Hacker] should certainly be read before or along = with this=20 article. This essay differs from those excellent works by emphasizing = social=20 problems and comprehensively summarizing the entire set of necessary = skills as I=20 see them.

In this essay the term boss to refer to = whomever gives=20 you projects to do. I use the words business, = company, and tribe, = synonymously=20 except that business connotes moneymaking, company connotes the modern = workplace=20 and tribe is generally the people you share loyalty with.

Welcome to the tribe.

Chapter=EF=BF=BD2.=EF=BF=BDBeginner

=

Table of Contents

Personal=20 Skills
Learn=20 to Debug
How=20 to Debug by Splitting the Problem Space
How=20 to Remove an Error
How=20 to Debug Using a Log
How=20 to Understand Performance Problems
How=20 to Fix Performance Problems
How=20 to Optimize Loops
How=20 to Deal with I/O Expense
How=20 to Manage Memory
How=20 to Deal with Intermittent Bugs
How=20 to Learn Design Skills
How=20 to Conduct Experiments
Team=20 Skills
Why=20 Estimation is Important
How=20 to Estimate Programming Time
How=20 to Find Out Information
How=20 to Utilize People as Information Sources
How=20 to Document Wisely
How=20 to Work with Poor Code
How=20 to Use Source Code Control
How=20 to Unit Test
Take=20 Breaks when Stumped
How=20 to Recognize When to Go Home
How=20 to Deal with Difficult People

Personal = Skills

Learn to = Debug

Debugging is the cornerstone of being a programmer. The first meaning = of the=20 verb to debug is to remove = errors, but the=20 meaning that really matters is to see into = the=20 execution of a program by examining it. A programmer that = cannot=20 debug effectively is blind.

Idealists that think design, or analysis, or complexity theory, or = whatnot,=20 are more fundamental are not working programmers. The working programmer = does=20 not live in an ideal world. Even if you are perfect, your are surrounded = by and=20 must interact with code written by major software companies, = organizations like=20 GNU, and your colleagues. Most of this code is imperfect and imperfectly = documented. Without the ability to gain visibility into the execution of = this=20 code the slightest bump will throw you permanently. Often this = visibility can=20 only be gained by experimentation, that is, debugging.

Debugging is about the running of programs, not programs themselves. = If you=20 buy something from a major software company, you usually don't get to = see the=20 program. But there will still arise places where the code does not = conform to=20 the documentation (crashing your entire machine is a common and = spectacular=20 example), or where the documentation is mute. More commonly, you create = an=20 error, examine the code you wrote and have no clue how the error can be=20 occurring. Inevitably, this means some assumption you are making is not = quite=20 correct, or some condition arises that you did not anticipate. Sometimes = the=20 magic trick of staring into the source code works. When it doesn't, you = must=20 debug.

To get visibility into the execution of a program you must be able to = execute=20 the code and observe something about it. Sometimes this is visible, like = what is=20 being displayed on a screen, or the delay between two events. In many = other=20 cases, it involves things that are not meant to be visible, like the = state of=20 some variables inside the code, which lines of code are actually being = executed,=20 or whether certain assertions hold across a complicated data structure. = These=20 hidden things must be revealed.

The common ways of looking into the =E2=80=98innards=E2=80=99 of an=20 executing program can be categorized as:

  • Using a debugging tool,

  • Printlining --- Making a temporary modification to the program, = typically=20 adding lines that print information out, and

  • Logging --- Creating a permanent window into the programs execution = in the=20 form of a log.

Debugging tools are wonderful when they are stable and available, but = the=20 printlining and logging are even more important. Debugging tools often = lag=20 behind language development, so at any point in time they may not be = available.=20 In addition, because the debugging tool may subtly change the way the = program=20 executes it may not always be practical. Finally, there are some kinds = of=20 debugging, such as checking an assertion against a large data structure, = that=20 require writing code and changing the execution of the program. It is = good to=20 know how to use debugging tools when they are stable, but it is critical = to be=20 able to employ the other two methods.

Some beginners fear debugging when it requires modifying code. This = is=20 understandable---it is a little like exploratory surgery. But you have = to learn=20 to poke at the code and make it jump; you have to learn to experiment on = it, and=20 understand that nothing that you temporarily do to it will make it = worse. If you=20 feel this fear, seek out a mentor---we lose a lot of good programmers at = the=20 delicate onset of their learning to this fear.

How to Debug by Splitting the = Problem=20 Space

Debugging is fun, because it begins with a mystery. You think it = should do=20 something, but instead it does something else. It is not always quite so = simple---any examples I can give will be contrived compared to what = sometimes=20 happens in practice. Debugging requires creativity and ingenuity. If = there is a=20 single key to debugging is to use the divide and = conquer=20 technique on the mystery.

Suppose, for example, you created a program that should do ten things = in a=20 sequence. When you run it, it crashes. Since you didn't program it to = crash, you=20 now have a mystery. When out look at the output, you see that the first = seven=20 things in the sequence were run successfully. The last three are not = visible=20 from the output, so now your mystery is smaller: =E2=80=98It crashed=20 on thing #8, #9, or #10.=E2=80=99

Can you design an experiment to see which thing it crashed on? Sure. = You can=20 use a debugger or we can add printline statements (or the equivalent in = whatever=20 language you are working in) after #8 and #9. When we run it again, our = mystery=20 will be smaller, such as =E2=80=98It crashed on = thing #9.=E2=80=99 I=20 find that bearing in mind exactly what the mystery is at any point in = time helps=20 keep one focused. When several people are working together under = pressure on a=20 problem it is easy to forget what the most important mystery is.

The key to divide and conquer as a debugging technique is the same as = it is=20 for algorithm design: as long as you do a good job splitting the mystery = in the=20 middle, you won't have to split it too many times, and you will be = debugging=20 quickly. But what is the middle of a mystery? There is where true = creativity and=20 experience comes in.

To a true beginner, the space of all possible errors looks like every = line in=20 the source code. You don't have the vision you will later develop to see = the=20 other dimensions of the program, such as the space of executed lines, = the data=20 structure, the memory management, the interaction with foreign code, the = code=20 that is risky, and the code that is simple. For the experience = programmer, these=20 other dimensions form an imperfect but very useful mental model of all = the=20 things that can go wrong. Having that mental model is what helps one = find the=20 middle of the mystery effectively.

Once you have evenly subdivided the space of all that can go wrong, = you must=20 try to decide in which space the error lies. In the simple case where = the=20 mystery is: =E2=80=98Which single unknown line makes = my program=20 crash?=E2=80=99, you can ask yourself: =E2=80=98Is the unknown line=20 executed before or after this line that I judge to be executed in the = about the=20 middle of the running program?=E2=80=99 Usually you will not be = so lucky as to=20 know that the error exists in a single line, or even a single block. = Often the=20 mystery will be more like: =E2=80=98Either there is = a pointer in that=20 graph that points to the wrong node, or my algorithm that adds up the = variables=20 in that graph doesn't work.=E2=80=99 In that case you may have to = write a small=20 program to check that the pointers in the graph are all correct in order = to=20 decide which part of the subdivided mystery can be eliminated. =

How to Remove an = Error

I've intentionally separated the act of examining a program's = execution from=20 the act of fixing an error. But of course, debugging does also mean removing the = bug.=20 Ideally you will have perfect understanding of the code and will reach = an =E2=80=98A-Ha!=E2=80=99 moment where you perfectly see the = error and how to=20 fix it. But since your program will often use insufficiently documented = systems=20 into which you have no visibility, this is not always possible. In other = cases=20 the code is so complicated that your understanding cannot be perfect. =

In fixing a bug, you want to make the smallest change that fixes the = bug. You=20 may see other things that need improvement; but don't fix those at the = same=20 time. Attempt to employ the scientific method of changing one thing and = only one=20 thing at a time. The best process for this is to be able to easily = reproduce the=20 bug, then put your fix in place, and then rerun the program and observe = that the=20 bug no longer exists. Of course, sometimes more than one line must be = changed,=20 but you should still conceptually apply a single atomic change to fix = the bug.=20

Sometimes, there are really several bugs that look like one. It is up = to you=20 to define the bugs and fix them one at a time. Sometimes it is unclear = what the=20 program should do or what the original author intended. In this case, = you must=20 exercise your experience and judgment and assign your own meaning to the = code.=20 Decide what it should do, and comment it or clarify it in some way and = then make=20 the code conform to your meaning. This is an intermediate or advanced = skill that=20 is sometimes harder than writing the original function in the first = place, but=20 the real world is often messy. You may have to fix a system you cannot = rewrite.=20

How to Debug Using a = Log

Logging is the practice of writing a system = so that it=20 produces a sequence of informative records, called a log.=20 Printlining is just producing a simple, usually = temporary, log. Absolute beginners must understand and use logs because = their=20 knowledge of the programming is limited; system architects must = understand and=20 use logs because of the complexity of the system. The amount of = information that=20 is provided by the log should be configurable, ideally while the program = is=20 running. In general, logs offer three basic advantages:

  • Logs can provide useful information about bugs that are hard to = reproduce=20 (such as those that occur in the production environment but that = cannot be=20 reproduced in the test environment).

  • Logs can provide statistics and data relevant to performance, such = as the=20 time passing between statements.

  • When configurable, logs allow general information to be captured in = order=20 to debug unanticipated specific problems without having to modify = and/or=20 redeploy the code just to deal with those specific problems.=20

The amount to output into the log is always a compromise between = information=20 and brevity. Too much information makes the log expensive and produces = scroll blindness, making it hard to find the = information you=20 need. Too little information and it may not contain what you need. For = this=20 reason, making what is output configurable is very useful. Typically, = each=20 record in the log will identify its position in the source code, the = thread that=20 executed it if applicable, the precise time of execution, and, commonly, = an=20 additional useful piece of information, such as the value of some = variable, the=20 amount of free memory, the number of data objects, etc. These log = statements are=20 sprinkled throughout the source code but are particularly at major = functionality=20 points and around risky code. Each statement can be assigned a level and = will=20 only output a record if the system is currently configured to output = that level.=20 You should design the log statements to address problems that you = anticipate.=20 Anticipate the need to measure performance.

If you have a permanent log, printlining can now be done in terms of = the log=20 records, and some of the debugging statements will probably be = permanently added=20 to the logging system.

How to Understand Performance=20 Problems

Learning to understand the performance of a running system is = unavoidable for=20 the same reason that learning debugging is. Even if the code you = understand=20 perfectly precisely the cost of the code you write, your code will make = calls=20 into other software systems that you have little control over or = visibility=20 into. However, in practice performance problems are a little different = and a=20 little easier than debugging in general.

Suppose that you or your customers consider a system or a subsystem = to be too=20 slow. Before you try to make it faster, you must build a mental model of = why it=20 is slow. To do this you can use a profiling tool or a good log to figure = out=20 where the time or other resources are really being spent. There is a = famous=20 dictum that 90% of the time will be spent in 10% of the code. I would = add to=20 that the importance of input/output expense (I/O) to performance issues. = Often=20 most of the time is spent in I/O in one way or another. Finding the = expensive=20 I/O and the expensive 10% of the code is a good first step to building = your=20 mental model.

There are many dimensions to the performance of a computer system, = and many=20 resources consumed. The first resource to measure is wall--clock time, the total time that passes for = the=20 computation. Logging wall-clock time is particularly valuable because it = can=20 inform about unpredictable circumstance that arise in situations where = other=20 profiling is impractical. However, this may not always represent the = whole=20 picture. Sometimes something that takes a little longer but doesn't burn = up so=20 many processor seconds will be much better in computing environment you = actually=20 have to deal with. Similarly, memory, network bandwidth, database or = other=20 server accesses may, in the end, be far more expensive than processor = seconds.=20

Contention for shared resources that are synchronized can cause = deadlock and=20 starvation. Deadlock is the inability to proceed because of improper=20 synchronization or resource demands. Starvation is the failure to = schedule a=20 component properly. If it can be at all anticipated, it is best to have = a way of=20 measuring this contention from the start of your project. Even if this=20 contention does not occur, it is very helpful to be able to assert that = with=20 confidence.

How to Fix Performance=20 Problems

Most software projects can be made with relatively little effort 10 = to 100=20 times faster than they are at the they are first released. Under = time-to-market=20 pressure, it is both wise and effective to choose a solution that gets = the job=20 done simply and quickly, but less efficiently than some other solution. = However,=20 performance is a part of usability, and often it must eventually be = considered=20 more carefully.

The key to improving the performance of a very complicated system is = to=20 analyze it well enough to find the bottlenecks, = or places=20 where most of the resources are consumed. There is not much sense in = optimizing=20 a function that accounts for only 1% of the computation time. As a rule = of thumb=20 you should think carefully before doing anything unless you think it is = going to=20 make the system or a significant part of it at least twice as fast. = There is=20 usually a way to do this. Consider the test and quality assurance effort = that=20 your change will require. Each change brings a test burden with it, so = it is=20 much better to have a few big changes.

After you've made a two-fold improvement in something, you need to at = least=20 rethink and perhaps reanalyze to discover the next-most-expensive = bottleneck in=20 the system, and attack that to get another two-fold improvement.

Often, the bottlenecks in performance will be an example of counting = cows by=20 counting legs and dividing by four, instead of counting heads. For = example, I've=20 made errors such as failing to provide a relational database system with = a=20 proper index on a column I look up a lot, which probably made it at = least 20=20 times slower. Other examples include doing unnecessary I/O in inner = loops,=20 leaving in debugging statements that are no longer needed, unnecessary = memory=20 allocation, and, in particular, inexpert use of libraries and other = subsystems=20 that are often poorly documented with respect to performance. This kind = of=20 improvement is sometimes called low-hanging = fruit,=20 meaning that it can be easily picked to provide some benefit.

What do you do when you start to run out of low-hanging fruit? Well, = you can=20 reach higher, or chop the tree down. You can continue making small = improvements=20 or you can seriously redesign a system or a subsystem. (This is a great=20 opportunity to use your skills as a good programmer, not only in the new = design=20 but also in convincing your boss that this is a good idea.) However, = before you=20 argue for the redesign of a subsystem, you should ask yourself whether = or not=20 your proposal will make it five to ten time better.

How to Optimize = Loops

Sometimes you'll encounter loops, or recursive functions, that take a = long=20 time to execute and are bottlenecks in your product. Before you try to = make the=20 loop a little faster, but spend a few minutes considering if there is a = way to=20 remove it entirely. Would a different algorithm do? Could you compute = that while=20 computing something else? If you can't find away around it, then you can = optimize the loop. This is simple; move stuff out. In the end, this will = require=20 not only ingenuity but also an understanding of the expense of each kind = of=20 statement and expression. Here are some suggestions:

  • Remove floating point operations.

  • Don't allocate new memory blocks unnecessarily.

  • Fold constants together.

  • Move I/O into a buffer.

  • Try not to divide.

  • Try not to do expensive typecasts.

  • Move a pointer rather than recomputing indices. =

The cost of each of these operations depends on your specific system. = On some=20 systems compilers and hardware do these things for you. Clear, efficient = code is=20 better than code that requires an understanding of a particular = platform.=20

How to Deal with I/O=20 Expense

For a lot of problems, processors are fast compared to the cost of=20 communicating with a hardware device. This cost is usually abbreviated = I/O, and=20 can include network cost, disk I/O, database queries, file I/O, and = other use of=20 some hardware not very close to the processor. Therefore building a fast = system=20 is often more a question of improving I/O than improving the code in = some tight=20 loop, or even improving an algorithm.

There are two very fundamental techniques to improving I/O: caching = and=20 representation. Caching is avoiding I/O (generally avoiding the reading = of some=20 abstract value) by storing a copy of that value locally so no I/O is = performed=20 to get the value. The first key to caching is to make it crystal clear = which=20 data is the master and which are copies. There is only one master---period. Caching = brings=20 with it the danger that the copy is sometimes can't reflect changes to = the=20 master instantaneously.

Representation is the approach of making I/O cheaper by representing = data=20 more efficiently. This is often in tension with other demands, like = human=20 readability and portability.

Representations can often be improved by a factor of two or three = from their=20 first implementation. Techniques for doing this include using a binary=20 representation instead of one that is human readable, transmitting a = dictionary=20 of symbols along with the data so that long symbols don't have to be = encoded,=20 and, at the extreme, things like Huffman encoding.

A third technique that is sometimes possible is to improve the = locality of=20 reference by pushing the computation closer to the data. For instance, = if you=20 are reading some data from a database and computing something simple = from it,=20 such as a summation, try to get the database server to do it for you. = This is=20 highly dependent on the kind of system you're working with, but you = should=20 explore it.

How to Manage = Memory

Memory is a precious resource that you can't afford to run out of. = You can=20 ignore it for a while but eventually you will have to decide how to = manage=20 memory.

Space that needs to persist beyond the scope of a single subroutine = is often=20 called heap allocated. A chunk of memory is = useless,=20 hence garbage, when nothing refers to it. = Depending on=20 the system you use, you may have to explicitly deallocate memory = yourself when=20 it is about to become garbage. More often you may be able to use a = system that=20 provides a garbage collector. A garbage = collector notices=20 garbage and frees its space without any action required by the = programmer.=20 Garbage collection is wonderful: it lessens errors and increases code = brevity=20 and concision cheaply. Use it when you can.

But even with garbage collection, you can fill up all memory with = garbage. A=20 classic mistake is to use a hash table as a cache and forget to remove = the=20 references in the hash table. Since the reference remains, the referent = is=20 noncollectable but useless. This is called a memory = leak.=20 You should look for and fix memory leaks early. If you have long running = systems=20 memory may never be exhausted in testing but will be exhausted by the = user.

The creation of new objects is moderately expensive on any system. = Memory=20 allocated directly in the local variables of a subroutine, however, is = usually=20 cheap because the policy for freeing it can be very simple. You should = avoid=20 unnecessary object creation.

An important case occurs when you can define an upper bound on the = number of=20 objects you will need at one time. If these objects all take up the same = amount=20 of memory, you may be able to allocate a single block of memory, or a = buffer, to=20 hold them all. The objects you need can be allocated and released inside = this=20 buffer in a set rotation pattern, so it is sometimes called a ring = buffer. This=20 is usually faster than heap allocation.

Sometimes you have to explicitly free allocated space so it can be=20 reallocated rather than rely on garbage collection. Then you must apply = careful=20 intelligence to each chunk of allocated memory and design a way for it = to be=20 deallocated at the appropriate time. The method may differ for each kind = of=20 object you create. You must make sure that every execution of a memory=20 allocating operation is matched by a memory deallocating operation = eventually.=20 This is so difficult that programmers often simply implement a = rudimentary form=20 or garbage collection, such as reference counting, to do this for them.=20

How to Deal with Intermittent=20 Bugs

The intermittent bug is a cousin of the=20 50-foot-invisible-scorpion-from-outer-space kind of bug. This nightmare = occurs=20 so rarely that it is hard to observe, yet often enough that it can't be = ignored.=20 You can't debug because you can't find it.

Although after 8 hours you will start to doubt it, the intermittent = bug has=20 to obey the same laws of logic everything else does. What makes it hard = is that=20 it occurs only under unknown conditions. Try to record the circumstances = under=20 which the bug does occur, so that you can guess at what the variability = really=20 is. The condition may be related to data values, such as =E2=80=98This=20 only happens when we enter Wyoming as a=20 value.=E2=80=99 If that is not the source of variability, the = next suspect should=20 be improperly synchronized concurrency.

Try, try, try to reproduce the bug in a controlled way. If you can't=20 reproduce it, set a trap for it by building a logging system, a special = one if=20 you have to, that can log what you guess you need when it really does = occur.=20 Resign yourself to that if the bug only occurs in production and not at = your=20 whim, this is may be a long process. The hints that you get from the log = may not=20 provide the solution but may give you enough information to improve the = logging.=20 The improved logging system may take a long time to be put into = production.=20 Then, you have to wait for the bug to reoccur to get more information. = This=20 cycle can go on for some time.

The stupidest intermittent bug I ever created was in a multi-threaded = implementation of a functional programming language for a class project. = I had=20 very carefully insured correct concurrent evaluation of the functional = program,=20 good utilization of all the CPUs available (eight, in this case). I = simply=20 forgot to synchronize the garbage collector. The system could run a long = time,=20 often finishing whatever task I began, before anything noticeable went = wrong.=20 I'm ashamed to admit I had begun to question the hardware before my = mistake=20 dawned on me.

At work we recently had an intermittent bug that took us several = weeks to=20 find. We have multi-threaded application servers in Java=E2=84=A2 behind Apache=E2=84=A2 web=20 servers. To maintain fast page turns, we do all I/O in small set of four = separate threads that are different than the page-turning threads. Every = once in=20 a while these would apparently get =E2=80=98stuck=E2=80=99 and cease=20 doing anything useful, so far as our logging allowed us to tell, for = hours.=20 Since we had four threads, this was not in itself a giant = problem---unless all=20 four got stuck. Then the queues emptied by these threads would quickly = fill up=20 all available memory and crash our server. It took us about a week to = figure=20 this much out, and we still didn't know what caused it, when it would = happen, or=20 even what the threads where doing when they got =E2=80=98stuck=E2=80=99.

This illustrates some risk associated with third-party software. We = were=20 using a licensed piece of code that removed HTML tags from text. Due to = its=20 place of origin we affectionately referred to this as =E2=80=98the=20 French stripper.=E2=80=99 Although we had the source code (thank = goodness!) we=20 had not studied it carefully until by turning up the logging on our = servers we=20 finally realized that the email threads were getting stuck in the French = stripper.

The stripper performed well except on some long and unusual kinds of = texts.=20 On these texts, the code was quadratic or worse. This means that the = processing=20 time was proportional to the square of the length of the text. Had these = texts=20 occurred commonly, we would have found the bug right away. If they had = never=20 occurred at all, we would never have had a problem. As it happens, it = took us=20 weeks to finally understand and resolve the problem.

How to Learn Design=20 Skills

To learn how to design software, study the action of a mentor by = being=20 physically present when they are designing. Then study well-written = pieces of=20 software. After that, you can read some books on the latest design = techniques.=20

Then you must do it yourself. Start with a small project. When you = are=20 finally done, consider how the design failed or succeeded and how you = diverged=20 from your original conception. They move on to larger projects, = hopefully in=20 conjunction with other people. Design is a matter of judgment that takes = years=20 to acquire. A smart programmer can learn the basics adequately in two = months and=20 can improve from there.

It is natural and helpful to develop your own style, but remember = that design=20 is an art, not a science. People who write books on the subject have a = vested=20 interest in making it seem scientific. Don't become dogmatic about = particular=20 design styles.

How to Conduct=20 Experiments

The late, great Edsger Dijkstra has eloquently explained that = Computer=20 Science is not an experimental science[ExpCS] and=20 doesn't depend on electronic computers. As he puts it referring to the=20 1960s[Knife],

...the harm was done: the topic became = known as=20 =E2=80=9Ccomputer science=E2=80=9D---which, = actually, is like=20 referring to surgery as =E2=80=9Cknife = science=E2=80=9D --- and it=20 was firmly implanted in people's minds that computing science is about = machines and their peripheral equipment.

Programming ought not to be an experimental science, but most working = programmers do not have the luxury of engaging in what Dijkstra means by = computing science. We must work in the realm of experimentation, just as = some,=20 but not all, physicists do. If thirty years from now programming can be=20 performed without experimentation, it will be a great accomplishment of = Computer=20 Science.

The kinds of experiments you will have to perform include:

  • Testing systems with small examples to verify that they conform to = the=20 documentation or to understand their response when there is no = documentation,=20

  • Testing small code changes to see if they actually fix a bug,

  • Measuring the performance of a system under two different = conditions due to=20 imperfect knowledge of there performance characteristics,

  • Checking the integrity of data, and

  • Collecting statistics that may hint at the solution to difficult or = hard-to-repeat bugs.

I don't think in this essay I can explain the design of experiments; = you will=20 have to study and practice. However, I can offer two bits of advice. =

First, try to be very clear about your hypothesis, or the assertion = that you=20 are trying to test. It also helps to write the hypothesis down, = especially if=20 you find yourself confused or are working with others.

You will often find yourself having to design a series of = experiments, each=20 of which is based on the knowledge gained from the last experiment. = Therefore,=20 you should design your experiments to provide the most information = possible.=20 Unfortunately, this is in tension with keeping each experiment = simple---you will=20 have to develop this judgment through experience.

Team=20 Skills

Why Estimation is=20 Important

To get a working software system in active use as quickly as possible = requires not only planning the development, but also planning the = documentation,=20 deployment, marketing. In a commercial project it also requires sales = and=20 finance. Without predictability of the development time, it is = impossible to=20 plan these effectively.

Good estimation provides predictability. Managers love it, as well = they=20 should. The fact that it is impossible, both theoretically and = practically, to=20 predict accurately how long it will take to develop software is often = lost on=20 managers. We are asked to do this impossible thing all the time, and we = must=20 face up to it honestly. However, it would be dishonest not to admit the=20 impossibility of this task, and when necessary, explain it. There is a = lot of=20 room for miscommunication about estimates, as people have a startling = tendency=20 to think wishfully that the sentence:

I estimate that, if I really understand = the=20 problem, it is about 50% likely that we will be done in five weeks (if = no one=20 bothers us during that time).

really means:

I promise to have it all done five weeks = from=20 now.

This common interpretation problem requires that you explicitly = discuss what=20 the estimate means with your boss or customer as if they were a = simpleton.=20 Restate your assumptions, no matter how obvious they seem to you. =

How to Estimate Programming=20 Time

Estimation takes practice. It also takes labor. It takes so much = labor it may=20 be a good idea to estimate the time it will take to make the estimate,=20 especially if you are asked to estimate something big.

When asked to provide an estimate of something big, the most honest = thing to=20 do is to stall. Most engineers are enthusiastic and eager to please, and = stalling certainly will displease the stalled. But an on-the-spot = estimate=20 probably won't be accurate and honest.

While stalling, it may be possible to consider doing or prototyping = the task.=20 If political pressure permits, this is the most accurate way of = producing the=20 estimate, and it makes real progress.

When not possible to take the time for some investigation, you should = first=20 establish the meaning of the estimate very clearly. Restate that meaning = as the=20 first and last part of your written estimate. Prepare a written estimate = by=20 deconstructing the task into progressively smaller subtasks until each = small=20 task is no more than a day; ideally at most in length. The most = important thing=20 is not to leave anything out. For instance, documentation, testing, time = for=20 planning, time for communicating with other groups, and vacation time = are all=20 very important. If you spend part of each day dealing with knuckleheads, = put a=20 line item for that in the estimate. This gives your boss visibility into = what is=20 using up your time at a minimum, and might get you more time.

I know good engineers who pad estimates implicitly, but I recommend = that you=20 do not. One of the results of padding is trust in you may be depleted. = For=20 instance, an engineer might estimate three days for a task that she = truly thinks=20 will take one day. The engineer may plan to spend two days documenting = it, or=20 two days working on some other useful project. But it will be detectable = that=20 the task was done in only one day (if it turns out that way), and the = appearance=20 of slacking or overestimating is born. It's far better to give proper = visibility=20 into what you are actually doing. If documentation takes twice as long = as coding=20 and the estimate says so, tremendous advantage is gained by making this = visible=20 to the manager.

Pad explicitly instead. If a task will probably take one day---but = might take=20 ten days if your approach doesn't work---note this somehow in the = estimate if=20 you can; if not, at least do an average weighted by your estimates of = the=20 probabilities. Any risk factor that you can identify and assign an = estimate to=20 should go into the schedule. One person is unlikely to be sick in any = given=20 week. But a large project with many engineers will have some sick time; = likewise=20 vacation time. And what is the probability of a mandatory company-wide = training=20 seminar? If it can be estimated, stick it in. There are of course, = unknown=20 unknowns, or unk-unks. Unk-unks by definition = cannot be=20 estimated individually. You can try to create a global line item for all = unk-unks, or handle them in some other way that you communicate to your = boss.=20 You cannot, however, let your boss forget that they exist, and it is = devilishly=20 easy for an estimate to become a schedule without the unk-unks = considered.

In a team environment, you should try to have the people who will do = the work=20 do the estimate, and you should try to have team-wide consensus on = estimates.=20 People vary widely in skill, experience, preparedness, and confidence. = Calamity=20 strikes when a strong programmer estimates for herself and then weak = programmers=20 are held to this estimate. The act of having the whole team agree on a=20 line-by-line basis to the estimate clarifies the team understanding, as = well as=20 allowing the opportunity for tactical reassignment of resources (for = instance,=20 shifting burden away from weaker team members to stronger).

If there are big risks that cannot be evaluated, it is your duty to = state so=20 forcefully enough that your manager does not commit to them and then = become=20 embarrassed when the risk occurs. Hopefully in such a case whatever is = needed=20 will be done to decrease the risk.

If you can convince your company to use Extreme=20 Programming, you will only have to estimate relatively small things, = and=20 this is both more fun and more productive.

How to Find Out=20 Information

The nature of what you need to know determines how you should find = it.

If you need information about concrete=20 things that are objective and easy to verify, for example = the latest=20 patch level of a software product, ask a large number of people politely = by=20 searching the internet for it or by posting on a discussion group. Don't = search=20 on the internet for anything that smacks of either opinion or subjective = interpretation: the ratio of drivel to truth is too high.

If you need general knowledge about = something=20 subjective the history of what people have thought about it, = go to=20 the library (the physical building in which books are stored). For = example, to=20 learn about math or mushrooms or mysticism, go to the library.

If you need to know how to do something = that is not=20 trivial get two or three books on the subject and read them. = You=20 might learn how to do something trivial, like install a software = package, from=20 the Internet. You can even learn important things, like good programming = technique, but you can easily spend more time searching and sorting the = results=20 and attempting to divine the authority of the results than it would take = to read=20 the pertinent part of a solid book.

If you need information that no one else = could be=20 expected to know for example, =E2=80=98does this software=20 that is brand new work on gigantic data sets?=E2=80=99, you must = still search the=20 internet and the library. After those options are completely exhausted, = you may=20 design an experiment to ascertain it.

If you want an opinion or a value judgment that takes into account = some=20 unique circumstance, talk to an expert. For instance, if you want to = know=20 whether or not it is a good idea to build a modern database management = system in=20 LISP, you should talk to a LISP expert and a database expert.

If you want to know how likely it = is=20 that a faster algorithm for a particular application exists that has not = yet=20 been published, talk to someone working in that field.

If you want to make a personal decision = that only=20 you can make like whether or not you should start a = business, try=20 putting into writing a list of arguments for and against the idea. If = that=20 fails, consider divination. Suppose you have studied the idea from all = angles,=20 have done all your homework, and worked out all the consequences and = pros and=20 cons in your mind, and yet still remain indecisive. You now must follow = your=20 heart and tell your brain to shut up. The multitude of available = divination=20 techniques are very useful for determining your own semi-conscious = desires, as=20 they each present a complete ambiguous and random pattern that your own=20 subconscious will assign meaning to.

How to Utilize People as = Information=20 Sources

Respect every person's time and balance it against your own. Asking = someone a=20 question accomplishes far more than just receiving the answer. The = person learns=20 about you, both by enjoying your presence and hearing the particular = question.=20 You learn about the person in the same way, and you may learn the answer = you=20 seek. This is usually far more important than your question.

However, the value of this diminishes the more you do it. You are, = after all,=20 using the most precious commodity a person has: their time. The benefits = of=20 communication must be weighed against the costs. Furthermore, the = particular=20 costs and benefits derived differ from person to person. I strongly = believe that=20 an executive of 100 people should spend five minutes a month talking to = each=20 person in her organization, which would be about 5% of their time. But = ten=20 minutes might be too much, and five minutes is too much if they have one = thousand employees. The amount of time you spend talking to each person = in your=20 organization depends on their role (more than their position). You = should talk=20 to your boss more than your boss's boss, but you should talk to your = boss's boss=20 a little. It may be uncomfortable, but I believe you have a duty to talk = a=20 little bit to all your superiors, each month, no matter what.

The basic rule is that everyone benefits from talking to you a little = bit,=20 and the more they talk to you, the less benefit they derive. It is your = job to=20 provide them this benefit, and to get the benefit of communicating with = them,=20 keeping the benefit in balance with the time spent.

It is important to respect your own time. If talking to someone, even = if it=20 will cost them time, will save you a great deal of time, then you should = do it=20 unless you think their time is more valuable than yours, to the tribe, = by that=20 factor.

A strange example of this is the summer intern. A summer intern in a = highly=20 technical position can't be expected to accomplish too much; they can be = expected to pester the hell out of everybody there. So why is this = tolerated?=20 Because the pestered are receiving something important from the intern. = They get=20 a chance to showoff a little. They get a chance to hear some new ideas, = maybe;=20 they get a chance to see things from a different perspective. They may = also be=20 trying to recruit the intern, but even if this is not the case there is = much to=20 gain.

You should ask people for a little bit of their wisdom and judgment = whenever=20 you honestly believe they have something to say. This flatters them and = you will=20 learn something and teach them something. A good programmer does not = often need=20 the advice of a Vice President of Sales, but if you ever do, you be sure = to ask=20 for it. I once asked to listen in on a few sales calls to better = understand the=20 job of our sales staff. This took no more than 30 minutes but I think = that small=20 effort made an impression on the sales force.

How to Document = Wisely

Life is too short to write crap nobody will read; if you write crap, = nobody=20 will read it. Therefore a little good documentation is best. Managers = often=20 don't understand this, because even bad documentation gives them a false = sense=20 of security that they are not dependent on their programmers. If someone = absolutely insists that you write truly useless documentation, say = ``yes'' and=20 quietly begin looking for a better job.

There's nothing quite as effective as putting an accurate estimate of = the=20 amount of time it will take to produce good documentation into an = estimate to=20 slacken the demand for documentation. The truth is cold and hard: = documentation,=20 like testing, can take many times longer than developing code.

Writing good documentation is, first of all, good writing. I suggest = you find=20 books on writing, study them, and practice. But even if you are a lousy = writer=20 or have poor command of the language in which you must document, the = Golden Rule=20 is all you really need: ``Do unto others as you would have them do unto = you.''=20 Take time to really think about who will be reading your documentation, = what=20 they need to get out of it, and how you can teach that to them. If you = do that,=20 you will be an above average documentation writer, and a good = programmer.

When it comes to actually documenting code itself, as opposed to = producing=20 documents that can actually be read by non-programmers, the best = programmers=20 I've ever known hold a universal sentiment: write self-explanatory code = and only=20 document code in the places that you cannot make it clear by writing the = code=20 itself. There are two good reasons for this. First, anyone who needs to = see=20 code-level documentation will in most cases be able to and prefer to = read the=20 code anyway. Admittedly, this seems easier to the experienced programmer = than to=20 the beginner. More importantly however, is that the code and the = documentation=20 cannot be inconsistent if there is no documentation. The source code can = at=20 worst be wrong and confusing. The documentation, if not written = perfectly, can=20 lie, and that is a thousand times worse.

This does not make it easier on the responsible programmer. How does = one=20 write self-explanatory code? What does that even mean? It means:

  • Writing code knowing that someone will have to read it;

  • Applying the golden rule;

  • Choosing a solution that is straightforward, even if you could get = by with=20 another solution faster;

  • Sacrificing small optimizations that obfuscate the code;

  • Thinking about the reader and spending some of your precious time = to make=20 it easier on her; and

  • Not ever using a function name like ``foo'',``bar'', or ``doIt''!=20

How to Work with Poor=20 Code

It is very common to have to work with poor quality code that someone = else=20 has written. Don't think too poorly of them, however, until you have = walked in=20 their shoes. They may have been asked very consciously to get something = done=20 quickly to meet schedule pressure. Regardless, in order to work with = unclear=20 code you must understand it. To understand it takes learning time, and = that time=20 will have to come out of some schedule, somewhere, and you must insist = on it. To=20 understand it, you will have to read the source code. You will probably = have to=20 experiment with it.

This is a good time to document, even if it is only for yourself, = because the=20 act of trying to document the code will force you to consider angles you = might=20 not have considered, and the resulting document may be useful. While = you're=20 doing this, consider what it would take to rewrite some or all of the = code.=20 Would it actually save time to rewrite some of it? Could you trust it = better if=20 you rewrote it? Be careful of arrogance here. If you rewrite it, it will = be=20 easier for you to deal with, but will it really be easier for the next = person=20 who has to read it? If you rewrite it, what will the test burden be? = Will the=20 need to re-test it outweigh any benefits that might be gained?

In any estimate that you make for work against code you didn't write, = the=20 quality of that code should affect your perception of the risk of = problems and=20 unk-unks.

It is important to remember that abstraction and encapsulation, two = of a=20 programmer's best tools, are particularly applicable to lousy code. You = may not=20 be able to redesign a large block of code, but if you can add a certain = amount=20 of abstraction to it you can obtain some of the benefits of a good = design=20 without reworking the whole mess. In particular, you can try to wall off = the=20 parts that are particularly bad so that they may be redesigned = independently.=20

How to Use Source Code=20 Control

Source code control systems let you manage projects effectively. = They're very=20 useful for one person and essential for a group. They track all changes = in=20 different versions so that no code is ever lost and meaning can be = assigned to=20 changes. One can create throw-away and debugging code with confidence = with a=20 source code control system, since the code you modify is kept carefully = separate=20 from committed, official code that will be shared with the team or = released.=20

I was late to appreciate the benefits of source code control systems = but now=20 I wouldn't live without one even on a one-person project. Generally they = are=20 necessary when you have team working on the same code base. However, = they have=20 another great advantage: they encourage thinking about the code as a = growing,=20 organic system. Since each change is marked as a new revision with a new = name or=20 number, one begins to think of the software as a visibly progressive = series of=20 improvements. I think this is especially useful for beginners.

A good technique for using a source code control system is to stay = within a=20 few days of being up-to-date at all time. Code that can't be finished in = a few=20 days is checked in, but in a way that it is inactive and will not be = called, and=20 therefore not create any problems for anybody else. Committing a mistake = that=20 slows down your teammates is a serious error; it is often taboo. =

How to Unit = Test

Unit testing, the testing of an individual piece of coded = functionality by=20 the team that wrote it, is a part of coding, not something different = from it.=20 Part of designing the code is designing how it will be tested. You = should write=20 down a test plan, even if it is only one sentence. Sometimes the test = will be=20 simple: ``Does the button look good?'' Sometimes it will be complex: = ``Did this=20 matching algorithm return precisely the correct matches?''

Use assertion checking and test drivers whenever possible. This not = only=20 catches bugs early, but is very useful later on and lets you eliminate = mysteries=20 that you would otherwise have to worry about.

The Extreme Programming developers are writing extensively on unit = testing=20 effectively; I can do no better than to recommend their writings. =

Take Breaks when = Stumped

When stumped, take a break. I sometimes meditate for 15 minutes when = stumped=20 and the problem magically unravels when I come back to it. A night's = sleep=20 sometimes does the same thing on a larger scale. It's possible that = temporarily=20 switching to any other activity may work.

How to Recognize When to Go=20 Home

Computer programming is an activity that is also a culture. The = unfortunate=20 fact is that it is not a culture that values mental or physical health = very=20 much. For both cultural/historical reasons (the need to work at night on = unloaded computers, for example) and because of overwhelming = time-to-market=20 pressure and the scarcity of programmers, computer programmers are = traditionally=20 overworked. I don't think you can trust all the stories you hear, but I = think 60=20 hours a week is common, and 50 is pretty much a minimum. This means that = often=20 much more than that is required. This is serious problem for a good = programmer,=20 who is responsible not only for themselves but their teammates as well. = You have=20 to recognize when to go home, and sometimes when to suggest that other = people go=20 home. There can't be any fixed rules for solving this problem, anymore = than=20 there can be fixed rules for raising a child, for the same = reason---every human=20 being is different.

Beyond 60 hours a week is an extraordinary effort for me, which I can = apply=20 for short periods of time (about one week), and that is sometimes = expected of=20 me. I don't know if it is fair to expect 60 hours of work from a person; = I don't=20 even know if 40 is fair. I am sure, however, that it is stupid to work = so much=20 that you are getting little out of that extra hour you work. For me = personally,=20 that's any more than 60 hours a week. I personally think a programmer = should=20 exercise noblesse oblige and shoulder a heavy burden. However, it is not = a=20 programmer's duty to be a patsy. The sad fact is programmers are often asked to be patsies in order = to put on=20 a show for somebody, for example a manager trying to impress an = executive.=20 Programmers often succumb to this because they are eager to please and = not very=20 good at saying no. There are four defenses against this:

  • Communicate as much as possible with everyone in the company so = that no one=20 can mislead the executives about what is going on,

  • Learn to estimate and schedule defensively and explicitly and give = everyone=20 visibility into what the schedule is and where it stands,

  • Learn to say no, and say no as a team when necessary, and

  • Quit if you have to.

Most programmers are good programmers, and good programmers want to = get a lot=20 done. To do that, they have to manage their time effectively. There is a = certain=20 amount of mental inertia associated with getting warmed-up to a problem = and=20 deeply involved in it. Many programmers find they work best when they = have long,=20 uninterrupted blocks of time in which to get warmed-up and concentrate. = However,=20 people must sleep and perform other duties. Each person needs to find a = way to=20 satisfy both their human rhythm and their work rhythm. Each programmer = needs to=20 do whatever it takes to procure efficient work periods, such as = reserving=20 certain days in which you will attend only the most critical meetings. =

Since I have children, I try to spend evenings with them sometimes. = The=20 rhythm that works best for me is to work a very long day, sleep in the = office or=20 near the office (I have a long commute from home to work) then go home = early=20 enough the next day to spend time with my children before they go to = bed. I am=20 not comfortable with this, but it is the best compromise I have been = able to=20 work out. Go home if you have a contagious disease. You should go home = if you=20 are thinking suicidal thoughts. You should take a break or go home if = you think=20 homicidal thoughts for more than a few seconds. You should send someone = home if=20 they show serious mental malfunctioning or signs of mental illness = beyond mild=20 depression. If you are tempted to be dishonest or deceptive in a way = that you=20 normally are not due to fatigue, you should take a break. Don't use = cocaine or=20 amphetamines to combat fatigue. Don't abuse caffeine.

How to Deal with Difficult=20 People

You will probably have to deal with difficult people. You may even be = a=20 difficult person yourself. If you are the kind of person who has a lot = of=20 conflicts with coworkers and authority figures, you should cherish the=20 independence this implies, but work on your interpersonal skills without = sacrificing your intelligence or principles.

This can be very disturbing to some programmers who have no = experience in=20 this sort of thing and whose previous life experience has taught them = patterns=20 of behavior that are not useful in the workplace. Difficult people are = often=20 inured to disagreement and they are less affected by social pressure to=20 compromise than others. The key is to respect them appropriately, which = is more=20 than you will want to but not as much as they might want.

Programmers have to work together as a team. When disagreement = arises, it=20 must be resolved somehow, it cannot be ducked for long. Difficult people = are=20 often extremely intelligent and have something very useful to say. It is = critical that you listen and understand the difficult person without = prejudice=20 caused by the person. A failure to communicate is often the basis of=20 disagreement but it can sometimes be removed with great patience. Try to = keep=20 this communication cool and cordial, and don't accept any baits for = greater=20 conflict that may be offered. After a reasonable period of trying to = understand,=20 make a decision.

Don't let a bully force you to do something you don't agree with. If = you are=20 the leader, do what you think is best. Don't make a decision for any = personal=20 reasons, and be prepared to explain the reasons for your decision. If = you are a=20 teammate with a difficult person, don't let the leader's decision have = any=20 personal impact. If it doesn't go your way, do it the other way = whole-heartedly.=20

Difficult people do change and improve. I've seen it with my own = eyes, but it=20 is very rare. However, everyone has transitory ups and downs.

One of the challenges that every programmer but especially leaders = face is=20 keeping the difficult person fully engaged. They are more prone to duck = work and=20 resist passively than others.

Chapter=EF=BF=BD3.=EF=BF=BDIntermediate

Table of Contents

Personal=20 Skills
How=20 to Stay Motivated
How=20 to be Widely Trusted
How=20 to Tradeoff Time vs. Space
How=20 to Stress Test
How=20 to Balance Brevity and Abstraction
How=20 to Learn New Skills
Learn=20 to Type
How=20 to Do Integration Testing
Communication=20 Languages
Heavy=20 Tools
How=20 to analyze data
Team=20 Skills
How=20 to Manage Development Time
How=20 to Manage Third-Party Software Risks
How=20 to Manage Consultants
How=20 to Communicate the Right Amount
How=20 to Disagree Honestly and Get Away with It
Judgement
How=20 to Tradeoff Quality Against Development Time
How=20 to Manage Software System Dependence
How=20 to Decide if Software is Too Immature
How=20 to Make a Buy vs. Build Decision
How=20 to Grow Professionally
How=20 to Evaluate Interviewees
How=20 to Know When to Apply Fancy Computer Science
How=20 to Talk to Non-Engineers

Personal = Skills

How to Stay = Motivated

It is a wonderful and surprising fact that programmers are highly = motivated=20 by the desire to create artifacts that are beautiful, useful, or nifty. = This=20 desire is not unique to programmers nor universal but it is so strong = and common=20 among programmers that it separates them from others in other roles. =

This has practical and important consequences. If programmers are = asked to do=20 something that is not beautiful, useful, or nifty, they will have low = morale.=20 There's a lot of money to be made doing ugly, stupid, and boring stuff; = but in=20 the end, fun will make the most money for the company.

Obviously, there are entire industries organized around motivational=20 techniques some of which apply here. The things that are specific to = programming=20 that I can identify are:

  • Use the best language for the job.

  • Look for opportunities to apply new techniques, languages, and=20 technologies.

  • Try to either learn or teach something, however small, in each = project.=20

Finally, if possible, measure the impact of your work in terms of = something=20 that will be personally motivating. For example, when fixing bugs, = counting the=20 number of bugs that I have fixed is not at all motivational to me, = because it is=20 independent of the number that may still exist, and is also affects the = total=20 value I'm adding to my company's customers in only the smallest possible = way.=20 Relating each bug to a happy customer, however, is personally motivating to me. =

How to be Widely = Trusted

To be trusted you must be trustworthy. You must also be visible. If = know one=20 knows about you, no trust will be invested in you. With those close to = you, such=20 as your teammates, this should not be an issue. You establish trust by = being=20 responsive and informative to those outside your department or team.=20 Occasionally someone will abuse this trust, and ask for unreasonable = favors.=20 Don't be afraid of this, just explain what you would have to give up = doing to=20 perform the favor.

Don't pretend to know something that you don't. With people that are = not=20 teammates, you may have to make a clear distinction between ``not = knowing right=20 off the top of my head'' and ``not being able to figure it out, ever.''=20

How to Tradeoff Time vs.=20 Space

You can be a good programmer without going to college, but you can't = be a=20 good intermediate programmer without knowing basic computational = complexity=20 theory. You don't need to know ``big O'' notation, but I personally = think you=20 should be able to understand the difference between = ``constant-time'',``n log=20 n'' and ``n squared''. You might be able to intuit how to tradeoff time = against=20 space without this knowledge, but in its absence you will not have a = firm basis=20 for communicating with your colleagues.

In designing or understanding an algorithm, the amount of time it = takes to=20 run is sometimes a function of the size of the input. When that is true, = we can=20 say an algorithm's worst/expected/best-case running time is ``n log n'' = if it is=20 proportional to the size ($n$) times the logarithm of the size. The = notation and=20 way of speaking can be also be applied to the space taken up by a data=20 structure.

To me, computational complexity theory is beautiful and as profound = as=20 physics---and a little bit goes a long way!

Time (processor cycles) and space (memory) can be traded off against = each=20 other. Engineering is about compromise, and this is a fine example. It = is not=20 always systematic. In general, however, one can save space by encoding = things=20 more tightly, at the expense of more computation time when you have to = decode=20 them. You can save time by caching, that is, spending space to store a = local=20 copy of something, at the expense of having to maintain the consistency = of the=20 cache. You can sometimes save time by maintaining more information in a = data=20 structure. This usually cost a small amount of space but may complicate = the=20 algorithm.

Improving the space/time tradeoff can often change one or the other=20 dramatically. However, before you work on this you should ask yourself = if what=20 you are improving is really the thing that needs the most improvement. = It's fun=20 to work on an algorithm, but you can't let that blind you to the cold = hard fact=20 that improving something that is not a problem will not make any = noticeable=20 difference and will create a test burden.

Memory on modern computers appears cheap, because unlike processor = time, you=20 can't see it being used until you hit the wall; but then failure is=20 catastrophic. There are also other hidden costs to using memory, such as = your=20 effect on other programs that must be resident, and the time to allocate = and=20 deallocate it. Consider this carefully before you trade away space to = gain=20 speed.

How to Stress = Test

Stress testing is fun. At first it appears that the purpose of stress = testing=20 is to find out if the system works under a load. In reality, it is = common that=20 the system does work under a load but fails to work in some way when the = load is=20 heavy enough. I call this hitting the wall or = bonking[1]. There may be some exceptions, but there = is almost=20 always a =E2=80=98wall=E2=80=99. The purpose = of stress testing is to=20 figure out where the wall is, and then figure out how to move the wall = further=20 out.

A plan for stress testing should be developed early in the project, = because=20 it often helps to clarify exactly what is expected. Is two seconds for a = web=20 page request a miserable failure or a smashing success? Is 500 = concurrent users=20 enough? That, of course, depends, but one must know the answer when = designing=20 the system that answers the request. The stress test needs to model = reality well=20 enough to be useful. It isn't really possible to simulate 500 erratic = and=20 unpredictable humans using a system concurrently very easily, but one = can at=20 least create 500 simulations and try to model some part of what they = might do.=20

In stress testing, start out with a light load and load the system = along some=20 dimension---such as input rate or input size---until you hit the wall. = If the=20 wall is too close to satisfy your needs, figure out which resource is = the=20 bottleneck (there is usually a dominant one.) Is it memory, processor, = I/O,=20 network bandwidth, or data contention? Then figure out how you can move = the=20 wall. Note that moving the wall, that is, increasing the maximum load = the system=20 can handle, might not help or might actually hurt the performance of a = lightly=20 loaded system. Usually performance under heavy load is more important = than=20 performance under a light load.

You may have to get visibility into several different dimensions to = build up=20 a mental model of it; no single technique is sufficient. For instance, = logging=20 often gives a good idea of the wall-clock time between two events in the = system,=20 but unless carefully constructed, doesn't give visibility into memory=20 utilization or even data structure size. Similarly, in a modern system, = a number=20 of computers and many software systems may be cooperating. Particularly = when you=20 are hitting the wall (that is, the performance is non-linear in the size = of the=20 input) these other software systems may be a bottleneck. Visibility into = these=20 systems, even if only measuring the processor load on all participating=20 machines, can be very helpful.

Knowing where the wall is is essential not only to moving the wall, = but also=20 to providing predictability so that the business can be managed = effectively.=20

How to Balance Brevity and=20 Abstraction

Abstraction is key to programming. You should carefully choose how = abstract=20 you need to be. Beginning programmers in their enthusiasm often create = more=20 abstraction than is really useful. One sign of this is if you create = classes=20 that don't really contain any code and don't really do anything except = serve to=20 abstract something. The attraction of this is understandable but the = value of=20 code brevity must be measured against the value of abstraction. = Occasionally,=20 one sees a mistake made by enthusiastic idealists: at the start of the = project a=20 lot of classes are defined that seem wonderfully abstract and one may = speculate=20 that they will handle every eventuality that may arise. As the project=20 progresses and fatigue sets in, the code itself becomes messy. Function = bodies=20 become longer than they should be. The empty classes are a burden to = document=20 that is ignored when under pressure. The final result would have been = better if=20 the energy spent on abstraction had been spent on keeping things short = and=20 simple. This is a form of speculative = programming. I=20 strongly recommend the article ``Succinctness is Power'' by Paul = Graham[PGSite].

There is a certain dogma associated with useful techniques such as information hiding and object = oriented=20 programming that are sometimes taken too far. These techniques let = one code=20 abstractly and anticipate change. I personally think, however, that you = should=20 not produce much speculative code. For example, it is an accepted style = to hide=20 an integer variable on an object behind mutators and accessors, so that = the=20 variable itself is not exposed, only the little interface to it. This = does allow=20 the implementation of that variable to be changed without affecting the = calling=20 code, and is perhaps appropriate to a library writer who must publish a = very=20 stable API. But I don't think the benefit of this outweighs the cost of = the=20 wordiness of it when my team owns the calling code and hence can recode = the=20 caller as easily as the called. Four or five extra lines of code is a = heavy=20 price to pay for this speculative benefit.

Portability poses a similar problem. Should code be portable to a = different=20 computer, compiler, software system or platform, or simply easily = ported? I=20 think a non-portable, short-and-easily-ported piece of code is better = than a=20 long portable one. It is relatively easy and certainly a good idea to = confine=20 non-portable code to designated areas, such as a class that makes = database=20 queries that are specific to a given DBMS.

How to Learn New = Skills

Learning new skills, especially non-technical ones, is the greatest = fun of=20 all. Most companies would have better morale if they understood how much = this=20 motivates programmers.

Humans learn by doing. Book-reading and class-taking are useful. But = could=20 you have any respect for a programmer who had never written a program? = To learn=20 any skill, you have to put yourself in a forgiving position where you = can=20 exercise that skill. When learning a new programming language, try to do = a small=20 project it in before you have to do a large project. When learning to = manage a=20 software project, try to manage a small one first.

A good mentor is no replacement for doing things yourself, but is a = lot=20 better than a book. What can you offer a potential mentor in exchange = for their=20 knowledge? At a minimum, you should offer to study hard so their time = won't be=20 wasted.

Try to get your boss to let you have formal training, but understand = that it=20 often not much better than the same amount of time spent simply playing = with the=20 new skill you want to learn. It is, however, easier to ask for training = than=20 playtime in our imperfect world, even though a lot of formal training is = just=20 sleeping through lectures waiting for the dinner party.

If you lead people, understand how they learn and assist them by = assigning=20 them projects that are the right size and that exercise skills they are=20 interested in. Don't forget that the most important skills for a = programmer are=20 not the technical ones. Give your people a chance to play and practice = courage,=20 honesty, and communication.

Learn to Type

Learn to touch-type. This is an intermediate skill because writing = code is so=20 hard that the speed at which you can type is irrelevant and can't put = much of a=20 dent in the time it takes to write code, no matter how good you are. = However, by=20 the time you are an intermediate programmer you will probably spend a = lot of=20 time writing natural language to your colleagues and others. This is a = fun test=20 of your commitment; it takes dedicated time that is not much fun to = learn=20 something like that. Legend has it that when Michael Tiemann[2] was at MCC people would stand outside his = door to=20 listen to the hum generated by his keystrokes which were so rapid as to = be=20 indistinguishable.

How to Do Integration=20 Testing

Integration testing is the testing of the integration of various = components=20 that have been unit tested. Integration is expensive and it comes out in = the=20 testing. You must include time for this in your estimates and your = schedule.=20

Ideally you should organize a project so that there is not a phase at = the end=20 where integration must explicitly take place. It is far better to = gradually=20 integrate things as they are completed over the course of the project. = If it is=20 unavoidable estimate it carefully.

Communication = Languages

There are some languages, that is, formally defined syntactic = systems, that=20 are not programming languages but communication=20 languages---they are designed specifically to facillitate = communication=20 through standardization. In 2003 the most important of these are UML, = XML, and=20 SQL. You should have some familiarity with all of these so that you can=20 communicate well and decide when to use them.

UML is a rich formal system for making drawings that describe = designs. It's=20 beauty lines in that is both visual and formal, capable of conveying a = great=20 deal of information if both the author and the audience know UML. You = need to=20 know about it because designs are sometimes communicated in it. There = are very=20 helpful tools for making UML drawings that look very professional. In a = lot of=20 cases UML is too formal, and I find myself using a simpler boxes and arrows style for design drawings. But = I'm fairly=20 sure UML is at least as good for you as studying Latin.

XML is a standard for defining new standards. It is not a solution to data interchange = problems,=20 though you sometimes see it presented as if it was. Rather, it is a = welcome=20 automation of the most boring part of data interchange, namely, = structuring the=20 representation into a linear sequence and parsing back into a structure. = It=20 provides some nice type- and correctness-checking, though again only a = fraction=20 of what you are likely to need in practicen.

SQL is a very powerful and rich data query and manipulation language = that is=20 not quite a programming language. It has many variations, typically = quite=20 product-dependent, which are less important than the standardized core. = SQL is=20 the lingua franca of relational databases. You = may or may=20 not work in any field that can benefit from an understanding of = relational=20 databases, but you should have a basic understanding of them and they = syntax and=20 meaning of SQL.

Heavy Tools

As our technological culture progresses, software technology moves = from=20 inconceivable, to research, to new products, to standardized products, = to widely=20 available and inexpensive products. These heavy tools can pull great = loads, but=20 can be intimidating and require a large investment in understanding. The = intermediate programmer has to know how to manage them and when they = should be=20 used or considered.

To my mind right some of the best heavy tools are:

  • Relational Databases,

  • Full-text Search Engines,

  • Math libraries,

  • OpenGL,

  • XML parsers, and

  • Spreadsheets.

How to analyze = data

--

Data analysis is a process in the early stages of software = development, when=20 you examine a business activity and find the requirements to convert it = into a=20 software application. This is a formal definition, which may lead you to = believe=20 that data analysis is an action that you should better leave to the = systems=20 analysts, while you, the programmer, should focus on coding what = somebody else=20 has designed. If we follow strictly the software engineering paradigm, = it may be=20 correct. Experienced programmers become designers and the sharpest = designers=20 become business analysts, thus being entitled to think about all the = data=20 requirements and give you a well defined task to carry out. This is not = entirely=20 accurate, because data is the core value of every programming activity. = Whatever=20 you do in your programs, you are either moving around or modifying data. = The=20 business analyst is analyzing the needs in a larger scale, and the = software=20 designer is further squeezing such scale so that, when the problem lands = on your=20 desk, it seems that all you need to do is to apply clever algorithms and = start=20 moving existing data.

Not so.

No matter at which stage you start looking at it, data is the main = concern of=20 a well designed application. If you look closely at how a business = analyst gets=20 the requirements out of the customer?s requests, you?ll realize that = data plays=20 a fundamental role. The analyst creates so called Data Flow Diagrams, = where all=20 data sources are identified and the flow of information is shaped. = Having=20 clearly defined which data should be part of the system, the designer = will shape=20 up the data sources, in terms of database relations, data exchange = protocols,=20 and file formats, so that the task is ready to be passed down to the = programmer.=20 However, the process is not over yet, because you ? the programmer ? = even after=20 this thorough process of data refinement, are required to analyze data = to=20 perform the task in the best possible way. The bottom line of your task = is the=20 core message of Niklaus Wirth, the father of several languages. = ?Algorithms +=20 Data Structures =3D Programs.? There is never an algorithm standing = alone, doing=20 something to itself. Every algorithm is supposed to do something to at = least one=20 piece of data.

Therefore, since algorithms don't spin their wheels in a vacuum, you = need to=20 analyze both the data that somebody else has identified for you and the = data=20 that is necessary to write down your code. A trivial example will make = the=20 matter clearer. You are implementing a search routine for a library. = According=20 to your specifications, the user can select books by a combination of = genre,=20 author, title, publisher, printing year, and number of pages. The = ultimate goal=20 of your routine is to produce a legal SQL statement to search the = back-end=20 database. Based on these requirements, you have several choices: check = each=20 control in turn, using a "switch" statement, or several "if" ones; make = an array=20 of data controls, checking each element to see if it is set; create (or = use) an=20 abstract control object from which inherit all your specific controls, = and=20 connect them to an event-driven engine. If your requirements include = also tuning=20 up the query performance, by making sure that the items are checked in a = specific order, you may consider using a tree of components to build = your SQL=20 statement. As you can see, the choice of the algorithm depends on the = data you=20 decide to use, or to create. Such decisions can make all the difference = between=20 an efficient algorithm and a disastrous one. However, efficiency is not = the only=20 concern. You may use a dozen named variables in your code and make it as = efficient as it can ever be. But such a piece of code might not be = easily=20 maintainable. Perhaps choosing an appropriate container for your = variables could=20 keep the same speed and in addition allow your colleagues to understand = the code=20 better when they look at it next year. Furthermore, choosing a well = defined data=20 structure may allow them to extend the functionality of your code = without=20 rewriting it. In the long run, your choices of data determines how long = your=20 code will survive after you are finished with it. Let me give you = another=20 example, just some more food for thought. Let's suppose that your task = is to=20 find all the words in a dictionary with more than three anagrams, where = an=20 anagram must be another word in the same dictionary. If you think of it = as a=20 computational task, you will end up with an endless effort, trying to = work out=20 all the combinations of each word and then comparing it to the other = words in=20 the list. However, if you analyze the data at hand, you'll realize that = each=20 word may be represented by a record containing the word itself and a = sorted=20 array of its letters as ID. Armed with such knowledge, finding anagrams = means=20 just sorting the list on the additional field and picking up the ones = that share=20 the same ID. The brute force algorithm may take several days to run, = while the=20 smart one is just a matter of a few seconds. Remember this example the = next time=20 you are facing an intractable problem.

Team=20 Skills

How to Manage Development=20 Time

To manage development time, maintain a concise and up-to-date project = plan. A=20 project plan is an estimate, a schedule, a set of milestones for marking = progress, and an assignment of your team or your own time to each task = on the=20 estimate. It should also include other things you have to remember to = do, such=20 as meeting with the quality assurance people, preparing documentation, = or=20 ordering equipment. If you are on a team, the project plan should be a=20 consensual agreement, both at the start and as you go.

The project plan exists to help make decisions, not to show how = organized you=20 are. If the project plan is either too long or not up-to-date, it will = be=20 useless for making decisions. In reality, these decisions are about = individual=20 persons. The plan and your judgment let you decide if you should shift = tasks=20 from one person to another. The milestones mark your progress. If you = use a=20 fancy project planning tool, do not be seduced into creating a Big = Design Up=20 Front (BDUF) for the project, but use it maintain concision and = up-to-dateness.=20

If you miss a milestone, you should take immediate action such as = informing=20 your boss that the scheduled completion of that project has slipped by = that=20 amount. The estimate and schedule could never have been perfect to begin = with;=20 this creates the illusion that you might be able to make up the days you = missed=20 in the latter part of the project. You might. But it is just as likely = that you=20 have underestimated that part as that you have overestimated it. = Therefore the=20 scheduled completion of the project has already slipped, whether you = like it or=20 not.

Make sure you plan includes time for: internal team meetings, demos,=20 documentation, scheduled periodic activities, integration testing, = dealing with=20 outsiders, sickness, vacations, maintenance of existing products, and=20 maintenance of the development environment. The project plan can serve = as a way=20 to give outsiders or your boss a view into what you or your team is = doing. For=20 this reason it should be short and up-to-date.

How to Manage Third-Party = Software=20 Risks

A project often depends on software produced by organizations that it = does=20 not control. There are great risks associated with third party software = that=20 must be recognized by everyone involved.

Never, ever, rest any hopes on vapor. Vapor is any alleged software that has been = promised but is=20 not yet available. This is the surest way to go out of business. It is = unwise to=20 be merely skeptical of a software company's promise to release a certain = product=20 with a certain feature at a certain date; it is far wiser to ignore it=20 completely and forget you ever heard it. Never let it be written down in = any=20 documents used by your company.

If third-party software is not vapor, it is still risky, but at least = it is a=20 risk that can be tackled. If you are considering using third-party = software, you=20 should devote energy early on to evaluating it. People might not like to = hear=20 that it will take two weeks or two months to evaluate each of three = products for=20 suitability, but it has to be done as early as possible. The cost of = integrating=20 cannot be accurately estimated without a proper evaluation.

Understanding the suitability of existing third party software for a=20 particular purpose is very tribal knowledge. It is very subjective and = generally=20 resides in experts. You can save a lot of time if you can find those = experts.=20 Often times a project will depend on a third-party software system so = completely=20 that if the integration fails the project will fail. Express risks like = that=20 clearly in writing in the schedule. Try to have a contingency plan, such = as=20 another system that can be used or the ability to write the = functionality=20 yourself if the risk can't be removed early. Never let a schedule depend = on=20 vapor.

How to Manage = Consultants

Use consultants, but don't rely on them. They are wonderful people = and=20 deserve a great deal of respect. Since they get to see a lot of = different=20 projects, they often know more about specific technologies and even = programming=20 techniques than you will. The best way to use them is as educators = in-house that=20 can teach by example.

However, they usually cannot become part of the team in the same = sense that=20 regular employees are, if only because you may not have enough time to = learn=20 their strengths and weaknesses. Their financial commitment is much = lower. They=20 can move more easily. They may have less to gain if the company does = well. Some=20 will be good, some will be average, and some will be bad, but hopefully = your=20 selection of consultants will not be as careful as your selection of = employees,=20 so you will get more bad ones.

If consultants are going to write code, you must review it carefully = as you=20 go along. You cannot get to the end of the a project with the risk of a = large=20 block of code that has not been reviewed. This is true of all team = members,=20 really, but you will usually have more knowledge of the team members = closer to=20 you.

How to Communicate the Right=20 Amount

Carefully consider the cost of a meeting; it costs its duration multiplied by the number of=20 participants. Meetings are sometimes necessary, but smaller = is=20 usually better. The quality of communication in small meetings is = better, and=20 less time overall is wasted. If any one person is bored at a meeting = take this=20 as a sing, that the meeting should be smaller.

Everything possible should be done to encourage informal = communication. More=20 useful work is done during lunches with colleagues than during any other = time.=20 It is a shame that more companies do not recognize nor support this = fact.=20

How to Disagree Honestly and = Get Away with=20 It

Disagreement is a great opportunity to make a good decision, but it = should be=20 handled delicately. Hopefully you feel that you have expressed your = thoughts=20 adequately and been heard before the decision is made. In that case = there is=20 nothing more to say, and you should decide whether you will stand behind = the=20 decision even though you disagree with it. If you can support this = decision even=20 though you disagree, say so. This shows how valuable you are because you = are=20 independent and are not a yes-man, but respectful of the decision and a = team=20 player.

Sometimes a decision that you disagree with will be made when the = decision=20 makers did not have the full benefit of you opinion. You should then = evaluate=20 whether to raise the issue on the basis of the benefit to the company or = tribe.=20 If it is a small mistake in your opinion, it may not be worth = reconsidering. If=20 it is a large mistake in you opinion, then of course you must present an = argument.

Usually, this is not a problem. In some stressful circumstances and = with some=20 personality types this can lead to things being taken personally. For = instance,=20 some very good programmers lack the confidence needed to challenge a = decision=20 even when they have good reason to believe it is wrong. In the worst of=20 circumstances the decision maker is insecure and takes it as a personal=20 challenge to their authority. It is best to remember that in such = circumstances=20 people react with the reptilian part of their brains. You should present = your=20 argument in private, and try to show how new knowledge changes the basis = on=20 which the decision was made.

Whether the decision is reversed or not, you must remember that you = will=20 never be able to say =E2=80=98I told you = so!=E2=80=99 since the=20 alternate decision was fully explored.

Judgement

How to Tradeoff Quality = Against=20 Development Time

Software development is always a compromise between what the project = does and=20 getting the project done. But you may be asked to tradeoff quality to = speed the=20 deployment of a project in a way that offends your engineering = sensibilities or=20 business sensibilities. For example, you may be asked to do something = that is a=20 poor software engineering practice and that will lead to a lot of = maintenance=20 problems.

If this happens your first responsibility is to inform your team and = to=20 clearly explain the cost of the decrease in quality. After all, your=20 understanding of it should be much better than your boss's = understanding. Make=20 it clear what is being lost and what is being gained, and at what cost = the lost=20 ground will be regained in the next cycle. In this, the visibility = provided by a=20 good project plan should be helpful. If the quality tradeoff affects the = quality=20 assurance effort, point that out (both to your boss and quality = assurance=20 people). If the quality tradeoff will lead to more bugs being reported = after the=20 quality assurance period, point that out.

If she still insists you should try to isolate the shoddiness into = particular=20 components that you can plan to rewrite or improve in the next cycle. = Explain=20 this to your team so that they can plan for it.

NinjaProgrammer at Slashdot sent in this gem:

Remember that a good design = will be=20 resillient against poor code implementations. If good interfaces and=20 abstractions exist throughout the code, then the eventual rewrites = will be far=20 more painless. If it is hard to write clear code that is hard to fix, = consider=20 what is wrong with the core design that is causing this. =

How to Manage Software System=20 Dependence

Modern software systems tend to depend on a large number of = components that=20 may not be directly under your control. This increases productivity = through=20 synergy and reuse. However, each component brings with it some problems: =

  • How will you fix bugs in the component?

  • Does the component restrict you to particular hardware or software = systems?=20

  • What will you do if the component fails completely? =

It is always best to encapsulate the component in some way so that it = is=20 isolated and so that it can be swapped out. If the component proves to = be=20 completely unworkable, you may be able to get a different one, but you = may have=20 to write your own. Encapsulation is not portability, but it makes = porting=20 easier, which is almost as good.

Having the source code for a component decreases the risk by a factor = of=20 four. With source code, you can evaluate it easier, debug it easier, = find=20 workarounds easier, and make fixes easier. If you make fixes, you should = give=20 them to the owner of the component and get the fixes incorporated into = an=20 official release; otherwise you will uncomfortably have to maintain an=20 unofficial version .

How to Decide if Software is = Too=20 Immature

Using software other people wrote is one of the most effective ways = to=20 quickly build a solid system. It should not be discouraged, but the = risks=20 associated with it must be examined. One of the biggest risks is the = period of=20 bugginess and near inoperability that is often associated with software = before=20 it matures, through usage, into a usable product. Before you consider=20 integrating with a software system, whether created in house or by a = third=20 party, it is very important to consider if it is really mature enough to = be=20 used. Here are ten questions you should ask yourself about it:

  1. Is it vapor? (Promises are very immature).

  2. Is there an accessible body of lore about the software?

  3. Are you the first user?

  4. Is there a strong incentive for continuation?

  5. Has it had a maintenance effort?

  6. Will it survive defection of the current maintainers?

  7. Is there a seasoned alternative at least half as good?

  8. Is it known to your tribe or company?

  9. Is it desirable to your tribe or company?

  10. Can you hire people to work on it even if it is bad? =

A little consideration of these criteria demonstrates the great value = of=20 well-established free software and open-source software in reducing risk = to the=20 entrepreneur.

How to Make a Buy vs. Build=20 Decision

An entrepreneurial company or project that is trying to accomplish = something=20 with software has to constantly make so-called buy = vs.=20 build decisions. This turn of phrase is unfortunate in two ways: it = seems to=20 ignore open-source and free software which is not necessarily bought. Even more importantly, it = should perhaps=20 be called an obtain and integrate = vs. build here and integrate decision = because the=20 cost of integration must be considered. This requires a great = combination of=20 business, management, and engineering savvy.

  • How well do your needs match those for which it was designed?

  • What portion of what you buy will you need?

  • What is the cost of evaluating the integration?

  • What is the cost of integration?

  • What is the cost of evaluating the integration?

  • Will buying increase or decrease long term maintenance costs?

  • Will building it put you in a business position you don't want to = be in?=20

You should think twice before building something that is big enough = to serve=20 as the basis for an entire other business. Such ideas are often proposed = by=20 bright and optimistic people that will have a lot to contribute to your = team. If=20 their idea is compelling, you may wish to change your business plan; but = do not=20 invest in a solution bigger than your own business without conscious = thought.=20

After considering these questions, you should perhaps prepare two = draft=20 project plans, one for building and one for buying. This will force you = to=20 consider the integration costs. You should also consider the long term=20 maintenance costs of both solutions. To estimate the integration costs, = you will=20 have to do a thorough evaluation of the software before you buy it. If = you can't=20 evaluate it, you will assume an unreasonable risk in buying it and you = should=20 decide against buying that particular product. If there are several buy=20 decisions under consideration, some energy will have to be spent = evaluating=20 each.

How to Grow=20 Professionally

Assume responsibility in excess of your authority. Play the role that = you=20 desire. Express appreciation for people's contribution to the success of = the=20 larger organization, as well as things as that help you personally.

If you want to become a team leader, instigate the formation of = consensus. If=20 you want to become a manager, take responsibility for the schedule. You = can=20 usually do this comfortably while working with a leader or a manager, = since this=20 frees them up to take greater responsibility. If that is too much to = try, do it=20 a little at a time.

Evaluate yourself. If you want to become a better programmer, ask = someone you=20 admire how you can become like them. You can also ask your boss, who = will know=20 less but have a greater impact on your career.

Plan ways to learn new skills, both the trivial technical kind, like = learning=20 a new software system, and the hard social kind, like writing well, by=20 integrating them into your work.

How to Evaluate=20 Interviewees

Evaluating potential employees is not given the energy it deserves. A = bad=20 hire, like a bad marriage, is terrible. A significant portion of = everyone's=20 energy should be devoted to recruitment, though this is rarely done. =

There are different interviewing styles. Some are torturous, designed = to put=20 the candidate under a great deal of stress. This serves a very valuable = purpose=20 of possibly revealing character flaws and weaknesses under stress. = Candidates=20 are no more honest with interviewers than they are with themselves, and = the=20 human capacity for self-deception is astonishing.

You should, at a minimum, give the candidate the equivalent of an = oral=20 examination on the technical skills for two hours. With practice, you = will be=20 able to quickly cover what they know and quickly retract from what they = don't=20 know to mark out the boundary. Interviewees will respect this. I have = several=20 times heard interviewees say that the quality of the examination was one = of=20 their motivations for choosing a company. Good people want to be hired = for their=20 skills, not where they worked last or what school they went to or some = other=20 inessential characteristic.

In doing this, you should also evaluate their ability to learn, which = is far=20 more important than what they know. You should also watch for the whiff = of=20 brimstone that is given off by difficult people. You may be able to = recognize it=20 by comparing notes after the interview, but in the heat of the interview = it is=20 hard to recognize. How well people communicate and work with people is = more=20 important than being up on the latest programming language.

A reader has had good luck using a =E2=80=98take-home=E2=80=99 test=20 for interviewees. This has the advantage that can uncover the = interviewee that=20 can present themselves well but can't really code---and there are many = such=20 people. I personally have not tried this technique, but it sounds = sensible.

Finally, interviewing is also a process of selling. You should be = selling=20 your company or project to the candidate. However, you are talking to a=20 programmer, so don't try to color the truth. Start off with the bad = stuff, then=20 finish strong with the good stuff.

How to Know When to Apply = Fancy Computer=20 Science

There is a body of knowledge about algorithms, data structures, = mathematics,=20 and other gee-whiz stuff that most programmers know about but rarely = use. In=20 practice, this wonderful stuff is too complicated and generally = unnecessary.=20 There is no point in improving an algorithm when most of your time is = spent=20 making inefficient database calls, for instance. An unfortunate amount = of=20 programming consists of getting systems to talk to each other and using = very=20 simple data structures to build a nice user interface.

When is high technology the appropriate technology? When should you = crack a=20 book to get something other than a run-of-the-mill algorithm? It is = sometimes=20 useful to do this but it should be evaluated carefully.

The three most important considerations for the potential computer = science=20 technique are:

  • Is it well encapsulated so that the risk to other systems is low = and the=20 overall increase in complexity and maintenance cost is low?

  • Is the benefit startling (for example, a factor of two in a mature = system=20 or a factor of ten in a new system)?

  • Will you be able to test and evaluate it effectively? =

If a well-isolated algorithm that uses a slightly fancy algorithm can = decrease hardware cost or increase performance by a factor of two across = an=20 entire system, then it would be criminal not to consider it. One of the = keys to=20 arguing for such an approach is to show that the risk is really quite = low, since=20 the proposed technology has probably been well studied, the only issue = is the=20 risk of integration. Here a programmer's experience and judgment can = truly=20 synergize with the fancy technology to make integration easy.

How to Talk to=20 Non-Engineers

Engineers and programmers in particular are generally recognized by = popular=20 culture as being different from other people. This implies that other = people are=20 different from us. This is worth bearing in mind when communicating with = non-engineers; you should always understand the audience.

Non-engineers are smart, but not as grounded in creating technical = things as=20 we are. We make things. They sell things and handle things and count = things and=20 manage things, but they are not experts on making things. They are not = as good=20 at working together on teams as engineers are (there are no doubt=20 exceptions.)[3] Their social skills are generally as good = as or=20 better than engineers in non-team environments, but their work does not = always=20 demand that they practice the kind of intimate, precise communication = and=20 careful subdivisions of tasks that we do.

Non-engineers may be too eager to please and they may be intimidated = by you.=20 Just like us, they may say =E2=80=98yes=E2=80=99 without really meaning=20 it to please you or because they are a little scared of you, and then = not stand=20 behind their words.

Non-programmers can understand technical things but they do not have = the=20 thing that is so hard even for us---technical judgment. They do = understand how=20 technology works, but they cannot understand why a certain approach = would take=20 three months and another one three days. (After all, programmers are = anecdotally=20 horrible at this kind of estimation as well.) This represents a great=20 opportunity to synergize with them.

When talking to your team you will, without thinking, use a sort of=20 shorthand, an abbreviated language that is effective because you will = have much=20 shared experience about technology in general and your product in = particular. It=20 takes some effort not to use this shorthand with those that don't have = that=20 shared experience, especially when members of your own team are present. = This=20 vocabulary create a wall between you and those that do not share it, = and, even=20 worse, wastes their time.

With your team, the basic assumptions and goals do not need to be = restated=20 often, and most conversation focuses on the details. With outsiders, it = must be=20 the other way around. They may not understand things you take for = granted. Since=20 you take them for granted and don't repeat them, you can leave a = conversation=20 with an outsider thinking that you understand each other when really = there is a=20 large misunderstanding. You should assume that you will miscommunicate = and watch=20 carefully to find this miscommunication. Try to get them to summarize or = paraphrase what you are saying to make sure they understand. If you have = the=20 opportunity to meet with them often, spend a little bit of time asking = if you=20 you are communicating effectively, and how you can do it better. If = there is a=20 problem in communication, seek to alter your own practices before = becoming=20 frustrated with theirs.

I love working with non-engineers. It provides great opportunities to = learn=20 and to teach. You can often lead by example, in terms of the clarity of = your=20 communication. Engineers are trained to bring order out of chaos, to = bring=20 clarity out of confusion, and non-engineers like this about us. Because = we have=20 technical judgment and can usually understand business issues, we can = often find=20 a simple solution to a problem.

Often non-engineers propose solutions that they think will make it = easier on=20 us out of kindness and a desire to do the right thing, when in fact a = much=20 better overall solution exists which can only be seen by synergizing the = outsiders view with your technical judgment. I personally like Extreme=20 Programming because it addresses this inefficiency; by marrying the = estimation=20 quickly to the idea, it makes it easier to find the idea that is the = best=20 combination of cost and benefit.



[1] =E2=80=9Cto = hit=E2=80=9D

Chapter=EF=BF=BD4.=EF=BF=BDAdvanced

=

Table of Contents

Technological=20 Judgment
How=20 to Tell the Hard From the Impossible
How=20 to Utilize Embedded Languages
Choosing=20 Languages
Compromising=20 Wisely
How=20 to Fight Schedule Pressure
How=20 to Understand the User
How=20 to Get a Promotion
Serving=20 Your Team
How=20 to Develop Talent
How=20 to Choose What to Work On
How=20 to Get the Most From Your Teammates
How=20 to Divide Problems Up
How=20 to Handle Boring Tasks
How=20 to Gather Support for a Project
How=20 to Grow a System
How=20 to Communicate Well
How=20 to Tell People Things They Don't Want to Hear
How=20 to Deal with Managerial Myths
How=20 to Deal with Organizational Chaos

Technological=20 Judgment

How to Tell the Hard From the=20 Impossible

It is our job to do the hard and discern the impossible. From the = point of=20 view of most working programmers, something is impossible if either it = cannot be=20 grown from a simple system or it cannot be estimated. By this definition = what is=20 called research is impossible. A large volume of mere=20 work is hard, but not necessarily impossible.

The distinction is not facetious because you may very well be asked = to do=20 what is practically impossible, either from a scientific point of view = or a=20 software engineering point of view. It then becomes your job to help the = entrepreneur find a reasonable solution which is merely=20 hard and gets most of what they wanted. A solution is merely = hard=20 when it can be confidently scheduled and the risks are understood.

It is impossible to satisfy a vague requirement, such as = =E2=80=98Build a system that will compute the most attractive hair = style and=20 color for any person.=E2=80=99 If the requirement can be made = more crisp, it will=20 often become merely hard, such as =E2=80=98Build a = system to compute=20 an attractive hair style and color for a person, allow them to preview = it and=20 make changes, and have the customer satisfaction based on the original = styling=20 be so great that we make a lot of money.=E2=80=99 If there is not = crisp=20 definition of success, you will not succeed.

How to Utilize Embedded=20 Languages

Embedding a programming language into a system has an almost erotic=20 fascination to a programmer. It is one of the most creative acts that = can be=20 performed. It makes the system tremendously powerful. It allows you to = exercise=20 her most creative and Promethean skills. It makes the system into your = friend.=20

The best text editors in the world all have embedded languages. This = can be=20 used to the extent that the intended audience can master the language. = Of=20 course, use of the language can be made optional, as it is in text = editors, so=20 that initiates can use it and no one else has to.

I and many other programmers have fallen into the trap of creating = special=20 purpose embedded languages. I fell into it twice. There already exist = many=20 languages designed specifically to be embedded languages. You should = think twice=20 before creating a new one.

The real question to ask oneself before embedding a language is: Does = this=20 work with or against the culture of my audience? If you intended = audience is=20 exclusively non-programmers, how will it help? If your intended audience = is=20 exclusively programmers, would they prefer an applications programmers = interface=20 (API)? And what language will it be? Programmers don't want to learn a = new=20 language that is narrowly used; but if it meshes with their culture they = will=20 not have to spend much time learning it. It is a joy to create a new = language.=20 But we should not let that blind us to the needs of the user. Unless you = have=20 some truly original needs and ideas, why not use an existing language so = that=20 you can leverage the familiarity users already have with it?

Choosing = Languages

The solitary programmer that loves his work (a hacker) can choose the = best=20 language for the task. Most working programmers have very little control = of the=20 language they will use. Generally, this issue is dictated by = pointy-haired=20 bosses who are making a political decision, rather than a technological=20 decision, and lack the courage to promote an unconventional tool even = when they=20 know, often with firsthand knowledge, that the less accepted tool is = best. In=20 other cases the very real benefit of unity among the team, and to some = extent=20 with a larger community, precludes choice on the part of the individual. = Often=20 managers are driven by the need to be able to hire programmers with = experience=20 in a given language. No doubt they are serving what they perceive to be = the best=20 interests of the project or company, and must be respected for that. = However, I=20 personally believe this the most wasteful and erroneous common practice = you are=20 likely to encounter.

But of course, things are never one-dimensional. Even if a core = language is=20 mandated and beyond your control, it is often the case that tools and = other=20 programs can and should be written in a different language. If a = language is to=20 be embedded (and you should always consider it!) the choice of language = will=20 depend a lot on the culture of the users. One should take advantage of = this to=20 serve your company or project by using the best language for the job, = and in so=20 doing make work more interesting.

Programming languages should really be called notations in that learning one is not at all as = difficult as=20 learning a natural language. To beginners and to some outsiders = ``learning a new=20 language'' seems a daunting task; but after you have three under your = belt it's=20 really just a question of becoming familiar with the available = libraries. One=20 tends to think of a large system that has components in three or four = languages=20 as a messy hodgepodge; but I argue that such a system is in many cases = stronger=20 than a one-language system in several ways:

  • There is necessarily loose coupling between the components that are = written=20 in different notations (though maybe not clean interfaces),

  • You can evolve to a new language/platform easily by rewriting each=20 component individually,

  • Its possible that some of the modules are actually up-to-date.=20

Some of these effects may only be psychological; but psychology = matters. In=20 the end the costs of language tyranny outweigh any advantage that it = provides.=20

Compromising=20 Wisely

How to Fight Schedule=20 Pressure

Time-to-market pressure is the pressure to deliver a good product = quickly. It=20 is good because it reflects a financial reality, and is healthy up to a = point.=20 Schedule pressure is the pressure to deliver something faster than it = can be=20 delivered and it is wasteful, unhealthy, and all too common.

Schedule pressure exists for several reasons. The people who task = programmers=20 do not fully appreciate what a strong work ethic we have and how much = fun it is=20 to be a programmer. Perhaps because they project their own behavior onto = us,=20 they believe that asking for it sooner will make us work harder to get = it there=20 sooner. This is probably actually true, but the effect is very small, = and the=20 damage is very great. Additionally, they have no visibility into what it = really=20 takes to produce software. Not being able to see it, and not be able to = create=20 it themselves, the only thing they can do is see time-to-market pressure = and=20 fuss at programmers about it.

The key to fighting schedule pressure is simply to turn it into=20 time-to-market pressure. The way to do this to give visibility into the=20 relationship between the available labor and the product. Producing an = honest,=20 detailed, and most of all, understandable=20 estimate of all the labor involved is the best way to do this. It has = the added=20 advantage of allowing good management decisions to be made about = possible=20 functionality tradeoffs.

The key insight that the estimate must make plain is that labor is an = almost=20 incompressible fluid. You can't pack more into a span of time anymore = than you=20 can pack more water into a container over and above that container's = volume. In=20 a sense, a programmer should never say =E2=80=98no=E2=80=99, but rather=20 to say =E2=80=98What will you give up to get that = thing you=20 want?=E2=80=99 The effect of producing clear estimates will be to = increase the=20 respect for programmers. This is how other professionals behave. = Programmers'=20 hard work will be visible. Setting an unrealistic schedule will also be=20 painfully obvious to everyone. Programmers cannot be hoodwinked. It is=20 disrespectful and demoralizing to ask them to do something unrealistic. = Extreme=20 Programming amplifies this and builds a process around it; I hope that = every=20 reader will be lucky enough to use it.

How to Understand the=20 User

It is your duty to understand the user, and to help your boss = understand the=20 user. Because the user is not as intimately involved in the creation of = your=20 product as you are, they behave a little differently:

  • The user generally makes short pronouncements.

  • The user has their own job; they will mainly think of small = improvements in=20 your product, not big improvements.

  • The user can't have a vision that represents the complete body of = your=20 product users.

It is your duty to give them what they really want, not what they say = they=20 want. It is however, better to propose it to them and get them to agree = that=20 your proposal is what they really want before you begin, but they may = not have=20 the vision to do this. Your confidence in your own ideas about this = should vary.=20 You must guard against both arrogance and false modesty in terms of = knowing what=20 the customer really wants. Programmers are trained to design and create. = Market=20 researchers are trained to figure out what people want. These two kinds = of=20 people, or two modes of thought in the same person, working harmoniously = together give the best chance of formulating the correct vision.

The more time you spend with users the better you will be able to = understand=20 what will really be successful. You should try to test your ideas = against them=20 as much as you can. You should eat and drink with them if you can.

Guy Kawasaki[Rules] has emphasized the = importance=20 of watching what your users do in = addition=20 to listening to them.

I believe contractors and consultants often have tremendous problems = getting=20 their clients to clarify in their own minds what they really want. If = you intend=20 to be a consultant, I suggest you choose your clients based on their=20 clear-headedness as well as their pocketbooks.

How to Get a = Promotion

To be promoted to a role, act out that role first.

To get promoted to a title, find out what is expected of that title = and do=20 that.

To get a pay raise, negotiate armed with information.

If you feel like you are past due for a promotion, talk to your boss = about=20 it. Ask them explicitly what you need to do to get promoted, and try to = do it.=20 This sounds trite, but often times your perception of what you need to = do will=20 differ considerably from your boss's. Also this will pin your boss down = in some=20 ways.

Most programmers probably have an exaggerated sense of their relative = abilities in some ways---after all, we can't all be in the top 10%! = However, I=20 have seem some people who were seriously unappreciated. One cannot = expect=20 everyone's evaluation to perfectly match reality at all times, but I = think=20 people are generally moderately fair, with one caveat: you cannot be = appreciated=20 without visibility into your work. Sometimes, do to happenstance or = personal=20 habits, someone will not be noticed much. Working from home a lot or = being=20 geographically separated from your team and boss makes this especially=20 difficult.

Serving = Your=20 Team

How to Develop = Talent

Nietschze exaggerated when he said[Stronger]:=20

What does not destroy me, makes me = stronger.=20

Your greatest responsibility is to your team. You should know each of = them=20 well. You should stretch your team, but not overburden them. You should = usually=20 talk to them about the way they are being stretched. If they buy in to = it, they=20 will be well motivated. On each project, or every other project, try to = stretch=20 them in both a way that they suggest and a way that you think will be = good for=20 them. Stretch them not by giving them more work, but by giving them a = new skill=20 or better yet a new role to play on the team.

You should allow people (including yourself) to fail occasionally and = should=20 plan for some failure in your schedule. If there is never any failure, = there can=20 be no sense of adventure. If there are not occasional failures, you are = not=20 trying hard enough. When someone fails, you should be as gentle as you = can with=20 them while not treating them as though they had succeeded.

Try to get each team member to buy in and be well motivated. Ask each = of them=20 explicitly what they need to be well-motivated if they are not. You may = have to=20 leave them dissatisfied, but you should know what everybody desires. =

You can't give up on someone who is intentionally not carrying their = share of=20 the load because of low morale or dissatisfaction and just let them be = slack.=20 You must try to get them well-motivated and productive. As long as you = have the=20 patience, keep this up. When your patience is exhausted, fire them. You = cannot=20 allow someone who is intentionally working below their level to remain = on the=20 team, since it is not fair to the team.

Make it clear to the strong members of your team that you think they = are=20 strong by saying so in public. Praise should be public and criticism = private.=20

The strong members of the team will naturally have more difficult = tasks than=20 the weak members of the team. This is perfectly natural and nobody will = be=20 bothered by it as long as everyone works hard.

It is an odd fact that is not reflected in salaries that a good = programmer is=20 more productive than 10 bad programmers. This creates a strange = situation. It=20 will often be true that you could move faster if your weak programmers = would=20 just get out of the way. If you did this you would in fact make more = progress in=20 the short term. However, your tribe would lose some important benefits, = namely=20 the training of the weaker members, the spreading of tribal knowledge, = and the=20 ability to recover from the loss of the strong members. The strong must = be=20 gentle in this regard and consider the issue from all angles.

You can often give the stronger team members challenging, but = carefully=20 delineated, tasks.

How to Choose What to Work=20 On

You balance your personal needs against the needs of the team in = choosing=20 what aspect of a project to work on. You should do what you are best at, = but try=20 to find a way to stretch yourself not by taking on more work but by = exercising a=20 new skill. Leadership and communication skills are more important than = technical=20 skills. If you are very strong, take on the hardest or riskiest task, = and do it=20 as early as possible in the project to decrease risk.

How to Get the Most From Your=20 Teammates

To get the most from your teammates, develop a good team spirit and = try to=20 keep every individual both personally challenged and personally engaged. =

To develop team spirit, corny stuff like logoized clothing and = parties are=20 good, but not as good as personal respect. If everyone respects everyone = else,=20 nobody will want to let anybody down. Team spirit is created when people = make=20 sacrifices for the team and think in terms of the good of the team = before their=20 own personal good. As a leader, you can't ask for more than you give = yourself in=20 this respect.

One of the keys to team leadership is to facilitate consensus so that = everyone has buy in. This occasionally means allowing your teammates to = be=20 wrong. That is, if it does not harm the project too much, you must let = some of=20 your team do things their own way, based on consensus, even if you = believe with=20 great confidence it is the wrong thing to do. When this happens, don't = agree,=20 simply disagree openly and accept the consensus. Don't sound hurt, or = like=20 you're being forced into it, simply state that you disagree but think = the=20 consensus of the team is more important. This will often cause them to=20 backtrack. Don't insist that they go through with their initial plan if = they do=20 backtrack.

If there is an individual who will not consent after you have = discussed the=20 issues from all appropriate sides, simply assert that you have to make a = decision and that is what your decision is. If there is a way to judge = if your=20 decision will be wrong or if it is later shown to be wrong, switch as = quickly as=20 you can and recognize the persons who were right.

Ask your team, both as a group and individually, what they think = would create=20 team spirit and make for an effective team.

Praise frequently rather than lavishly. Especially praise those who = disagree=20 with you when they are praiseworthy. Praise in public and criticize in = private;=20 with one exception: sometimes growth or the correction of a fault can't = be=20 praised without drawing embarrassing attention to the original fault, so = that=20 growth should be praised in private.

How to Divide Problems = Up

It's fun to take a software project and divide it up into tasks that = will be=20 performed by individuals. This should be done early. Sometimes managers = like to=20 think that an estimate can be made without consideration of the = individuals that=20 will perform the work. This is impossible since the productivity of = individuals=20 varies so widely. Who has particular knowledge about a component also = constantly=20 changes and can have an order of magnitude effect on performance.

Just as a composer considers the timbre of the instrument that will = play a=20 part or the coach of an athletic team considers the strengths of each = player,=20 the experienced team leader will not usually be able to separate the = division of=20 the project into tasks from the team members to which they will be = assigned.=20 This is part of the reason that a high-performing team should not be = broken up.=20

There is a certain danger in this given that people will become bored = as they=20 build upon their strengths and never improve their weaknesses or learn = new=20 skills. However, specialization is a very useful productivity tool when = not=20 overused.

How to Handle Boring=20 Tasks

Sometimes it is not possible to avoid boring tasks that are critical = to the=20 success of the company or the project. These tasks can really hurt the = morale of=20 those that have to do them. The best technique for dealing with this is = to=20 invoke or promote Larry Wall's programmer's virtue of Laziness. Try to = find some=20 way to get the computer to do the task for you or to help your teammates = do=20 this. Working for a week on a program to do a task that will take a week = to do=20 by hand has the great advantage of being more educational and sometimes = more=20 repeatable.

If all else fails, apologize to those who have to do the boring task, = but=20 under no circumstances allow them to do it alone. At a minimum assign a = team of=20 two to do the work and promote healthy teamwork to get the task done. =

How to Gather Support for a=20 Project

To gather support for a project, create and communicate a vision that = demonstrates real value to the organization as a whole. Attempt to let = others=20 share in your vision creation. This gives them a reason to support you = and gives=20 you the benefit of their ideas. Individually recruit key supporters for = your=20 project. Wherever possible, show, don't tell. If possible, construct a = prototype=20 or a mockup to demonstrate your ideas. A prototype is always powerful = but in=20 software it is far superior to any written description.

How to Grow a = System

The seed of a tree contains the idea of the adult but does not fully = realize=20 the form and potency of the adult. The embryo grows. It becomes larger. = It looks=20 more like the adult and has more of the uses. Eventually it bears fruit. = Later,=20 it dies and its body feeds other organisms.

We have the luxury of treating software like that. A bridge is not = like that;=20 there is never a baby bridge, but merely an unfinished bridge. Bridges = are a lot=20 simpler than software.

It is good to think of software as growing, because it allows us to = make=20 useful progress before we have a perfect mental image. We can get = feedback from=20 users and use that to correct the growth. Pruning off weak limbs is = healthful.=20

The programmer must design a finished system that can be delivered = and used.=20 But the advanced programmer must do more. You must design a growth path = that=20 ends in the finished system. It is your job to take a germ of an idea = and build=20 a path that takes it as smoothly as possible into a useful artifact. =

To do this, you must visualize the end result and communicate it in a = way=20 that the engineering team can get excited about. But you must also = communicate=20 to them a path that goes from wherever they are now to where they want = to be=20 with no large leaps. The tree must stay alive the whole time; it cannot = be dead=20 at one point and resurrected later.

This approach is captured in spiral development. Milestones that are = never=20 too far apart are used to mark progress along the path. In the = ultra-competitive=20 environment of business, it is best if the milestones can be released = and make=20 money as early as possible, even if they are far away from a = well-designed=20 endpoint. One of the programmer's jobs is to balance the immediate = payoff=20 against future payoff by wisely choosing a growth path expressed in = milestones.=20

The advanced programmer has the triple responsibility of growing = software,=20 teams, and persons.

A reader, Rob Hafernik, sent in this comment on this section that I = can do no=20 better than to quote in full:

I think you under-emphasize the importance here. It's not just = systems, but=20 algorithms, user interfaces, data models, and so on. It's absolutely = vital as you work on a large system = to have=20 measurable progress toward intermediate goals. Nothing is as bad as = the=20 special horror of getting down to the end and discovering that the = whole thing=20 just isn't going to work (look at the recent debacle of the Voter News = System). I would even go further and state it as a law of nature: no = large,=20 complex system can be implemented from scratch, it can only be evolved from a simple system = to a=20 complex system in a series of intentional steps. =

To which one can only reply Fiat lux!

How to Communicate = Well

To communicate well, you have to recognize how hard it is. It is a = skill unto=20 itself. It is made harder by the fact that the persons with whom you = have to=20 communicate are flawed. They do not work hard at understanding you. They = speak=20 poorly and write poorly. They are often overworked or bored, and, at a = minimum,=20 somewhat focused on their own work rather than the larger issues you may = be=20 addressing. One of the advantages of taking classes and practicing = writing,=20 public speaking, and listening is that if you become good at it you can = more=20 readily see where problems lie and how to correct them.

The programmer is a social animal whose survival depends on = communication=20 with her team. The advanced programmer is a social animal whose = satisfaction=20 depends on communication with people outside her team.

The programmer brings order out of chaos. One interesting way to do = this is=20 to initiate a proposal of some kind outside the team. This can be done = in a strawman or white-paper = format or=20 just verbally. This leadership has the tremendous advantage of setting = the terms=20 of the debate. It also exposes you to criticism, and worse, rejection = and=20 neglect. The advanced programmer must be prepared to accept this, = because she=20 has a unique power and therefore a unique responsibility. Entrepreneurs = who are=20 not programmers need programmers to provide leadership in some ways. = Programmers=20 are the part of the bridge between ideas and reality that rests on = reality.

I haven't mastered communicating well, but what I'm currently trying = is what=20 I think of a four-pronged approach: After I have my ideas in order and = am fully=20 prepared, I try to speak verbally, hand people a white-paper (on real = paper, as=20 well as electronically) show them a demo, and then patiently repeat this = process. I think a lot of times we are not patient enough in this kind = of=20 difficult communication. You should not be disheartened if your ideas = are not=20 immediately accepted. If you have invested energy in there preparation, = no one=20 will think poorly of you for it.

How to Tell People Things They = Don't Want=20 to Hear

You will often have to tell people things that will make them = uncomfortable.=20 Remember that you are doing this for a reason. Even if nothing can be = done about=20 the problem, you are telling them as early as possible so they will be=20 well-informed.

The best way to tell someone about a problem is to offer a solution = at the=20 same time. The second best way is to appeal to them for help with the = problem.=20 If there is a danger that you won't be believed, you should gather some = support=20 for your assertion.

One of the most unpleasant and common things you will have to say is, = =E2=80=98The schedule will have to slip.=E2=80=99 The = conscientious programmer=20 hates to say this, but must say it as early as possible. There is = nothing worse=20 than postponing action when a milestone slips, even if the only action = is to=20 inform everyone. In doing this, it is better to do it as a team, at = least in=20 spirit, if not physically. You will want your team's input on both where = you=20 stand and what can be done about it, and the team will have to face the=20 consequences with you.

How to Deal with Managerial=20 Myths

The word myth sometimes means = fiction.=20 But it has a deeper connotation. It also means a story of religious = significance=20 that explains the universe and mankind's relationship to it. Managers = tend to=20 forget what they learned as programmers and believe in certain myths. It = would=20 be as rude and unsuccessful to try to convince them these myths are = false as to=20 try to disillusion a devoutly religious person of their beliefs. For = that=20 reason, you should recognize these beliefs as myths:

  • More documentation is always better. (They want it, but they don't = want you=20 to spend any time on it.)

  • Programmers can be equated. (Programmers vary by an order of = magnitude.)=20

  • Resources can be added to a late project to speed it. (The cost of=20 communication with the new persons is almost always more taxing than = helpful.)=20

  • It is possible to estimate software development reliably. (It is = not even=20 theoretically possible.)

  • Programmers' productivity can be measured in terms of some simple = metric,=20 like lines of code. (If succinctness is power, lines of code are bad, = not=20 good.)

If you have an opportunity, you can try to explain these things, but = don't=20 feel bad if you have no success and don't damage your reputation by = confronting=20 these myths belligerently. Each of these myths reinforces the manager's = idea=20 that they have some actual control over what is going on. The truth is = that=20 managers facilitate if they are good, and impede if they are bad. =

How to Deal with = Organizational=20 Chaos

There are often brief periods of great organizational chaos, such as = layoffs,=20 buyouts, ipos, firings, new hirings, and so on. These are unsettling to=20 everyone, but perhaps a little less unsettling to the programmer whose = personal=20 self-esteem is founded in capacity rather than in position. = Organizational chaos=20 is a great opportunity for programmers to exercise their magic power. = I've saved=20 this for last because it is a deep tribal secret. If you are not a = programmer,=20 please stop reading now.

Engineers have the power to create and = sustain.=20

Non-engineers can order people around but, in a typical software = company, can=20 create and sustain nothing without engineers, just as engineers = typically cannot=20 sell a product or manage a business effectively. This power is proof = against=20 almost all of the problems associated with temporary organizational = mayhem. When=20 you have it you should ignore the chaos completely and carry on as if = nothing is=20 happening. You may, of course, get fired, but if that happens you can = probably=20 get a new job because of the magic power. More commonly, some = stressed-out=20 person who does not have the magic power will come into your cube and = tell you=20 to do something stupid. If you are really sure that it is stupid, it is = best to=20 smile and nod until they go away and then carry on doing what you know = is best=20 for the company.

If you are a leader, tell your people to do the same thing and tell = them to=20 ignore what anybody else tells them. This course of action is the best = for you=20 personally, and is the best for your company or project. =

Glossary

This is a glossary of terms as used in this essay. These do not = necessarily=20 have a standardized meaning to other people. Eric S. Raymond has = compiled a=20 massive and informative glossary[HackerDict] that=20 rather surprisingly can pleasurably be read cover-to-cover once you can=20 appreciate a fraction of it.

unk-unk

Slang for unknown-unknown. Problems that cannot presently even be=20 conceptualized that will steal time away from the project and wreck = the=20 schedule.

boss

The person or entity that gives you tasks. In some cases this may = be the=20 public at large.

printlining

The insertion of statements into a program on a strictly temporary = basis=20 that output information about the execution of the program for the = purpose of=20 debugging.

logging

The practice of writing a program so that it can produce a = configurable=20 output log describing its execution.

divide and conquer

A technique of top-down design and, importantly, of debugging that = is the=20 subdivision of a problem or a mystery into progressively smaller = problems or=20 mysteries.

vapor

Illusionary and often deceptive promises of software that is not = yet for=20 sale and, as often as not, will never materialize into anything solid. =

boss

The person who sets your tasks. In some cases, the user is the = boss.

tribe

The people with whom you share loyalty to a common goal.

low-hanging fruit

Big improvements that cost little.

Entrepreneur

The initiator of projects.

garbage

Objects that are no longer needed that hold memory.

busines

A group of people organized for making money.

company

A group of people organized for making money.

tribe

A group of people you share cultural affinity and loyalty with. =

scroll blindness

The effect of being unable to find information you need because it = is=20 buried in too much other, less interesting information.

wall-clock

Actually time as measured by a clock on a wall, as opposed to CPU = time.=20

bottleneck

The most important limitation in the performance of a system. A=20 constriction that limits performance.

master

A unique piece of information from which all cached copies are = derived that=20 serves as the official definition of that data.

heap allocated

Memory can be said to be heap allocated whenever the mechanism for = freeing=20 it is complicated.

garbage

Allocated memory that no longer has any useful meaning.

garbage collector

A system for recycling garbage.

memory leak

The unwanted collection of references to objects that prevents = garbage=20 collection (or a bug in the garbage collector or memory management = system!)=20 that causes the program to gradually increase its memory demands over = time.=20

Extreme Programming

A style of programming emphasizing communication with the customer = and=20 automated testing.

hitting the wall

To run out of a specific resource causing performance to degrade = sharply=20 rather than gradually.

speculative programming

Producing a feature before it is really known if that feature will = be=20 useful.

information hiding

A design principle that seeks to keep things independent and = decoupled by=20 using interfaces that expose as little information as possible.

object-oriented programming

An programming style emphasizing the the management of state inside = objects.

communication languages

A language designed primarily for standardization rather than = execution.=20

boxes and arrows

A loose, informal style of making diagrams consiting of boxes and = arrows=20 drawn between those boxes to show the relationships. This contrast = with formal=20 diagram methodologies, such as UML.

lingua franca

A language so popular as to be a de facto standard for its field, = as French=20 was for international diplomacy at one time.

buy vs. build

An adjective describing a choice between spending money for = software or=20 writing it your self.

mere work

Work that requires little creativity and entails little risk. Mere = work can=20 be estimated easily.

programming notation

A synonym for programming language that emphasizes the mathematical = nature=20 of programming language and their relative simplicity compared to = natural=20 languages.

strawman

A document meant to be the starting point of a technical = discussion. A=20 strawman may lead to a stickman, tinman, woodman, ironman, etc.

wite-paper

An informative document that is often meant to explain or sell a = product or=20 idea to an audience different than the programmers of that product or = idea.=20

Table of Contents

Bibliography/Websiteography

Bibliography/Websiteography

Books

[Rules00] Guy Kawasaki, = Michelle Moreno, = and Gary Kawasaki. = 2000. HarperBusiness. Rules for=20 Revolutionaries: The Capitalist Manifesto for Creating and Marketing New = Products and Services.

[RDev96] Steve McConnell. = 1996. Microsoft Press. Redmond, Wash.=20 Rapid Development: Taming Wild = Software=20 Schedules.

[CodeC93] Steve McConnell. = 1993. Microsoft Press. Redmond, Wash.=20 Code Complete. =

[XP99] Kent Beck. = 1999. 0201616416. Addison-Wesley. = Extreme Programming Explained: Embrace Change.=20

[PlanXP00] Kent Beck and = Martin Fowler. = 2000. 0201710919. Addison-Wesley. = Planning Extreme Programming.

[Prag99] Andrew Hunt, David Thomas, and = Ward Cunningham. = 1999. 020161622X. Addison-Wesley. = The Pragmatic Programmer: From Journeyman to = Master.=20

[Stronger] Friedrich Nietzsche.=20 1889. Twilight of the=20 Idols, "Maxims and Arrows", section 8..

Web Sites

[PGSite] Paul Graham. = 2002. Articles on his = website:=20 http://www.paulgraham.com/articles.html. All of them, but especially = "Beating=20 the Averages".

[Hacker] Eric S. Raymond. = 2003. How to Become a = Hacker.=20 http://www.catb.org/~esr/faqs/hacker-howto.html.=20

[HackDict] Eric S. Raymond. = 2003. The New Hacker = Dictionary.=20 http://catb.org/esr/jargon/jargon.html.=20

[ExpCS] Edsger W. Dijkstra.=20 1986. How = Experimental is=20 Computing Science?. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD988a.= PDF.=20

[Knife] Edsger W. Dijkstra.=20 1984. On a = Cultural=20 Gap. http://www.cs.utexas.edu/users/EWD/ewd09xx/EWD913.P= DF .=20

Appendix=EF=BF=BDB.=EF=BF=BDHistory (As Of = February,=20 2003)

Request for Feedback or=20 Extension

Please send me any comments you may have on this essay. I consider = all=20 suggestions, many of which have already improved this essay.

I have placed this essay under the GNU Free Documentation License. = This=20 license is not specifically designed for essays. Essays are usually = intended to=20 be coherent and convincing arguments that are writtien from a single = point of=20 view in a single voice. I hope this essay is a short and pleasant read. =

I also hope that it is instructive. Although not a textbook, it is = broken=20 into many small sections to which new sections can be freely added. If = so=20 inclined, you are encouraged to expand upon this essay as you see fit, = subject=20 to the provisions of the License.

It may be arrogance to imagine that this document is worthy of = extension; but=20 hope springs eternal. I would be joyous if it were extended in the = following=20 ways:

  • The addition of a comprehensive reading list to each section,

  • The addition of more and better sections,

  • Translation into other languages, even if only on a=20 subsection-by-subsection basis, and/or

  • Criticism or commentary in-lined into the text.

  • The ability to build into different formats, such as palm formats = and=20 better HTML.

If you inform me of your work, I will consider it and may include it = in=20 subsequent versions that I produce, subject to the provisions of the = License.=20 You may of course produce your own versions of this document without my=20 knowledge, as explained in the License.

Thank you.

Robert L. Read

Original = Version

The original version of this document was begun by Robert L. Read in = the year=20 2000 and first published electronically at Samizdat=20 Press(http://Samizdat.mines.edu) in 2002. It is dedicated to the = programmers of=20 Hire.com.

After this article was mentioned on Slashdot in 2003, about 75 people = sent me=20 email with suggestions and errata. I appreciate them all. There was a = lot of=20 duplication, but the following people either made major suggestions or = were the=20 first to find a bug that I fixed: Morgan McGuire, David Mason, Tom = Moertel,=20 Ninja Programmer (145252) at Slashdot, Ben Vierck, Rob Hafernik, Mark = Howe,=20 Pieter Pareit, Brian Grayson, Zed A. Shaw, Steve Benz, Maksim Ioffe, = Andrew Wu,=20 David Jeschke, and Tom Corcoran.

Finally I would like to thank Christina Vallery, whose editing and=20 proofreading greatly improved the second draft, and Wayne Allen, who = encouraged=20 me to initiate this.

Original Author's = Bio

Robert L. Read lives in Austin, Texas, with his wife and two = children. He is=20 currently a Principal Engineer at Hire.com, where he has worked for four = years.=20 Prior to that he founded 4R Technology, which made a scanner-based image = analysis quality control tool for the paper industry.

Rob received a PhD from the University of Texas at Austin in 1995 in = Computer=20 Science related to database theory. In 1987 he received a BA in Computer = Science=20 from Rice University. He has been a paid programmer since the age of 16. =

Appendix=EF=BF=BDC.=EF=BF=BDGNU = Free Documentation=20 License

Version 1.2, November 2002

Table of Contents

P= REAMBLE
A= PPLICABILITY=20 AND DEFINITIONS
V= ERBATIM=20 COPYING
C= OPYING=20 IN QUANTITY
M= ODIFICATIONS
C= OMBINING=20 DOCUMENTS
C= OLLECTIONS=20 OF DOCUMENTS
A= GGREGATION=20 WITH INDEPENDENT WORKS
T= RANSLATION
T= ERMINATION
= FUTURE=20 REVISIONS OF THIS LICENSE
ADDENDUM:=20 How to use this License for your documents

Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 59 = Temple=20 Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to = copy and=20 distribute verbatim copies of this license document, but changing it = is not=20 allowed.

PREAMBLE

The purpose of this License is to make a manual, textbook, or other=20 functional and useful document "free" in the sense of freedom: to assure = everyone the effective freedom to copy and redistribute it, with or = without=20 modifying it, either commercially or noncommercially. Secondarily, this = License=20 preserves for the author and publisher a way to get credit for their = work, while=20 not being considered responsible for modifications made by others.

This License is a kind of "copyleft", which means that derivative = works of=20 the document must themselves be free in the same sense. It complements = the GNU=20 General Public License, which is a copyleft license designed for free=20 software.

We have designed this License in order to use it for manuals for free = software, because free software needs free documentation: a free program = should=20 come with manuals providing the same freedoms that the software does. = But this=20 License is not limited to software manuals; it can be used for any = textual work,=20 regardless of subject matter or whether it is published as a printed = book. We=20 recommend this License principally for works whose purpose is = instruction or=20 reference.

APPLICABILITY AND=20 DEFINITIONS

This License applies to any manual or other = work, in any=20 medium, that contains a notice placed by the copyright holder saying it = can be=20 distributed under the terms of this License. Such a notice grants a = world-wide,=20 royalty-free license, unlimited in duration, to use that work under the=20 conditions stated herein. The "Document", below, refers to any such = manual or=20 work. Any member of the public is a licensee, and is addressed as "you". = You=20 accept the license if you copy, modify or distribute the work in a way = requiring=20 permission under copyright law.

A "Modified Version" of the Document means = any work=20 containing the Document or a portion of it, either copied verbatim, or = with=20 modifications and/or translated into another language.

A "Secondary Section" is a named = appendix or a=20 front-matter section of the Document that deals exclusively with the=20 relationship of the publishers or authors of the Document to the = Document's=20 overall subject (or to related matters) and contains nothing that could = fall=20 directly within that overall subject. (Thus, if the Document is in part = a=20 textbook of mathematics, a Secondary Section may not explain any = mathematics.)=20 The relationship could be a matter of historical connection with the = subject or=20 with related matters, or of legal, commercial, philosophical, ethical or = political position regarding them.

The "Invariant Sections" are certain = Secondary=20 Sections whose titles are designated, as being those of Invariant = Sections, in=20 the notice that says that the Document is released under this License. = If a=20 section does not fit the above definition of Secondary then it is not = allowed to=20 be designated as Invariant. The Document may contain zero Invariant = Sections. If=20 the Document does not identify any Invariant Sections then there are = none.

The "Cover Texts" are certain short = passages of=20 text that are listed, as Front-Cover Texts or Back-Cover Texts, in the = notice=20 that says that the Document is released under this License. A = Front-Cover Text=20 may be at most 5 words, and a Back-Cover Text may be at most 25 = words.

A "Transparent" copy of the Document = means a=20 machine-readable copy, represented in a format whose specification is = available=20 to the general public, that is suitable for revising the document=20 straightforwardly with generic text editors or (for images composed of = pixels)=20 generic paint programs or (for drawings) some widely available drawing = editor,=20 and that is suitable for input to text formatters or for automatic = translation=20 to a variety of formats suitable for input to text formatters. A copy = made in an=20 otherwise Transparent file format whose markup, or absence of markup, = has been=20 arranged to thwart or discourage subsequent modification by readers is = not=20 Transparent. An image format is not Transparent if used for any = substantial=20 amount of text. A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain = ASCII=20 without markup, Texinfo input format, LaTeX input format, SGML or XML = using a=20 publicly available DTD, and standard-conforming simple HTML, PostScript = or PDF=20 designed for human modification. Examples of transparent image formats = include=20 PNG, XCF and JPG. Opaque formats include proprietary formats that can be = read=20 and edited only by proprietary word processors, SGML or XML for which = the DTD=20 and/or processing tools are not generally available, and the = machine-generated=20 HTML, PostScript or PDF produced by some word processors for output = purposes=20 only.

The "Title Page" means, for a printed = book, the=20 title page itself, plus such following pages as are needed to hold, = legibly, the=20 material this License requires to appear in the title page. For works in = formats=20 which do not have any title page as such, "Title Page" means the text = near the=20 most prominent appearance of the work's title, preceding the beginning = of the=20 body of the text.

A section "Entitled XYZ" means a named = subunit of=20 the Document whose title either is precisely XYZ or contains XYZ in = parentheses=20 following text that translates XYZ in another language. (Here XYZ stands = for a=20 specific section name mentioned below, such as "Acknowledgements",=20 "Dedications", "Endorsements", or "History".) To "Preserve the Title" of = such a=20 section when you modify the Document means that it remains a section = "Entitled=20 XYZ" according to this definition.

The Document may include Warranty Disclaimers next to the notice = which states=20 that this License applies to the Document. These Warranty Disclaimers = are=20 considered to be included by reference in this License, but only as = regards=20 disclaiming warranties: any other implication that these Warranty = Disclaimers=20 may have is void and has no effect on the meaning of this = License.

VERBATIM=20 COPYING

You may copy and distribute the Document in any medium, either = commercially=20 or noncommercially, provided that this License, the copyright notices, = and the=20 license notice saying this License applies to the Document are = reproduced in all=20 copies, and that you add no other conditions whatsoever to those of this = License. You may not use technical measures to obstruct or control the = reading=20 or further copying of the copies you make or distribute. However, you = may accept=20 compensation in exchange for copies. If you distribute a large enough = number of=20 copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and = you may=20 publicly display copies.

COPYING IN=20 QUANTITY

If you publish printed copies (or copies in media that commonly have = printed=20 covers) of the Document, numbering more than 100, and the Document's = license=20 notice requires Cover Texts, you must enclose the copies in covers that = carry,=20 clearly and legibly, all these Cover Texts: Front-Cover Texts on the = front=20 cover, and Back-Cover Texts on the back cover. Both covers must also = clearly and=20 legibly identify you as the publisher of these copies. The front cover = must=20 present the full title with all words of the title equally prominent and = visible. You may add other material on the covers in addition. Copying = with=20 changes limited to the covers, as long as they preserve the title of the = Document and satisfy these conditions, can be treated as verbatim = copying in=20 other respects.

If the required texts for either cover are too voluminous to fit = legibly, you=20 should put the first ones listed (as many as fit reasonably) on the = actual=20 cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering = more=20 than 100, you must either include a machine-readable Transparent copy = along with=20 each Opaque copy, or state in or with each Opaque copy a = computer-network=20 location from which the general network-using public has access to = download=20 using public-standard network protocols a complete Transparent copy of = the=20 Document, free of added material. If you use the latter option, you must = take=20 reasonably prudent steps, when you begin distribution of Opaque copies = in=20 quantity, to ensure that this Transparent copy will remain thus = accessible at=20 the stated location until at least one year after the last time you = distribute=20 an Opaque copy (directly or through your agents or retailers) of that = edition to=20 the public.

It is requested, but not required, that you contact the authors of = the=20 Document well before redistributing any large number of copies, to give = them a=20 chance to provide you with an updated version of the Document.

MODIFICATIONS

You may copy and distribute a Modified Version of the Document under = the=20 conditions of sections 2 and 3 above, provided that you release the = Modified=20 Version under precisely this License, with the Modified Version filling = the role=20 of the Document, thus licensing distribution and modification of the = Modified=20 Version to whoever possesses a copy of it. In addition, you must do = these things=20 in the Modified Version:

  1. Use in the Title Page (and on the covers, if any) a title distinct = from=20 that of the Document, and from those of previous versions (which = should, if=20 there were any, be listed in the History section of the Document). You = may use=20 the same title as a previous version if the original publisher of that = version=20 gives permission.=20
  2. List on the Title Page, as authors, one or more persons or = entities=20 responsible for authorship of the modifications in the Modified = Version,=20 together with at least five of the principal authors of the Document = (all of=20 its principal authors, if it has fewer than five), unless they release = you=20 from this requirement.=20
  3. State on the Title page the name of the publisher of the Modified = Version,=20 as the publisher.
  4. Preserve all the copyright notices of the Document.=20
  5. Add an appropriate copyright notice for your modifications = adjacent to the=20 other copyright notices.=20
  6. Include, immediately after the copyright notices, a license notice = giving=20 the public permission to use the Modified Version under the terms of = this=20 License, in the form shown in the Addendum=20 below.=20
  7. Preserve in that license notice the full lists of Invariant = Sections and=20 required Cover Texts given in the Document's license notice.
  8. Include an unaltered copy of this License.=20
  9. Preserve the section Entitled "History", Preserve its Title, and = add to it=20 an item stating at least the title, year, new authors, and publisher = of the=20 Modified Version as given on the Title Page. If there is no section = Entitled=20 "History" in the Document, create one stating the title, year, = authors, and=20 publisher of the Document as given on its Title Page, then add an item = describing the Modified Version as stated in the previous sentence.=20
  10. Preserve the network location, if any, given in the Document for = public=20 access to a Transparent copy of the Document, and likewise the network = locations given in the Document for previous versions it was based on. = These=20 may be placed in the "History" section. You may omit a network = location for a=20 work that was published at least four years before the Document = itself, or if=20 the original publisher of the version it refers to gives permission.=20
  11. For any section Entitled "Acknowledgements" or "Dedications", = Preserve the=20 Title of the section, and preserve in the section all the substance = and tone=20 of each of the contributor acknowledgements and/or dedications given = therein.=20
  12. Preserve all the Invariant Sections of the Document, unaltered in = their=20 text and in their titles. Section numbers or the equivalent are not = considered=20 part of the section titles.=20
  13. Delete any section Entitled "Endorsements". Such a section may not = be=20 included in the Modified Version.=20
  14. Do not retitle any existing section to be Entitled "Endorsements" = or to=20 conflict in title with any Invariant Section.=20
  15. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or = appendices that=20 qualify as Secondary Sections and contain no material copied from the = Document,=20 you may at your option designate some or all of these sections as = invariant. To=20 do this, add their titles to the list of Invariant Sections in the = Modified=20 Version's license notice. These titles must be distinct from any other = section=20 titles.

You may add a section Entitled "Endorsements", provided it contains = nothing=20 but endorsements of your Modified Version by various parties--for = example,=20 statements of peer review or that the text has been approved by an = organization=20 as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and = a=20 passage of up to 25 words as a Back-Cover Text, to the end of the list = of Cover=20 Texts in the Modified Version. Only one passage of Front-Cover Text and = one of=20 Back-Cover Text may be added by (or through arrangements made by) any = one=20 entity. If the Document already includes a cover text for the same = cover,=20 previously added by you or by arrangement made by the same entity you = are acting=20 on behalf of, you may not add another; but you may replace the old one, = on=20 explicit permission from the previous publisher that added the old = one.

The author(s) and publisher(s) of the Document do not by this License = give=20 permission to use their names for publicity for or to assert or imply=20 endorsement of any Modified Version.

COMBINING=20 DOCUMENTS

You may combine the Document with other documents released under this = License, under the terms defined in s= ection=20 4 above for modified versions, provided that you include in the = combination=20 all of the Invariant Sections of all of the original documents, = unmodified, and=20 list them all as Invariant Sections of your combined work in its license = notice,=20 and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and = multiple=20 identical Invariant Sections may be replaced with a single copy. If = there are=20 multiple Invariant Sections with the same name but different contents, = make the=20 title of each such section unique by adding at the end of it, in = parentheses,=20 the name of the original author or publisher of that section if known, = or else a=20 unique number. Make the same adjustment to the section titles in the = list of=20 Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled "History" = in the=20 various original documents, forming one section Entitled "History"; = likewise=20 combine any sections Entitled "Acknowledgements", and any sections = Entitled=20 "Dedications". You must delete all sections Entitled = "Endorsements".

COLLECTIONS = OF=20 DOCUMENTS

You may make a collection consisting of the Document and other = documents=20 released under this License, and replace the individual copies of this = License=20 in the various documents with a single copy that is included in the = collection,=20 provided that you follow the rules of this License for verbatim copying = of each=20 of the documents in all other respects.

You may extract a single document from such a collection, and = distribute it=20 individually under this License, provided you insert a copy of this = License into=20 the extracted document, and follow this License in all other respects = regarding=20 verbatim copying of that document.

AGGREGATION = WITH=20 INDEPENDENT WORKS

A compilation of the Document or its derivatives with other separate = and=20 independent documents or works, in or on a volume of a storage or = distribution=20 medium, is called an "aggregate" if the copyright resulting from the = compilation=20 is not used to limit the legal rights of the compilation's users beyond = what the=20 individual works permit. When the Document is included in an aggregate, = this=20 License does not apply to the other works in the aggregate which are not = themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these = copies of=20 the Document, then if the Document is less than one half of the entire=20 aggregate, the Document's Cover Texts may be placed on covers that = bracket the=20 Document within the aggregate, or the electronic equivalent of covers if = the=20 Document is in electronic form. Otherwise they must appear on printed = covers=20 that bracket the whole aggregate.

TRANSLATION

Translation is considered a kind of modification, so you may = distribute=20 translations of the Document under the terms of section 4. Replacing = Invariant=20 Sections with translations requires special permission from their = copyright=20 holders, but you may include translations of some or all Invariant = Sections in=20 addition to the original versions of these Invariant Sections. You may = include a=20 translation of this License, and all the license notices in the = Document, and=20 any Warranty Disclaimers, provided that you also include the original = English=20 version of this License and the original versions of those notices and=20 disclaimers. In case of a disagreement between the translation and the = original=20 version of this License or a notice or disclaimer, the original version = will=20 prevail.

If a section in the Document is Entitled "Acknowledgements", = "Dedications",=20 or "History", the requirement (section 4) to Preserve its Title (section = 1) will=20 typically require changing the actual title.

TERMINATION

You may not copy, modify, sublicense, or distribute the Document = except as=20 expressly provided for under this License. Any other attempt to copy, = modify,=20 sublicense or distribute the Document is void, and will automatically = terminate=20 your rights under this License. However, parties who have received = copies, or=20 rights, from you under this License will not have their licenses = terminated so=20 long as such parties remain in full compliance.

FUTURE = REVISIONS OF THIS=20 LICENSE

The Free Software Foundation may publish new, revised versions of the = GNU=20 Free Documentation License from time to time. Such new versions will be = similar=20 in spirit to the present version, but may differ in detail to address = new=20 problems or concerns. See http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. = If the=20 Document specifies that a particular numbered version of this License = "or any=20 later version" applies to it, you have the option of following the terms = and=20 conditions either of that specified version or of any later version that = has=20 been published (not as a draft) by the Free Software Foundation. If the = Document=20 does not specify a version number of this License, you may choose any = version=20 ever published (not as a draft) by the Free Software = Foundation.

ADDENDUM: How to=20 use this License for your documents

To use this License in a document you have written, include a copy of = the=20 License in the document and put the following copyright and license = notices just=20 after the title page:

Copyright (c) YEAR YOUR NAME. Permission is granted to copy, = distribute=20 and/or modify this document under the terms of the GNU Free = Documentation=20 License, Version 1.2 or any later version published by the Free = Software=20 Foundation; with no Invariant Sections, no Front-Cover Texts, and no=20 Back-Cover Texts. A copy of the license is included in the section = entitled=20 "GNU Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover = Texts,=20 replace the "with...Texts." line with this:

with the Invariant Sections being LIST THEIR TITLES, with the = Front-Cover=20 Texts being LIST, and with the Back-Cover Texts being LIST.=20

If you have Invariant Sections without Cover Texts, or some other = combination=20 of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we = recommend=20 releasing these examples in parallel under your choice of free software = license,=20 such as the GNU General Public License, to permit their use in free=20 software.

Colophon

This work is licensed under the GNU Free Documentation License. It = was=20 originally written in LaTeX, then ported to DocBook. It is available in=20 transparent copy in the DocBook/XML format. A build system and special=20 instructions on processing are part of the transparent copy package, = though=20 building from the source is system dependent. The source can be built = into=20 either HTML or PDF format, and extension to other formats should be = possible and=20 is encouraged.

The original version of this document was written by Robert L. Read = without=20 renumeration and dedicated to the programmers of Hire.com.=20