Wednesday, October 26, 2011

How Do You Forward To An Action In Struts 2.0?


In the old Struts 1.0, you could forward from one action to another, letting the second action handle the request. There doesn't seem to be anything in Struts 2 that lets you do that. If you search on the Internet for answers, you get a lot of replies about using redirect. But redirection loses the input parameters. It has it's place, but it isn't the same as letting another action handle a request that comes in. So how do you forward?

The answer is you don't. Think about it. If one action is calling another, then they must have some code in common. Since we're good object-oriented programmers, we don't want to repeat code. This implies that the two actions are really the same class or one action extends the other. I'll show how to do either version in the example below. This example is somewhat contrived and simplified, but it will give you the basic idea.

Suppose you have a summary page, that lists documents the user owns. On the page is a number of drop down lists, that can be used to filter the document list.


Type: Date:
NumberDescriptionDateTypeAction
10-9345Order for 1000 #2 pencils10/11/2011PendingEdit | Delete
31-99AAHand wash mimeograph machine and rebuild12/31/1995CancelledEdit | Delete
AA-1239New hard drive09/30/2001CompletedEdit | Delete
08-1127Copies of latest security bulletin03/13/2010In ProcessEdit | Delete
11-2563Test drive of new car05/07/2009CancelledEdit | Delete



So the filters are sent into the action through the request, and used to control what documents get listed. But the users want the application to remember what the filters were set to, even after they navigate away from the page. This implies the filter values are stored in the session. So sometimes the summary action needs to take the filters from the request, and sometimes from the session.

Here's the action classes that do this.

The first action takes the filters from the session, and uses them to get the document summary to display.

public class SummaryAction extends ActionSupport
                           implements SessionAware {

   ...some skipped boilerplate...

  public String execute() throws Exception {
    this.docType = (DocumentType)this.session.get(DOC_TYPE);
    this.dateRange = (DateRange)this.session.get(DATE_RANGE);
    this.docList = this.service.getDocs(this.docType, this.dateRange);
    return ActionSupport.SUCCESS;
  }

}
The second action extends the first one, gets the filters from the request, and then calls super.execute():

public class FilterAction extends SummaryAction {

   ...some skipped boilerplate...

  public String execute() throws Exception {
    this.session.set(DOC_TYPE, this.docType);
    this.session.set(DATE_RANGE, this.dateRange);
    return super.execute();
  }
}
No repeated code, one action “forwards” to another, and as a plus, instead of going through the Struts framework to do it, we just use Java.

If you don't want to create a whole other class just for a little code, there's a Struts trick you can use. In your Struts configuration XML you can tell which method should be called on an action. So you can rewrite the first class to have another method like so:

public class SummaryAction extends ActionSupport
                           implements SessionAware {

   ...some skipped boilerplate...

  public String execute() throws Exception {
    this.docType = (DocumentType)this.session.get(DOC_TYPE);
    this.dateRange = (DateRange)this.session.get(DATE_RANGE);
    this.docList = this.service.getDocuments(this.docType);
    return ActionSupport.SUCCESS;
  }

  public String filter() throws Exception {
    this.session.set(DOC_TYPE, this.docType);
    this.session.set(DATE_RANGE, this.dateRange);
    return execute();
  }

}
Then in the struts.xml:

<action name="summary" class="org.hack.SummaryAction">
    <result type="tiles">hack.summary</result>
</action>

<action name="filter" class="org.hack.SummaryAction" method="filter">
    <result type="tiles">hack.summary</result>
</action>
Again, no repeated code, one action follows another, and you don't need to go through the framework to get there.

I've been having a hard time coming up with new things to say about the programming and the human mind, so I decided to branch out a little. Every once in a while I'll post a page giving a solution to a problem I had. I'll stick with problems that I couldn't find a solution to on the internet.

Friday, September 23, 2011

What's Wrong With Them?

