Wednesday, December 22, 2010

Holiday Break

I've been posting every two weeks consistently, but the holidays caught up with me this week. I'll be back in two weeks. Happy Holidays!

Tuesday, December 7, 2010

Grabbing the Dog Toy

If you've ever played with a dog you know about this. The dog brings you a ball to throw and sets it at your feet. When you reach down to grab it, the dog takes it back. If you try to take the toy from the dog, he'll refuse to let go. The harder you try to get the toy, the deeper he sinks his teeth into it. Don't think your point of view is superior to the dog's; you're as emotionally connected to the ball as he is. And as long as the relationship between the two of you is defined by your desire for the ball, you'll get nowhere. The only way you can get the toy is ignore it, wait for the dog to leave it alone and then snatch it away when he's distracted. Interestingly, once you have the toy, the dog changes from angrily defending its property to happily waiting for you to throw the ball.

Human beings are social creatures like dogs, and we aren't that different from them. At certain times we revert to adversarial relationships, even if it's against our own interest. Any attempt to address the problem directly seems to cause everyone to dig in their heels even more, making things worse. Breaking out of this bond requires distraction, either by changing the subject or getting away from the problem long enough to cool down.

Fights with customers over whether a change is a bug or an enhancement are notorious for how much emotion they raise and how impossible it is to come to an agreement. Even though classifying something as an enhancement means more time will be spent getting it right, customers feel like their change is being snatched away from them to some far off future they'll never see. Distract the customer away from their bug definition by defining the process instead. A change can either be made quickly with minimal testing or can go through a whole design-code-test-document cycle. These terms are easier to swallow because they don't make the customer feel like their change is being taken away. Throw that ball as hard as you can and the customer will run after it.

But customers aren't the only ones that can't let go of dog toys; it's a universal affliction. It's easy to become possessive about a piece of code, a build method or an operating system and feel defensive when someone criticizes them. Although this behavior is easy to recognize in others, it's hard to see when you're the one with your teeth sunk into something you should let go. Being too attached to anything, from a variable name to a business process, makes it that much harder to drop when necessary. You should be able to step back from anything enough to judge whether it's time to give it up.

This is done by being alone. Defensive aggression is a perversion of social behavior so you have to be antisocial to break out of it. Our business culture encourages endless meetings to talk out problems but sometimes you need to be alone with your own thoughts to figure something out. The social network feeds your need for defense from perceived attacks, so leaving it allows you to look at something objectively without thinking of it as your property.

This doesn't necessarily mean being physically alone. Everyone knows you can be alone in your thoughts even if someone is present. But most don't realize that even if no one is around, you could still not be alone enough to think. If, in your head, you're rehashing an argument with someone you aren't really alone. You're still acting out a defensive social posture against the character in your mind, who strangely, knows how to push your buttons better than any real person does. You need to banish this person, either by ignoring them or waiting until they get tired and leave you alone. Then you'll be alone enough to think about things without getting defensive. At this point you can relax your jaws, let the ball fall on the grass, and think of something else.

Tuesday, November 23, 2010

Lost in the Maze

Imagine an office. There are random stains on the carpet. The cubicles are missing pieces and half filled with junk left from former occupants. Cubes have only one power jack and if too many people in the row power up a breaker flips. Empty cubes are informal storage depots of obsolete and unwanted equipment. Keyboards are grimy with the sweat of a thousand fingers. Piles of unused hardware accumulate on any surface that isn't part of someone's personal space. Network cables have the little prong broken off so they fall out at the slightest movement. Drawers are filled with paper clips that are never used and old manuals of obsolete programs. Chairs missing arms or backs clog the narrow halls between cubes. Even chairs that are regularly used are creaky and worn.

The kitchen has a single low-wattage microwave, its interior speckled with dried food. Every surface is covered with crumbs. The table still wobbles even though someone's stuck a folded up napkin under one leg. There's a brown water stain under the coffee maker that's never been cleaned. The fridge smells. A few random posters are tacked haphazardly to the walls along with a reminder of the company policy on sexual harassment.

The conference room is more of the same. The white boards are covered with unreadable scribblings written with permanent markers. The eraser is missing. A pile of wires and unused equipment sits on the conference table and under it. The room is packed with mismatched and broken chairs. A random jumble of equipment sits in the corner ignored, its purpose forgotten.

What kind of software is going to be created in a place like this? What kind of software process is going to be followed? How inspired are the employees going to be to fight against the entropy of their surroundings?

Much has been written about the broken window theory, that seeing broken windows never fixed encourages worse things. But the theory is always talked about as if it only applies to people in far-off ghettos and not to those who wear business casual to work. We're professionals, so we can work through balky equipment and late hours with no overtime pay. I don't buy it. It's hard to rise above the environment you're in no matter who you are. Exceptional people do it, but organizations are made of ordinary people. When ordinary people live in a trashed environment they feel little motivation to do anything special. What's the point when nobody cares?