What's wrong with our users? They try to use our software without bothering to learn anything about it and then complain when they run into trouble. They're confused by the terminology we use in the program and try to translate it into something that's more familiar to them. They don't know how to use anything right, and instead do the strangest things to get their work done. For instance, when they need a new field to store some data, instead of asking for it to be added they just start typing special codes into another one of the fields. This inevitably causes data problems down the road. Can't they do anything right?

I don't think users are stupid or difficult. Instead, there's something about their relationship with programmers that makes them seem that way. Look at how programmers act when they're users themselves. How do programmers act when they use the software they need to get their job done? Do they read the manual before doing anything? Do they only use the software in the recommended way? When the software doesn't work quite like they want do they patiently wait for an update or do they hack in a workaround that they know is going to cause problems? We all know the answers to these questions. When programmers are users they act just like users. If you listen to them complain about the software they use you'll notice they even sound like users. There's nothing strange about user's behavior; it's human nature. Everyone treats programs like that. So why do programmers get so worked up about it?

Programmers emotionally identify with the programs they write. To them, the program is their creation, an expression of their own self. To the user, a program is just some piece of junk that's supposed to help them get their work done, if only it would work right. The user doesn't think they're hurting anyone's feelings when they criticize a program, but it's amazing how rejected you feel when someone doesn't like your work. Programmers aren't supposed to show these hurt feelings and that's when the trouble begins.

There's a few different ways to suppress hurt feelings. One is to attack the person who's hurting you. If the users are dumb or overly critical then their judgment doesn't count, so looking at users like that is one way programmers cope with criticism. Realistically, if the system isn't making sense to the users, then it's probably the programmer who didn't understand what the users needed, not vice versa. Instead of accepting the painful truth that they haven't done their job, programmers project that failure onto the user. Programmers trick themselves into believing users have poor judgment, all to not face up to their own poor judgment.

The more common method of escaping from painful feelings is to hide. Most programming is done in complete isolation from the users and their daily work. The majority of programmers never meet anyone that uses their programs, much less actually sit down and watch them work. Yet few people in the business think this is strange or needs to change. No matter how complete requirements are, millions of questions come up while writing the code which need to be answered somehow. Usually you guess. Guessing by it's nature is inaccurate. So the isolation, created to avoid users and their questions, actually make the software worse. The internet, which was supposed to make everyone more connected, has eliminated software installation, so programmers don't have to be physically near users when updating software. Programmers are more isolated than ever and the software suffers.

What needs to happen to fix these problems? Programmers need to identify more with users instead of the programs they write. As long as programmers consider their relationship with users adversarial, they will react to any criticism, feeding their own hostility and isolation. Programmers need to recognize that they have a part in the breakdown in communication with users and strive to fix their part in it. That means taking users and their problems seriously.

Saturday, June 25, 2011

Emergency Room Burnout

By nature, you ignore what's familiar to you. Things that happen all the time become background noise to you, something that barely registers. This happens when you learn something as well. When you first learned to drive a car it took a lot of concentration, but now it's probably so second nature you barely notice you're doing it. This frees up your mind to pay attention when something changes drastically, because that's usually the sign of danger, something you need to notice. This instinct works well normally since ordinary things can usually be safely ignored, but it breaks down in certain artificial environments.

In an emergency room, becoming numb to the everyday means becoming numb to emergencies. How can you get excited over a patient when you know another one is just behind them? It doesn't help that many emergencies are anything but. Many people come to the emergency room with trivial complaints, many are there because they can't take care of themselves. These people have to be treated the same as true emergencies, but that just makes it easier to treat everyone callously. Bureaucracy naturally grows around ER medicine because a mistake can be life or death, but the bureaucracy just adds to the numbing effect. And people die. When death becomes ordinary, your attitude toward death becomes very different from most people. To an outsider, this behavior can seem callous or arrogant, but it's really a human instinct perverted by the artificial environment of the emergency room.

Many programming groups are run like emergency rooms. Everything sent in is labeled "rush, stop everything!" After awhile it becomes impossible to be excited about problems. What's the point of rushing to fix something when another bug will be right behind it? Once you become numb to the infinite progression of bugs, it becomes impossible to get excited about users' problems. This leads to a callousness that users find infuriating. Where a user sees a piece of software as a necessity to get their job done, the programmer sees a piece of junk that never worked right and never will. When you walk through an IT department and see people laughing and goofing off when a major outage has occurred, you're seeing the detachment that comes when disaster is everyday. When everything's an emergency, nothing's an emergency.

Many managers try to fix this by upping the threat level. This works for a little while, but like any addiction cycle, programmers quickly become used to the higher dose and return to their numb daze. Raising priorities feels right because what you're trying to do is motivate people, but it doesn't work because the sameness of emergencies is what's causing the problems. Human beings recognize things through contrast, and without that contrast everything blurs together. People also need a mental break from emergencies to prepare themselves for the next one. If they don't get a break as part of their week, then their overloaded mind will shut them down anyway, and will probably not pick the shutdown time based on management priorities.

The solutions for these problems are written in many programming books. Increase usability to minimize user complaints. Test to increase reliability. Rotate personnel off maintenance so they don't get burned out. These techniques have been adequately explained elsewhere. What I want to emphasize here is that human psychology is what makes these techniques necessary. Human beings aren't like machines; they can't do the same thing over and over without it effecting them. People need variety and contrast to properly react to events around them. When emergencies are rare, they get treated like emergencies.

Tuesday, May 10, 2011

The Bad Tourist

Think of a country, it doesn't matter which one. Somewhere in this country, far away from any cosmopolitan city, is a tourist that hasn't bothered to learn the native language. Red-faced and cursing, he's yelling at the natives in his own language in the mistaken belief that anything can be understood if it's said loud and often enough. Most natives avoid him, looking terrified. If any of his countrymen are unfortunate enough to be near he will corner them, muttering about the ignorance of people who can't learn a language so easy a child of three can speak it. If his anger is deep enough, he will swear that the natives are pretending to not understand just to drive him crazy. His frustration blinds him to his own ignorance, and so prevents him from learning a better way to communicate.

There's another type of tourist as well. This tourist has tried to learn the native language, but his skills are so poor few can understand him. Many talk to him slowly, enunciating each word, just like you'd talk to a baby. Even worse, some natives will mistake his halting sentences for fluency, and will answer the tourist with a burst of incomprehensible speech. But after seeing the dumb, frightened look on the tourist's face, the native reverts to baby talk. This sort of tourist feels humiliated by his treatment and the evidence of his ignorance. He often will change into the first type of tourist by the end of his trip. It's easier to retreat to what you know than go through the pain of learning something new.

Programmers are tourists in the user's world. Programs are written for a specific audience, and the audience has it's own dialect for talking about their work. Oftentimes developers will not bother to learn this new tongue, and instead run around shouting their own language, which sounds like gibberish to users. The programmer assumes users are too stupid to understand, but what users see is a lout who can't be bothered to learn anything about the country he's visiting.

Some developers do try to learn the native language, but don't go far enough. They seize on one or two user terms and use them constantly. This can sound both patronizing and ignorant to users. And when users ask a detailed question the programmer is immediately lost. Often he will try to hide his lack of fluency by pretending to understand, like a foreigner nodding through incomprehension. The pretense fools no one. The users feel frustrated, and the programmer, in embarrassment, retreats to his shell. If translation problems aren't seen as a chance to learn more from each other, the opportunity to improve the users' system is lost.

This isn't all the developers' fault; users do this too. Many users don't bother to learn anything about computers and so have unrealistic expectations about what can be done and how soon. This naiveté leads to frustration with the development process, and to the common belief that programmers are messing up on purpose. These users get trapped in the same situation as the bad tourist: their lack of education creates even more distance between them and the people they're supposed to be working with.