This doesn't have to happen. Why not take a slow day near the end of the year to do some spring cleaning? Throw away all the junk nobody uses, replace everything broken, clean everything dirty. It's amazing how energized you feel after filling up a trash can with junk you don't need. And actually doing something physical instead of staring at a screen all day helps clear the cobwebs in your mind, even while you're clearing the real cobwebs collecting in the corner. Everyone can start the year feeling refreshed instead of beaten down by the dreariness of their surroundings.

Opposing these cleanups is the hoarder's fear that something useful might get tossed. But how hard is it to know when something's junk? And how hard is it to buy a new network cable? When cleaning up, there needs to be someone who knows what the cost of replacement is so decisions can be made on whether to keep or trash something. But that brings us to the other thing holding back these cleanups. In many offices there doesn't seem to be anyone who has the authority to fill out a purchase order or to even know what things belong to which group. Without anyone in charge nobody feels secure enough to throw anything away. Instead everyone decides it's someone else's problem and so the junk piles up. Someone has to take on the responsibility of saying enough is enough, and someone who can make decisions on purchases needs to be around.

But these points don't just apply to the physical environment. The soft environment can become just as junk-filled. Network drives full of out-of-date software that no one needs. FTP sites with files from customers that no longer exist. Test machines with installed versions that have been end-of-life for years. Log files from customer problems that were closed months ago. These things need to be cleaned up too, before the junk makes important information too difficult to find.

But it doesn't stop there. Code itself gets filled with junk. Methods and variables that aren't used. Classes that never get created. Chunks of logic that can never be called. Comments about bugs that were solved years ago. Code needs to be swept through as well, to clean up the debris that accumulates over a programs lifetime. It happens to documentation too, to web sites, training manuals and anything else that gets worked over in the day to day process of software development. This virtual trash has the same draining effect on those who work with it as physical trash. If nobody cares what the code's like why should you? The virtual environment needs to be cleaned up regularly too, before the garbage in it overwhelms anyone's ability to work with it. Once a program resembles a hoarder's house, with narrow trails winding through mounds of trash, it's unsalvageable.

Destroying is as important as creating. The garbage in every environment, physical and virtual, needs to be gotten rid of, so that it doesn't drain the motivation of who work around it.

Tuesday, November 9, 2010

Code Is Meaningless

Computer languages are great for describing how to do something, but they can't explain why. Why add two to the personCounter? Why is statusField set to the empty string when counterField is null? Questions like these don't get answered by code. Code is very good at answering what and how questions, but why questions are completely impossible for it. So documentation was invented to provide a way to explain why something is the way it is. Unfortunately, few use it this way.

Instead, for programmers we have what's called echo documentation:

/**
* Gets a value.
*
* @return value the value returned
*/

public int getValue() {
   return this.value;
}

Many programmers will document their code by simply repeating what's there. There's no indication of what anything is used for, or why it was designed the way it was. Instead of explaining anything they echo the code. This isn't really documentation.

For users, we have a numbered list of exact instructions, in other words, a program:

  1. Click the button labeled “Excute”.
  2. In the popup window that appears, select the radio button labeled “Process Records”.
  3. Click the OK button.
  4. Now select “File/Open...” from the menu.
This style is marginally useful, but it still doesn't do what documentation is supposed to do: answer the questions the interface itself can't answer. It doesn't give the user a chance to do anything more than mindlessly follow directions. This is great for computers but human beings need something different.

Your brain needs information to be balanced between how and why just as your body needs nutritionally balanced food. Eating unhealthy food can leave you with the uncomfortable sensation of being full and hungry at the same time. This same thing happens to your brain when confronted with mounds of data and little explanation. You feel dizzy from the sheer volume of information, but are still confused as to exactly what's going on. And just like junk food that passes through your system without contributing much, most data bereft of reasons for its existence will be quickly forgotten. Documentation that's heavy on information but light on explanation creates more confusion than it prevents.

Why is why necessary? Answering why is so important because it helps human beings store information. To understand something, the human mind needs to create a mental model of it to hang details on. Without the mental model, the mass of details overwhelms the brain's capacity to store them, and the brain forgets most of what was said. People feel lost and confused when this happens, because they have no mental map to orient themselves on. But once they have that mental model to organize things around, human beings can remember an enormous amount of information. Although few people can memorize more than ten phone numbers, most people know more than ten thousand words. Meaning creates the conditions necessary for understanding.