Language barriers create frustrating emotional binds, which make working together hard. But the emotional symptoms are good in a way, since they can be used to diagnose communication problems. Whenever someone takes on the personality of the bad tourist, repeating himself over and over, frightening others away, and swearing the natives are plotting against him, you can be sure that there's a language barrier between him and whoever he's arguing about. This is most useful when diagnosing yourself, because it's harder to see these things when you're trapped in your own emotional storm. When you've spotted a communication problem, remember that the solution is not to say the same thing in different words. What's needed is a willingness to learn something about the other side.

Wednesday, March 30, 2011

Stop Being Lazy

Like all human beings, programmers are naturally lazy. Sometimes this laziness can be positive, when they build an easier way to do something, or avoid complexity. But laziness usually causes problems. It trades a quick fix today for a long, arduous bug fixing session down the road. Unfortunately, programmer laziness is harder to recognize than other kinds, especially when many programmers cover it up by inventing fake technical reasons for it. Let's look at how programmers can be lazy.

Programmers usually look for a solution that’s simple for them to implement, not something that’s simple for anyone to use. This gets things done quickly which pleases management, but it makes users' lives a misery. This preference for programmer performance over user performance has serious consequences. The whole point of automation is to reduce the workload and increase the productivity of users. If the program is sacrificing users' productivity to programmers' laziness, it's flying in the face of what programming is supposed to be about. What's easy to use should always be more important than what's easy to program.

Programmers grab the first solution they think of, instead of looking for other, better ones. In most cases, the first solution is not the best, so looking further afield is necessary to program well. Getting locked in to a design is another case of saving time at first and paying for it later. With any big decision a few alternatives should be considered before going ahead with one. But never believe that there is a perfect design waiting out there for you. Every design has trade-offs and compromises, most of which you won’t understand until it’s already implemented.

This laziness about selecting alternatives plays out in another way too. When writing something, a programmer makes a huge number of decisions; some right, some wrong. To be a good programmer you need to recognize your bad decisions and rip out the code that implements them. Unfortunately, programmers naturally resist tearing apart something they’ve already written. There’s an element of laziness to it, but it’s more a problem with focus. It’s hard to step back and look dispassionately at what you’ve done and admit you made a mistake. As a result, systems get clogged with all kinds of junk. This not only makes it harder for the maintenance programmers, it can slow down the system.

When the system goes into production, it's too late to clean up. Pulling out the bad code might create more bugs than it fixes, so you'll be discouraged from doing so. As a result, production systems get filled with zombie code – dead code that no one dares touch, so it never gets deleted. The bad ideas in the code eventually percolate up to the interface, making the users miserable. Once the users complain enough, the junk will have to be removed. Wouldn’t you rather fix things before it gets to that point?

Not only should you fix things before the users find out, it’s easier to recognize bad ideas as you write, and easier to remove them while they’re still fresh enough that you understand what you were doing. Young programmers are usually resistant to cleaning up after themselves. Coding anything is such an effort for them that they abandon their mess in frustration and stagger off to the next disaster. But once programmers become confident and experienced enough, they should learn to reread their code and reorganize things that don’t work well. This will actually speed up the coding process because time won’t be wasted programming around junk.

Programmer laziness causes a lot of the problems we see in computing today – kludgey interfaces, inefficient code and poor performance. The solution is no different from what a good writer does; reread code as it's written, try it out, and keep the ultimate goal in mind. The goal of programming is making things easier for users. When that's central to what you're doing, it's easier to make the right programming decisions.

Tuesday, March 15, 2011

Writers As Designers

In too many offices, the documentation specialists are isolated from the rest of the team. The programmers usually think of documentation as nonsense, and don't think that writing clear English is a skill even though they can't do it themselves. The doc specialists are frustrated by confusing software which nobody can seem to explain, and insulted by programmers who hold in contempt anyone who can't write code. Since both sides dislike each other it's easier to not talk. This is too bad, because a writer's skills are necessary to program well. Writers can contribute in many more ways than just putting together manuals. Every step of a programming project can be improved by having writers as a part of the team.

A project begins with listening to what users want, and then trying to translate that into a consistent story. If this isn't done, or is done badly, it's likely that the users will be missing things they want, require extra training to understand the system, and possibly reject the system out of hand. Building a system out of the user's language forestalls these problems. This skill, of translating an undifferentiated mass of ideas into a narrative is what writing is. Doing this requires no technical knowledge, just an ability to listen and think, and then translate that into a system. This is an area that writers shine in.

Including writers on the design team can also help because they aren't programmers. Programmers can get bogged down in technical detail to the detriment of the design. Also programmers have a tendency to make up technical excuses for being lazy. Many times programmers will settle for a poor design because a good one seems like too much work. Another thing programmers are lazy about is the look and feel of applications, mostly because fixing cosmetic problems is usually arduous and boring. Having someone on your team that can push back against that mentality is important. It keeps the team honest.

Writers help with the design in other ways. When a writer finds something difficult to document, that's a warning sign. It usually means you need some clarification from the users, or the programmers need to go back to the drawing board and think up something that's easier to explain. Forcing writers to document things that are confusing or ambiguous means forcing bad design on your users. But if writers are full members of the team, they can tell you about these problems before the users see them.

Writers are also part of the test team. Every piece of documentation is also a test plan. The first thing a writer should do after finishing a piece of documentation is fire up the application and test what they've written. If things don't go as they should, that's another warning sign. Either the documentation needs to be rewritten to explain extra steps, the program needs to be fixed or the design needs to be revisited. In any case, the mismatch between documentation and code lets you know that some more work needs to be done.

Writers should be full members of programming teams. They can contribute to the design of the project, and are able to spot problems before the users see them. If writers are considered full team members, they'll be more willing to share problems they're having, which many times are signs of deeper problems in the application. Writers should be brought out of their isolation and into the team.

Tuesday, March 1, 2011

Label Considered Harmful

Code is straightforward and logical, but because it's written by human beings, it's as vulnerable to superstition as anything else. One of the most detrimental superstitions is the fear of early return. Convoluted nested ifs and pointless temporary flags are created just to avoid early returns. Early returns are feared because they are believed to be the same as gotos, but more awful code has been written to avoid early returns than was ever written with the goto statement. Although the return statement is superficially like a goto, it was never the goto statement that was the real problem with goto programs. If we look at why the rule forbidding goto was made, we'll see the real culprit.

Superstition begins when a rule's reason is forgotten, and the rule is blindly obeyed. Most programmers today know that goto is wrong, but never worked on a goto program, so don't know why goto is forbidden. The answer has to do with readability and information hiding. Each statement in a program changes the state of the program. How easy it is to understand the state change depends on what statement is called. Let's look at some examples.

b = 10;
c = a – b;
if (a <= 25) return;

After these statements execute, we know that a is greater than 25, b is ten, and c is ten less than a, so c is greater than 15. Notice that the return statement actually increased our knowledge about program state, by eliminating any a's less than 25. If we replace the return statement with a goto statement, we can reason similarly about program state.

b = 10;
c = a – b;
if (a <= 25) goto label1;

The goto statement is not quite as meaningful as return. A return means we're done with whatever the current method is trying to do, so if the current method has a meaningful name, we understand what the return means. A goto has different meanings depending on where it goes. Is it going back in the program to try and get a better value of a? Is it going to a special routine to calculate something different? Is it skipping over the next chunk of code since it doesn't have a good value for a? But even though there's this ambiguity with the goto statement, we can still reason fairly well about program state.

Now look at the label statement, the statement that gets executed after a goto.

  b = 10;
  c = a – b;
label2:

After label2 is executed, what do we know about program state? Nothing. The statement 'goto label2' could be anywhere in the program and before that statement a, b and c could be set to anything. We would have to find every instance of 'goto label2' in the program and read the code around it before we could have any idea what the program state is. This could be exceedingly hard in languages where labels are numbers and can be computed. This is what makes goto programming so difficult to understand and debug. It was never the goto statement itself that caused these problems; instead it was the passive label that received the goto.

And here's where the human mind gets into trouble. Because people are naturally attracted to an action like goto instead of a passive statement like label, all the negative press is directed toward goto. But the real problem with unstructured programming is having spots in the program that can be gotten to from anywhere else in the program.

Tuesday, February 15, 2011

Between The Cracks

All of computer development is centered around building systems, not the glue that holds different systems together. This is like building a wall of bricks without using mortar. Such a wall might be strong, depending on how heavy the bricks are, but it's never as strong as bricks with mortar. Yet whenever these systems fail, people tend to say, “I guess we need heavier bricks.” Something else is needed.

Many times I've seen users print data from another system and then enter it manually in their own system. The excuse given is that human eyes need to review the data before it's entered. But if the data is that important, wouldn't you want to automate the review process as much as possible? It's not hard to create a queue that would pull the data from the other system and then allow users to review it before pushing it into the new system. Then you could automate away the tedious parts of data entry, making it more likely that the data is correct. The interface between systems is typically where data integrity has to be addressed, but usually this part of the system is an afterthought. Think of it this way: if all the interfaces into and out of a system are manual, have you really gained anything by automating?

The interface between user systems is important, but it's not the only crack that gets neglected. The interface between the user system and the programmers working on it is important too. Installation and update methods are usually tacked on at the end of a project instead of being thought about from the beginning. Many times updates are in the form of a file that's manually copied to the system. But manually copying a file is an error prone task – people copy the wrong file, put it in the wrong place, or forget to delete the original file. This isn't even mentioning the mess created when trying to back out a change that didn't work. Yet many insist this manual work is needed to keep control of what's going on, even though this sort of control is exactly what computers were invented for. The exactness and consistency of computers is what can guarantee data integrity, and programs are a developer's data. Developers should be as concerned with the integrity of their software as users are with their data. Wouldn't it make more sense to have some sort of license server that grabs the right updates or at least can tell you when you try to install the wrong one? Instead this part of the system is neglected, leaving a gap that can bring down an otherwise solid system.

I've saved the worst for last. Although there are many integrated user systems and there are some programs that are able to update themselves, maintenance programming is still very primitive. Database audit information, telling who did what to which and when, is all stored in database tables where they can be searched in any way you can imagine. But log files, which are basically program audit information, are still stored in text files where they need to be read line by line. And this is if the original programmer remembered to add logging. Many times programs fail silently, leaving no clue why they gave up the ghost. Other times they display a cryptic error message to the user, which the user will have to memorize if the maintenance programmer is going to have any hope of locating what part of the program failed. In general dealing with program failure is a tediously manual task, which is why it's usually given to the least senior programmers. Yet there continues to be a lack of thought, from language designers down to everyday programmers, on how to improve this.

There are other systems that a program is plugged into, like configuration, documentation and testing. The interface with these things should also be as automated as possible. Filling in the gaps between one system and the systems it interacts with, whether these are other user systems or programmer systems removes a lot of the tedious and error-prone busy work. But it also makes a system more robust, because all the paths into and out of it have been automated.

Monday, January 31, 2011

Your Company On The Couch

Suppose you work on a huge, complicated program that has major problems. This monster is central to the business, runs all the time and has far and away more bugs than any other program in production. The amount of time being sucked up just fighting the problems has management thinking it's time for some kind of rewrite, but everyone's afraid of what that would mean.

Look a little closer. Examining what bugs have been logged shows that the vast majority of them are against the part of the code that does data correction. The bad data that's causing the bugs is traced back to an obscure program that never had any bugs logged against it. If this little program is rewritten to stop sending bad data to the monster, most of the problems would go away. So even though the big program had the bugs logged against it, it was the small program that everyone thought was reliable that was causing the problems.