Think of the mental model as a data structure that someone builds in their brain. You don't want to shove information into someone, overflowing their buffer, causing them to forget most of what you tell them. Instead you need to start out telling people how to construct the data structure they need to understand your system. Then you can add details, letting the user know where in their mental model the details fit. This way the human brain can store a lot more information, because it has someplace to put it. When someone has a mental model of something, they say they “understand” it, meaning if you gave them more information they would have somewhere to store it.

To see how different something looks once you have a mental model for it already built, look at the following interface:

Afsefioj:
Jheisp:
Diep:
Bivi:

It's just some fields that seem to have nothing to do with each other. Nothing really suggests what should be entered in them or how they would be used. Now look at the same interface labeled correctly:

Protocol:
Server:
Port:
Path:

Now, because you already know what a URL is, the fields make sense. You see how they relate to each other and can think of some possible values. The structure in your brain that stores what a URL is helps you understand this interface. Without that information in your brain, the interface wouldn't help you understand what the program is about.

This is radically different from the way programs work. Computer programs always have the internal data structure already decided on, and coded into the program. Human beings, on the other hand, have no preset structure, so the first thing you must do is give them the structure that the rest of the data will be a part of.

Documentation should be about creating mental models. The docs don't even have to be complete; once a human being has a mental model, they can discover a lot of information on their own without instructions. But without the model a person is lost and can't do much more than mindlessly follow directions.





Monday, October 25, 2010

Everything Is Interface

There’s a myth that programmers are divided into flighty, sensitive types who can create beautiful user interface but can’t do any heavy lifting, and code jocks who can write multithreaded servers but don’t understand usability.  In truth, everything is user interface.  For your program to do anything, it must interface with something else, be it the operating system, a server, another program, or a human being.  And someone is going to have to learn that interface to use your program.  Source code itself is an interface between the programmer who writes it and the poor slob who has to maintain it.  Computer languages are interfaces between what you can understand and what a computer can do.  If your style of user interface is illogical and inefficient, then your coding style is probably the same.  As a programmer, you should strive to write code that is as slick and easy to use as a good user interface. 

Since all code is user interface, anything forbidden to user interface is forbidden to code and vice versa.  If you wouldn’t cover a screen with dozens of buttons, you shouldn’t write a class with dozens of public methods.  If you don’t use goto because it makes your code confusing and buggy, you shouldn’t force your users to visit screens at random to get their work done.  If you don’t want your users entering their data in a huge free-form field, then you shouldn’t store data in some giant string that needs to be parsed.  If you wouldn’t make your function’s actions depend on a mysterious global variable that’s squirreled away in some header file, you shouldn’t make your program’s behavior depend on a global setting that’s hidden in some inaccessible menu. 

This idea of code as interface goes deeper than just the surfaces I’ve been talking about so far.  When you write a method, the method signature is an interface between the code in that method and everything that calls it.  The public methods of a class are an interface between that class and the rest of your program.  Your logging statements are an interface between the program and whoever has to debug it.  What structure you choose to store data in is an interface between the values stored and the code which uses those values.  Everything is interface, and you must always keep that in mind as you code. 

Code itself is an interface because code is written to be read.  You will read your code months after you wrote it, maintenance programmers will read your code to fix all the bugs in it, and if you do things right, your testers and doc writers will know how to read code and be doing that to do their jobs.  Code doesn’t exist just to perform some action, code exists to communicate what the action is and why we’re doing it.  If code wasn’t meant to be read we’d use _1 and aBc as variable names.  Code is meant to be read so must be readable. 

Programmers have trouble coding these interfaces because they believe they’re interfacing with a computer.  But interfaces almost always boil down to an interface between people.  You may never meet this other person, they could be a language designer or a maintenance programmer; they could be using your server as a backend for their own web site or installing your software on their desktop.  Whoever they are, the decisions you make need to keep them in mind.  Programs are limited not by the computers that run them, but by the humans that use them. 

How many projects fail because these human factors are never considered?  Cool ideas get run into the ground all the time because nobody can understand the implementation.  Projects get patched to death by maintenance programmers who can’t understand them because the original developer is too busy or unavailable to explain it.  Programmers forget why they made some decision in the code and so revisit the same questions again and again and again with management.  Clumsy interfaces generate excessive calls to support, preventing a project from scaling beyond a handful of customers.  The success or failure of any project depends on whether any attention is given to the human beings involved. 

This is why I’ve called my blog Hacking the Ultimate Machine.  The human brain is the ultimate machine and understanding what it can and can’t do is central to being a good programmer.  Ignoring human capabilities and limits means ignoring the capabilities and limits of your own work.  And that means putting out software that is no better than the average half-baked junk.  Paying attention to the human interfaces that make up your code is necessary to achieve anything worthwhile in programming.