The big program is similar to what family psychotherapy calls the “identified patient”. The identified patient is the member of a family who the family agrees is the problem. The patient is usually the one with symptoms of either depression, neurosis, or others. But although the identified patient seems to be the only family member who isn't functioning well, family therapy sees the family as a system, and so the therapist looks at how the family works together to find out what's causing the identified patient's symptoms. Typically, a therapist gets better results from adjusting the behavior of other family members instead of concentrating on the identified patient. In fact, if the therapist buys into the family's assessment and only tries to address the patient's behavior, the therapist usually becomes part of the problem itself and won't be able to help the family function better. This is why it's important for a therapist to remain objective enough to look beyond the symptomatic family member to the full system of the family.

A company can be thought of as a family, made of departments and the software that serves them. Like families, some companies are close, some are impersonal, some seem well-adjusted and some seem dysfunctional. Just like in families, the dysfunction is usually concentrated in one department or system. But just because the breakdown appears in one place doesn't mean that the rest of the system around it isn't contributing in some way. In fact, like in the case of families, efforts to fix the dysfunctional part without looking at the rest of the system will likely fail.

Let's look at another example and try to see it as family therapist. Instead of concentrating on the specific problem, look farther afield at how the system is working or not working. At company X, some program keeps getting changed over and over. Careful examination discovers that one section is being changed back and forth at the request of two different departments. The departments are having the code changed because they have different ideas about how the program should work.

So what's the problem? Is it:
  1. The two departments should communicate with each other.
  2. The documentation should explain precisely what the program should do.
  3. New development should have discovered and resolved the contradictory desires when the program was written.
  4. Maintenance should have noticed the problem and mentioned it to someone.
  5. Management should have built a process to prevent such problems or at least detect them.
Of course each one of these suggestions can be pursued as its own problem with its own set of possible causes. You can look at this as a tree structure with the original problem as the root. In real life you don't need to search the tree to any great depth, but you have to at least look beyond the root. Probably all of these issues are contributing to the original problem, but some are worse than others. A few inquiries will tell you which of these problems have priority.

Although the examples above are at a higher level, this all applies to the nuts and bolts of programming as well. It's easy to get caught up in thinking that one part of your program is causing problems and ignoring other possibilities. But this tunnel vision blinds you to other possibilities around you and many times causes you to fail.  Imagination and objectivity are needed to look past what's right in front of you, and think about what other solutions are possible.

Tuesday, January 18, 2011

Tripping Over Your Own Feet

At the office everyone jokes about multi-tasking, in the sort of unfunny way one jokes about pain to be endured. But multi-tasking is a myth. There's been research showing it doesn't work but you don't need to look at a study to know that. Just watch someone try to walk and push buttons on their cell phone at the same time. Not only do they get in other people's way, walk into things and generally act like they're lost; it's also obvious they're having a hard time operating their cell phone. Multi-tasking means doing every job worse than if you did each one singly.

But there's something deeper going on here too. The most interesting thing about distraction is how nobody's really aware of their own. Human attention is positive; it only notices what it's looking at. When you don't have enough attention for your current tasks, you certainly don't have enough attention to observe your own functioning. So although it's very easy to see that the guy walking and pushing buttons is distracted, he's completely unaware of it. If he realizes he's having trouble, he just thinks that what he's doing is hard or confusing. And because of this he never thinks to sit down before clicking away on his cell. The first thing distraction removes is your consciousness of being distracted.

But it gets worse. When you're having trouble doing something, the natural instinct is to give it more attention. But when your difficulties are caused by divided attention, paying more attention just means you have less attention to give to your own functioning or upcoming obstacles. Distraction feeds on itself and also shuts off the one thing that can bring you out of distraction: self-awareness. When you do a lousy job on a few things you have to work harder to get them done and catch up on everything else too. Pretty soon you're working so hard you can't do anything right. At this point most people think they're burnt out and need a vacation. What they're really doing is breaking away from all the mental noise in the office that's keeping them distracted.

See, removing distractions doesn't just mean only doing one thing at a time. It also means giving yourself enough time to finish something before you start what's next. That time includes the seemingly useless time needed to decompress. A manager that spends all day in meetings without a break is just as distracted as a programmer working on three projects at once. His full attention isn't on any one thing, so nothing gets done particularly well. But like with any distraction, although it's obvious to all his employees, the boss is unaware of his underfunctioning.

One of the important cures for distraction is to become self-aware enough to recognize it in yourself. Look for the symptoms. Confusion, impatience, or a feeling of pressure or buzzing in your head are all typical. Symptoms can also be unique to yourself, and only you will be able to diagnose them. So you need to pay enough attention to your own functioning to notice when it drops. When you do notice it, you will know it's time to go take a walk, delegate some problem, or take a day off. Reducing your mental load, instead of working harder, is what keeps you sure-footed and in the right direction.

Tuesday, January 4, 2011

Writing Is Key

There are two things you need to learn before you learn programming. One is typing. If you can’t type, you’re all but illiterate today. Hunt and peck typists refuse to type anything out because it’s so hard for them, so they don’t write documentation, explain problems to users or management, or communicate their design to other programmers. If you can’t type, you’re stuck with face to face communication and cut and paste programming. You’re like a primitive caveman who has to rely on his memory for everything and if he can’t remember it, it doesn’t exist. Typing is necessary.

The second and more important thing you have to learn is how to write. You may think you can’t write. You may have fallen for that left-brain/right-brain hogwash and believe it’s impossible for you to learn to write. You may believe it takes an innate talent to write. You may think that you were cheated out of an education in high school and it’s too late to fix that. You may believe writing is a waste of time. You’d be wrong on all counts.

There’s plenty of community colleges that have writing courses. Such courses are on writing alone and don’t teach to a test, so you aren’t distracted by other junk and can concentrate on learning. You get to choose what to write about, which makes it easier to come up with ideas. You can take the course pass/fail, so you aren’t distracted by the nonsense of grades. Instead, you pay your money and learn a skill. You don’t need to become a great writer; I’m only a passable writer myself. You do need to understand writing enough to be able to express yourself to others. You need to rise above the average illiteracy of today; the clumsy wording and meaningless corporate-speak that is most writing you see at work.

Okay, so you can learn to write; but why would you bother? There’s a million reasons. When you have a problem that’s similar to something that happened six months ago, it’d be useful to have something written down about your earlier solution. When you’re looking at a program you wrote two years ago, it’d be useful to have the code documented, so you can quickly figure out how it works. When you need to add a couple of fixes the users asked for in the last meeting, it’d help to have that list written down, with a clear explanation of what the users wanted. Any program you write must have user documentation, and it’d be easier to hand your doc writer a decent list and description of features instead of spending hours rambling about what you remember coding. When you get a nasty email from the boss, it’d be useful to be able to explain yourself clearly so you don’t get in trouble.

You may be thinking that most of these examples are about things that are no more than three sentences long, so you don’t really need to learn to write. But despite the fact that children are graded and writers are paid by the word, writing isn’t about volume. The skill of writing consists of organizing your thoughts so you can convey them precisely. Even a one sentence description of a function can be improved by someone who knows how to write. And the act of writing, of wrestling with how to say something clearly, will clarify in your mind what you’re trying to do. Writing helps you understand what you need to do even before you start coding.

These skills carry over in another way too. A good writer will take a group of sentences, cut out the unnecessary, clarify the unclear, and rearrange everything until it flows properly. This should sound familiar because this is exactly what a good programmer does when coding. Writing is design. When you write you are exercising the same mental muscles you use when you design and implement a program. So improving your writing skills will not only help you communicate with your boss, your users, and your colleagues; it will also help develop the skills you need when you’re sitting at your desk pounding out code. Writing skills are fundamental to what you do as a programmer.