Thursday, July 31, 2008

Lol...Very interesting article on people types who will ruin your party...

http://www.holytaco.com/2008/07/29/8-people-who-will-ruin-your-party/

Throwing a party is a lot of work, so it’s a real disappointment when somebody you invited ruins it. Here’s 8 types of people to watch out for before you make your next invite list.

8. Person Who Insists On Cleaning Up Your Party While It’s Still Going On

WHERE YOU CAN FIND THEM: Right in front of you, asking if your drink is finished. Or, methodically moving through the party with a white trash bag and a look on their face as if they’ve been hunting Osama Bin laden for the last 6 years and have narrowed down his whereabouts to somewhere in this party.

WHY THEY WILL RUIN YOUR PARTY: Drinking a beer, much like sex, is far less enjoyable when someone is asking you if you’re finished every five minutes. It’s great that they want to help you clean up, but if you’ve decided to have a party, you’ve already resigned yourself to the fact that when it’s over, your house is going to probably look like the bathroom that Cary Elwes and Danny Glover woke up in, in the first Saw movie. I wonder if these people also decide to wipe their ass in the middle of taking a shit, just to “cut down on the work that has to be done when it’s all over!”

7. GUY WHO GETS WASTED IN THE FIRST HOUR

WHERE YOU WILL FIND HIM: Right by the fridge, bro, cause that’s where all the beer is!

HOW HE WILL RUIN YOUR PARTY: From the moment this guy shows up, everything he says has an exclamation point at the end of it. “This party rules, dude!” “I am ready to party TO-night!” “Let’s shotgun these, bro!” “Tits!” Then, one hour and 13 beers later this guy is incoherent, weaving on his feet and saying stuff like “Paartyyyygjlskdvm…” So, instead of kicking back and hanging out with your friends, you have to spend the rest of the night making sure he doesn’t puke on your couch, piss in your plants or crap on your coffee table.

6. Person Who Only Knows You

WHERE YOU CAN FIND THEM: About two feet to the right of you, standing silently, staring at either you or the person you’re talking to.

WHY THEY WILL RUIN YOUR PARTY: You invited them because during the four and a half minutes a day you talk to them at work, they seem pretty cool and/or really enjoy the impression you do of a fellow coworker. Except as soon as they get to your party, they tense up like Alex Rodriguez’s asshole during a game in October. You have two options at this point, 1) entertain them and include them in every conversation you have the entire night, like they’re your wife or husband even though you probably don’t know their last name, or 2) leave them on their own which leads to them standing in a corner by themselves, staring at you, causing your friends to ask you “I think that dude in the corner is planning on raping you.”

5. GIRL WHO STARTS CRYING

WHERE YOU WILL FIND HER: She’s usually holed up in the bathroom (taking up valuable toilet space) with three of her bestest girlfriends—all three of whom are overweight.

HOW SHE WILL RUIN YOUR PARTY: The worst part is that this girl isn’t crying because her parents just died or she lost a limb. She’s sobbing into a fistful of tissues because she always needs to be the center of attention. If everyone’s not focused on her and all her problems, she just starts crying louder about her job or some lame guy who won’t date her or how fat her friends are. This means you either sit there and let her bring down the vibe of your party or you take her outside and listen to her whine about absolutely nothing. If possible, pair her up with the super wasted guy. She’ll think he’s listening and he’ll think he’s going to score.

4. Person Who Just Got Dumped By Their Girlfriend/Boyfriend

WHERE YOU CAN FIND THEM: In any corner where they were able to trap and force someone to listen to them talk about how they “don’t know what happened,” and how it “seemed like things were fine and then all of a sudden she just said that she thought that we were different people now. What does that even mean? Do you know, because I sure as fuck don’t! I just miss her so much. My name’s Brian by the way.”

WHY THEY WILL RUIN YOUR PARTY: If I wanted people to get depressed as fuck at my party, I’d screen a copy of Schlindler’s list. The problem with these people is, they don’t care who they talk to, and no excuse you give will stop them from talking to you. “Hey, I gotta run to the bathroom,” “No worries, I’ll just wait for you until your done, unlike my EX girlfriend, who wouldn’t wait no matter HOW important it was to go to the bathroom and would just leave you with NOTHING while you were in there.”

3. Creepy Dude Who Tries To Bang Chicks At The Very End Of The Party

WHERE YOU CAN FIND THEM: Towards the end of the party, he’ll be wherever he hears the words “I can’t believe my friends left without me, they were my ride!” or “I’m so (hiccup) fucked up (hiccup) I gotta lay down or something.”

WHY THEY WILL RUIN YOUR PARTY: There’s a reason why this dude waits till the end of the party to try and score; he’s way too fucking creepy to do so when someone isn’t in some sort of desperate situation. Thus, although he’s there because he’s either family, a neighbor, or someone else invited him, you now have to hope to God he doesn’t take advantage of someone at your party, otherwise your party will not be remembered as “That Fourth of July Party at Bill’s house,” and instead be remembered as “that party at Bill’s house where that creepy guy tried to fingerbang Michele while she was puking.”

2. Couple Who Brings Their Baby

COUPLE WHO BRING THEIR BABY: Off to the side, on their knees, pleading with a 6 month old child to stop screaming or right next to you, asking you where he can dispose of a shit filled diaper.

WHY THEY WILL RUIN THEIR PARTY: Nothing says party like the sound of a screaming child and the stench of talcum powder and baby diarrhea! If there was a dude puking, shitting and crying at your party, would you be cool with that? No, you’d either be like “Who the fuck brought this guy?” But if you say that about a baby suddenly that makes you an asshole. Meanwhile, the party sucks becase everyone is being super cautious and attentive to the baby, as if the other 99% of the time that they’re not there the baby is barely eluding death due to unsupervision.

1. THE POLITICS GUY

WHERE YOU WILL FIND HIM: At the beginning of the night he usually stands right next to the front door where he overtly shows off his political button or T-shirt that says something like “Once You Go Barack, You Won’t Go Back” or “McCain = McStupid.” Then, after everyone shows up, he stealthily mingles from group to group while nonchalantly dropping lines like “Did you see what those fatcats tried to pull?” anytime there’s a lull in the conversation.

HOW HE WILL RUIN YOUR PARTY: No one in the history of parties has ever changed their political beliefs based on some asshole screaming about health care reform in the kitchen of a two bedroom apartment. His endlessly tiresome factoids and statistics about how much oil we consume and how the death penalty doesn’t work will make your guests either leave or kill themselves where they stand.

OTHER STUFF YOU MIGHT LIKE:

8 Truthful Celebrity Autobiography Covers

9 College Mascots That Should Be Real

The 8 Places You Probably Lost Your Virginity

Highlights Magazine: The Evil Version

7 Best Paternity Results Reactions

Tuesday, July 29, 2008

Java...fail.

from: http://itmanagement.earthweb.com/entdev/article.php/3761921

The 'Anti-Java' Professor and the Jobless Programmers
By James Maguire
July 29, 2008

When I noticed that this list of the popular programming languages placed Java in the top position, I picked up the phone to call Robert Dewar. Several months back I interviewed Dewar, a professor emeritus of computer science at New York University, about Java’s role in the college classroom.
What he said in that interview about Java in the classroom wasn’t pretty.

In essence, he said that today’s Java-savvy college grad is tomorrow’s pizza delivery man. Their skills are so easily outsourced that they’re heading for near-term obsolescence.

Dewar stresses that he’s not against Java itself. But the fact that Java is taught as the core language in so many colleges is resulting in a weak field of computer science grads, he says.

The reason: students’ reliance on Java’s libraries of pre-written code means they aren’t developing the deep programming skills necessary to make them invaluable. Colleges, alarmed by falling CS enrollment, have dumbed down the course requirements. Consequently, CS majors sail through a curriculum of Math Lite, earning a smiley-face on their papers for “developing” projects using pre-built libraries.

In the end, they graduate with a diploma whose value is questionable. They may be equipped for a dynamic career in fast food delivery, yet they are not fully prepared to compete against what is now a global field of rigorously educated software developers.

But What About the List?

But wait a second, Professor Dewar. (Actually, Dewar is both a professor and a CEO. He co-founded AdaCore, whose clients include Boeing and Lockheed Martin, so his experience includes decades in private industry.) I wanted to ask him, since this list of popular programming languges puts Java at No. 1 – ahead of biggies like C, C++ and Visual Basic – doesn’t that negate his theory?

I mean, if Java is this popular, maybe universities should teach it first. It called “being in touch with the real world,” isn’t it?

“This list is pretty meaningless in my opinion,” he says. “Using YouTube and Google to measure popularity just means that you pick up the buzz factor. Many serious application developers are not even present on the Web, which tends to overemphasize academic and hobbyist views. As the list itself says, this has nothing to do with quality of languages or level of usage.”

“Furthermore, Java is mainly used in Web applications that are mostly fairly trivial,” Dewar says, with his characteristic candor. “If all we do is train students to be able to do simple Web programming in Java, they won't get jobs, since those are the jobs that can be easily outsourced. What we need are software engineers who understand how to build complex systems.”

“By the way Java has almost no presence in such systems. At least as of a few months ago, there was not a single line of safety-critical Java flying in commercial or military aircraft. I recently talked to a customer who had a medium-sized application in Java, which was to be adapted to be part of a safety-critical avionics system. They immediately decided that this meant it would have to be recoded in a suitable language, probably either C or Ada.”


Robert Dewar (Ada, by the way, is down at No. 19 in the list of popular programming languages.)
Dewar says he has been deluged with emails supporting his view that computer science programs must move beyond – far beyond – focusing on Java.

“One was quite interesting,” he says. “It was from a software/hardware company in the Valley. The writer said that at the end of ads for software engineers, they added the sentence ‘This job will not involve any use of Java, or any Web-based application programming’, and that this single sentence was enough to essentially eliminate American applicants for their jobs – which was their idea; they felt they had wasted too much time interviewing incompetent college graduates.”

--
Questions for New CS Grads

Dewar says that if he were interviewing applicants for a development job, he would quickly eliminate the under-trained by asking the following questions:

1.) You begin to suspect that a problem you are having is due to the compiler generating incorrect code. How would you track this down? How would you prepare a bug report for the compiler vendor? How would you work around the problem?

2.) You begin to suspect that a problem you are having is due to a hardware problem, where the processor is not conforming to its specification. How would you track this down? How would you prepare a bug report for the chip manufacturer, and how would you work around the problem?

“I am afraid I would be met by blank stares from most recent CS graduates, many of whom have never seen assembly or machine language!” he says.

Lest he go too far, Dewar stresses that there are indeed some graduates who are unquestionably well prepared.

“There are a couple of top schools where I think the students come in knowing a heck of a lot and they leave knowing even more,” he says. “Places like Carnegie [Mellon] and MIT – those are not dummies who come out of those schools, by any means. So my comments don’t talk about everyone everywhere.”

Anxiety Tremors

To look back a few decades, universities once focused on programming languages that lent themselves to greater intellectual rigor, in Dewar’s view, like Fortran and Pascal.

But with the tech revolution of the 1990s, a blizzard of change swept through university CS departments.

“I can relate what happened at NYU and I think it’s probably pretty typical of many places,” he says. ”So we’re sitting around, and we ask, ‘What language should we teach?’ And it was “Oh, we’d like to teach Java.’ Now no one around the table actually knows Java. But they’re sure they want to teach it because it’s an upcoming language that the industry’s gonna use, and everyone will be doing everything in Java.”

“And it sort of swept the field – pretty quickly. It swept away Pascal. At that time there were about 200 universities teaching ADA as a first language in the U.S. And a somewhat smaller number teaching C and C++. And it largely swept those away.”

Java as a core teaching language is now universal. “A good indication is that the [college placement] AP class is exclusively Java. Used to be C and C++. So Java has a really dominant place in the university curriculum.”

As the sunny 1990s gave way to the troubled 2000s, two seismic shifts hit the software industry: the dotcom bust and a steady flow of outsourcing headlines. Both factors helped turn a healthy crowd of CS students into a comparatively smaller cohort. Enrollment trended ever downward. Academic deans felt anxiety tremors.

Here in 2008 the clouds are dark. “Everyone is desperately worried about the dropping enrollments – it’s dramatic,” Dewar says.

“We had 650 [NYU] undergraduate students in advanced courses, it’s now less than 300. A huge change. And you’ll find that repeated across the country, it’s not isolated,” he says. “ You can imagine, if suddenly half your students disappear, then your budget gets under extreme pressure. The dean is unhappy if he sees that happening.”

“These are market economies in most universities – no students, no faculty money, etc, etc.”

In response, colleges have compromised – heavily – to attract students, Dewar explains. “So two things: reducing requirements and getting rid of annoying math courses and things like that. And also trying to make courses ‘fun.’ I believe that computer science should be fun, but the fun should come out of solving problems – not making pretty pictures. That’s the danger, I think.”

The situation has the potential to turn into a vicious circle: Enrollment is down, so CS programs lower requirements. This in turn creates more CS grads who are replaced by outsourcing. As a result, news of this outsourcing keeps driving down CS enrollment – and the spiral continues.

--
Solutions (And a Ray of Hope?)

If it’s true that CS curriculums need to be improved, to be bulked up and made more in-depth, does Dewar foresee any improvements on the way?

“I don’t know,” he says. “We got a fair amount of interest going. And a nice thing that’s happening is that there’s going to be an ACM [Association of Computer Machinery] point-counterpoint, with me writing the point and some guy from some other university writing the counterpoint on this whole issue.”

“I just like to keep it as a topic of discussion. I know it strikes a chord among many university people, too. Part of the trouble with universities is that there are relatively few faculty members who know much about software. They know about the theory of computer science and the theory of programming languages. But there are relatively few faculty who really are programmers and software engineers and understand what’s involved in writing big applications.”

“It’s just not the kind of thing that universities are into, really. Because they tend to regard computer science as a scientific field rather than an engineering field. So I’ve always felt that was a weakness.”

Part of the problem is that programming is hard to teach. “Programming is a mixture of a highly technical skill and an aesthetic art. And that’s a very difficult combination.”

Dewar sees at least four ways to better educate programmers:

• More one-on-one mentoring “My most successful teaching of programming was when I worked one-on-one with people,” he says. Of course that’s difficult at the university level, with a teacher-student ratio of 30 to 1, or 90 to 1.

• Read a whole lot of good code “One critical way of learning programming is to read a lot of code written by really good programmers. Most students don’t get that opportunity.”

• Work in Groups “I would like to see much more in terms of group projects. Now they’re hard to grade, and grading stands in the way of education, often – and this is one of those ways. It’s the same problem a manager faces, really understanding how much everyone has contributed.”

• Realize that “copying” code has value “It’s interesting when you think that the message that we give to students is: ‘You must do this all on your own, you mustn’t borrow anything from anyone else.’ And then we put them in a real industry situation and the message suddenly turns to, ‘Reuse code as much as you can.’ Real life programmers get good at using chunks of other people’s code.

While those may all be good suggestions, Dewar’s voice alone isn’t enough to produce change. As he sees it, CS departments need to light a fresh fire.

“I’ve got all these people saying ‘Yeah, Yeah, Yeah,’ but that’s not good enough to say ‘Yeah, Yeah, Yeah’ – you have to do something.”

“One obvious thing is that we need to get much more industry presence in the ACM curriculum discussion, because that’s a real focus. ACM has a real influence over curriculums. Each year they produce a recommended computer science curriculum. So that’s a real entry point.”

One obstacle: “The inertia is huge. So many members don’t really want to learn new stuff, particularly.”

Still, amid his doubts, Dewar believes that a bright, well-trained CS grad can have a good career.

“My feeling is, it’s not a field where any idiot will be able to get a high paying job. Which at the height of the dotcom thing, any idiot could get a high paying. But competent, well-educated students will be able to find jobs without problem. I think that’s a fairly widely held view.”

--

Gross.

How to Run Injury-Free By Jeff Galloway

How to Run Injury-Free
By Jeff Galloway
For Active.com
June 13, 2007


One of my proudest accomplishments is being free of overuse injuries for almost 30 years. Below you will find the risks and the ways to avoid them.

My advice comes from working with over 200,000 runners in Galloway training groups, one-day running schools, Tahoe retreats, e-coaching and individual consultations. As the runners send me the results of my suggestions, I adjust the training and rest schedules. The current injury-free program is listed below, but I continue to look for better ways of avoiding problems and reducing downtime.

Fewer days of training per week

Those who run three days a week have the lowest rate of injury. I believe that almost all runners, except for Olympic candidates and world record aspirants, can be just as fit and perform as well running every other day. This may involve two-a-day workouts and more quality on each day.

Having 48 hours between runs is like magic in repairing damage. Those who insert a short and slow jog on recovery day (junk miles) are not allowing for complete recovery. When a client complains about lingering aches and pains, I cut them back to every other day and the problems usually go away.

Go slower on the long runs

After 30 years of tracking injuries during marathon training programs, I've found that most are due to running the long ones too fast. You can't run the long ones too slowly -- you get the same endurance whether you go very fast or very slow. Slow running will allow your legs to recover faster. The fastest that I want our Galloway Training groups to run is two minutes per mile slower than goal pace. Many run three or four min/mi slower and experience very fast recovery. Be sure to slow down as the temperature increases: 30 sec/mi slower for each 5 degrees of temperature increase above 60 degrees Fahrenheit.

More walk breaks

The continuous use of any muscle used the same way, increases fatigue more rapidly. Continuing to run continuously, with fatigued muscles, will greatly increase the chance of injury. You'll see on my Web site the recommended frequency of walk breaks, based upon pace. If you have aches and pains already, it is best to walk more often, from the beginning, than is recommended. The most important walk breaks are those taken in the beginning of the run, for these can erase all of the fatigue. Walk breaks will also tend to produce a faster time in all races from 5K up. The average improvement in a marathon among those who've run several without walk breaks is 13 minutes faster by taking the strategic walks.

Don't stretch if you have an ache, pain, or injury

Stretching a tight or injured muscle or tendon will increase the damage dramatically. Even one stretch will produce tears in the fibers, resulting in a longer recovery. Stretching a muscle that has been tightened by running can injure it within a minute. Massage is a great way to deal with the natural tightening produced by running. The tightening is mostly a good thing, allowing you to run more efficiently.

Be careful with speed training

Speed workouts produce a lot of injuries. You can reduce the odds of this happening by warming up very well, doing a few light accelerations as described in my books Testing Yourself, Year-Round Plan, Half Marathon and Marathon. Other important injury-reduction factors are the following walking more between each speed repetition and staying smooth at the expense of time. Don't strain to run a certain time. This is most important at the end of a workout.

Never push through pain, inflammation or loss of function

If you experience one of the above, stop the run immediately. Continuing to run for another block or another lap will often produce multiples of damage requiring weeks or months off for repair -- instead of days.

For more information, see Jeff's books Marathon, Half-Marathon, Running -- A Year Round Plan, Walking -- The Complete Book and Galloway's Book on Running, 2nd Ed. These are available, autographed, from www.RunInjuryFree.com. Join Jeff's blog: www.jeffgallowayblog.com

Healty diet foundations...just add meat. ;)

Snagged this from zenhabits:
http://zenhabits.net/2008/07/the-building-blocks-of-a-super-healthy-diet-with-a-sample-meal-plan/
--

The Building Blocks of a Super Healthy Diet (with a sample meal plan)

Most people know how to eat healthy, and know that they should — it’s just that when it comes down to implementing this knowledge, there’s a bridge that needs to be crossed from knowledge to action.

How do you actually eat healthy, instead of just knowing that you should eat healthy?

Create a meal plan, constructed with super healthy foods that you enjoy eating.

Now, there are three parts of that solution, if you look closely, and all three parts are equally important:

1. Create a meal plan. Without this, you’ll just know what to eat, vaguely, but you need to actually make a plan and implement it (meaning, go shopping for the foods in the plan and actually cook the foods and eat them).
2. Super healthy foods. A meal plan without this doesn’t get you to where you want to go. Build your meals around stuff that’s really good for you. You can add other stuff, of course, but the super healthy stuff should be the majority of the food.
3. Food you really love. This is key. If you don’t enjoy the foods, you won’t stick with the plan for long. No one can eat food they don’t enjoy for more than a month or so (usually less). It’s why most diets fail — anyone can stick with a diet for a couple of weeks, but if you feel that you are suffering by eating it, you’ll fall off it after a little while. Instead, make sure you love your food. Add variety, of course, and mix up the plan every few weeks, but stick with foods you love.

Given those simple components, the solution doesn’t seem so hard, does it? And with a super healthy meal plan like this — one that you love — you can pair it with some exercise and get healthier than ever.

What follows are some of my building blocks. They aren’t the only possible building blocks, and you shouldn’t use them exclusively, but they’re a good starting point for anyone. Below those building blocks are some sample meals you can use, but only if you love these foods like I do. Instead of following it exactly, use it as a starting place, as a few ideas you can use to construct your own meal plan — with foods you love, not ones that I love.

Super Healthy Building Blocks

Spinach and other greens. Spinach is my favorite of the greens, but other good ones include kale, bok choi, collards, dark green lettuce (skip iceberg), and other similar greens. Try to build a couple of your meals around these greens, as they are high in fiber, vitamins and minerals. And best yet: super low in calories. You can eat a whole plate of greens and while they can fill you up, you couldn’t possibly get fat on them (unless you added a bunch of butter or fatty dressing or something like that).

Avocadoes. I love these things. Full of good fats and good flavor, avocadoes are perfect for salads, sandwiches, wraps and more.

Tomatoes. There are other good fruits and veggies, but tomatoes are one of my favorites, not only for their nutritional content but because of the flavor they add to any dish — salads, sandwiches, pastas, soups, anything.

Fruits. Don’t worry about their “carb content”. Fruits are incredible snacks, because they are filled with fiber and vitamins but are low in calories. I eat lots of apples, oranges, bananas, mangoes, pears, grapes, melons. I like to get a big back of small apples and just munch on them whenever I’m hungry. I also add fruits to all kinds of uncooked meals, chopped up or as a side dish.

Berries. They’re fruits, but they’re so special to me that I add them as a separate item. I absolutely adore berries. They are like a dessert to me, eaten cold and slowly and with my eyes closed. I add them to cereal, yogurt, smoothies, desserts, oatmeal and more … and of course just eat them by themselves.

Nuts. Full of fiber and good fats and protein. I like to chop them up and put them in hot cereal or salads or stir frys, or just eat them raw and whole as snacks (almonds are my favorites). I also enjoy almond butter instead of peanut butter (although I eat both).

Beans. Great sources of fiber and protein, low in calories, you can eat beans all day long. I like them in chili, soups, tacos and more. Get a variety — red, black, pinto, white, lentils.

Whole grains. This is a broad category that includes all kinds of cereals, breads, wraps, brown rice, pizza dough, and more. Try to go for as much whole grain as possible — if you see “wheat flour” or “enriched wheat flour” it’s not as good. I especially like sprouted grains, such as Ezekiel sprouted bread or English muffins or cereals. Oatmeal is good (avoid instant) as is muesli.

Olive or canola oil. You need fats, but they should be the good kind. Avoid saturated, although a little saturated fat is fine. I usually use olive oil or canola oil, although there are other good ones too. Again, nuts and avocadoes also provide good fats. I also use ground flaxseed on lots of things for fiber and good fats.

Lean protein. As a vegetarian, I eat lean vegetable protein — lots of soy protein and beans and nuts. Whole grains also contain protein, as do other veggies. It’s not hard to meet your daily requirements, even with lots of exercise raising your requirements. However, if you’re not vegetarian, fish and lean poultry are best, and lean red meat can be included if you don’t eat too much of it. Note: Please, let’s not get into another debate about soy protein or meat! Let those sleeping dogs lie.

Lean calcium. I try to stick to soy sources, but that’s not necessary for good health. However, try to stick with lower-fat versions, as whole dairy can have too much saturated fat. Lower-fat milk, yogurt, and cheese are good choices. Soy milk and yogurt are great because they are very low in saturated fat.

A Sample Meal Plan

This is not something you should just adopt wholesale, without making changes. In fact, if these are foods you don’t like, ditch the whole thing, but use it just to get an idea of what you can do. These are foods I love to eat, but you should choose your own.

Also remember that I’m not a dietician. I’ve run these meals through online calculators, and most of the time you’ll get plenty of all the things you’ll need, from protein and healthy fats to the major vitamins and minerals, including calcium and iron. But don’t take my advice as the advice of an expert.

Each day, you would choose one of the meals from each category (more from the snacks), or mix them up if you like. Be sure to get a variety, and change the options every few weeks or so.

Breakfasts

1. Hot oatmeal (using rolled oats) with chopped fruits or dried fruits, flaxseed, and/or berries.
2. Kashi cereal with soymilk and berries or other fruits.
3. Sprouted grain toast with almond butter, chopped fruits on the side.
4. Scrambled tofu with tomatoes, mushrooms, spinach, onions. (Try this recipe).
5. Fried brown rice — fry up with olive oil, onions, mushrooms, green veggies, tofu, soy sauce or tamari sauce. You can throw in some corn or carrots or other veggies.

Lunches

1. Veggie sandwich or wrap. Can have tomatoes, spinach or other greens, avocadoes, hummus, bell peppers, maybe some dijon mustard and/or Veganaise. Any combo that works for you. On thick whole grain bread or whole grain wrap.
2. Whole wheat pita with hummus. Add tomatoes and raw spinach and sprouts.
3. Veggie burger. Gardenburger is my favorite brand. On a sprouted grain bun, with dijon mustard and ketchup and maybe a touch of Veganaise, lots of veggies (greens, sprouts, tomatoes and avocadoes are my favorites). Add some homemade sweet potato fries (use olive oil and a little salt) if you’re feeling decadent. These fries also go well with the sandwich or wrap.
4. Amy’s Kitchen lunches. For when you’re lazy or in a hurry. Amy’s Kitchen has a whole variety of fairly healthy, vegetarian lunches made from whole foods. Very little processed stuff. The only weakness is that it’s usually high in sodium, but if the rest of your day is low in sodium (as most of these dishes are), then that’s not a worry.
5. Big salad. I like to use spinach or other greens, tomatoes, avocadoes, feta cheese, nuts, maybe some chopped fruit or berries, and a little bit of light vinaigrette (Newman’s Own is my favorite).
6. Leftovers from dinners or fried brown rice (see breakfasts)

Snacks

1. Fruits.
2. Chopped veggies. Carrots, broccoli, edamame are some of my favs. Dip in hummus if you like.
3. Nuts. Almonds are my favorites.
4. Protein shake. Good after a strength workout. I use soy protein, although whey is also a good choice, along with soy milk, frozen berries, banana and ground flaxseed.
5. Clif Bar. Good for before or after a workout (or during a really long workout, for that matter). My favorites are apricot or cranberry apple cherry.
6. Yogurt with berries or fruits and nuts.

Dinners

1. Tofu veggie stir fry. Just stir fry some onions, cubed tofu, and chopped veggies — various greens such as kale or bok choi work well, as do broccoli, bell peppers, carrots, anything really. Add some soy sauce or tamari, black pepper and anything else you’d like to add — nuts, sesame seed oil, ginger, garlic, a little honey all work well in different combinations. Serve over brown rice if you like.
2. Tacos. Some low-fat refried beans and/or black beans on soft corn tortillas with salsa (try Newman’s Own salsa or Amy’s), greens, tomatoes, maybe corn or even some Sour Supreme.
3. Chili. Here’s my veggie recipe. Great with brown rice or corn bread or on its own.
4. Spaghetti or other pasta. Cook any kind of pasta you like. Cook some onions with diced tomatoes and bell peppers and some tomato sauce and basil. Add some fresh Parmesan if you like. For a meatier version, cook some veggie “ground beef” (Bocca or MorningStar) with onions and then add some pre-made pasta sauce.
5. Homemade pizza. Get a pre-made whole-wheat pizza crust, add some pre-made spaghetti sauce, and then any chopped veggies you like, brushed with olive oil. Kale, broccoli, spinach, mushrooms, tomatoes, bell peppers all work great. Add some grated fresh cheese if you like.
6. Leo’s fabulous veggie soup. Simple awesome. Here’s the recipe. Will last you several days, even with a ridiculously large family like mine.

Monday, July 28, 2008

select random thoughts...

me: hot blonde doctors rule ;(
shane: who cares if she likes jason mraz, shes a girl shes supposed to like shitty music
me: yeah, but she said she didn't know what techno was ;(
shane: girls who like good music are usually ugly or whores
me: lol!!
me: i just told her that..and she agreed. thats a nice line of wisdom!

-- later

shane: if i ever get married i want to have a few best men, but at least you know you're the one that makes it ...
me: ..i think those are called Groomsmen ;p
me: if i ever get married, i wont have a best man, and my bitch of a wife wont have any bridesmaids either. im going to have a judge marry me in a court room with the scales of justice behind me.
shane: lol

OSX Server Woes - and I have to agree.

Here are some comments regarding the recent BIND problem and Apple's inaction in patching it thus far...and I have to say, the following two comments I must agree with, as I've had years of OS X server...Experience.

--
As someone that's cursed to administer an OS X Server machine, I have nothing good to say about Apple in general and OS X Server in particular. Apple's history of patching---or, in this case, not patching---stuff has been lukewarm at best and downright abysmal at worst. The Server 10.5.3 update introduced something that causes ClamAV to crash/reboot a Server machine when mail is turned on (since ClamAV is on by default. Nice one. They've had other stellar examples of their extreme lack of QA for their Server software, such as updating their included PHP to a version that was known to break Squirrelmail (the default webmail that comes with OS X Server), even though a fix had been available for months from the PHP maintainers.

I'm a huge fan of FreeBSD. I have been doing this OS X Server thing for more than two years now. I went in to it with an open mind, hoping that Apple wouldn't screw things up too badly. I was disappointed. The only things I've learned is that their Server QA is awful, they don't actually use their own Server software internally, their customer service is horrible when it comes to their Server stuff and their Server documentation is awful. I could rant about that for several pages. All of this leads me to believe that Apple really doesn't want to do well in the "server" segment of the market...Which is really too bad, cause they've finally got the hardware side of it to the point where there's not much separating them from most other low-end server vendors.

Now, that I've got that all that off my chest, Apple's dropped the ball on the BIND update. This is not surprising. Anyone that's administered OS X Server for any length of time probably feels the same way. It's so bad that I will suppress my OS X experience next time I am in the job market again; I hope to never work with OS X (particularly as a server) again and will do everything in my power to avoid doing so. I'm batting a thousand on persuading people interested in using OS X Server to use anything else...Apple really has to get things together or get out of the "server" market.

---

DVD/CD-Rom Drive problems ; Choppy Audio / Video

I was having problems with DVD-Audio and Video on one of our Laptops in Windows XP, it turned out to be transfer mode for the hardware controller in device manager; below is the solution that solved it for me:

First off, go to:


Start -> Settings -> Control Panel -> System

This will open up a display. From here, on the top of this new window click on
"HARDWARE"

From under this tab, click on DEVICE MANAGER.

Another window should open up with several listings. Look for the one called
"IDE ATA/ATAPI controllers" or something very VERY similier to this.

Click on the + next to the name, a list of other things should drop down under it.

From in here, we ONLY want to look at
SECONDARY IDE CHANNEL

This is because, such things like your CD-ROM, DVD-ROM etc are connected through this.

Now, this is what you need to look for in the Secondary IDE Channel

Right click Secondary and select Properties

Another window will open up, look for the Tab named Advanced Settings and click on it.

Under this tab you should see two box's.

DEVICE 0 and DEVICE 1

NOTE: DEVICE 1 under CURRENT TRANSFER MODE might state it does not apply. If so, ignore it, if it does not state that it is not in use, then do the same for DEVICE 1 as you do for DEVICE 0

In Device 0 it should read out as following, there should not be anything stating PIO unless your computer is fairly old (like... 1999 or older.. it varies):
-----------------------------------------
DEVICE TYPE: Auto Detection
Transfer Mode: DMA if available
Current Transfer Mode: Ultra DMA Mode 5
-----------------------------------------

Now, Current Transfer Mode can say something different.
EX: Mode 1 is a slower form, and Mode 5 is very fast as in Ultra Quick. So it may display something a bit different, as long as it states it is in DMA mode it should be alright. Also, it may say something like.. "Multi-Word DMA Mode 2"

IF
TRANSFER MODE: "PIO Only"
switch that over to "DMA if available" and restart your computer.
Once restarted, come back in and continue the checks from this point
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

IF
-----------------------------
TRANSFER MODE: "DMA if available"
Current Transfer Mode: PIO Mode
-----------------------------
Then we have a problem, if this is TRUE, then click on the Driver Tab in this window at the top.

From here, Uninstall Drivers.
It will give you a warning, no worries, continue on. Once you restart your computer it will automatically detect the devices and reinstall everything for you.

Once done, try playing your DVD and see if it works. If not, go back in and make sure everything is the way it should be.

If not, sorry, you could try this again if you'd wish.

Causes for this changing over to PIO mode:

Disk Errors on the cd/dvd disk itself can cause this. For an example of what caused mine:

I've been playing Final Fantasy IX on my laptop using an emulator. Though, alot of the copies of DISK 2 for the game were bad copies and have corrupted files on it. I kept trying to play past these corrupted parts.

Sometimes, this repeated use to read the disk and it having to skip back and fourth trying to kicked it into another mode.. this usually happens after five or so of these. A dirty lense causing it to have plenty of trouble or dirty disk could also do the same thing.

Wednesday, July 23, 2008

when I see things like this it upsets me:

Jan 9 2008 8:48 PM

Hey man! God has blessed us both with a great job! How awesome is He! He is even allowing us to work together! God is good! Thanks for your help man!

wooooo yay 4 god...hes letting us work together!!!
I'm sure he held a gun to the hiring manager's head, too.

Monday, July 14, 2008

http://eriwen.com/tools/grep-is-a-beautiful-tool/

grep is a beautiful tool
July 13th, 2008 | Category: Productivity, Tools

Global Regular Expression Print is a staple of every command-line user’s toolbox. As with find, it derives a lot of power from being combined with other tools and can increase your productivity significantly.

Following is a simple tutorial that will help you realize the power of this simple and most useful command. If you are on Windows and haven’t already, download and install Cygwin. If you are also new to regular expressions (regex), here is a great regular expressions reference to get you started.
Tutorial

Suppose we want to search for duplicate functions in all of our JavaScript files. Let’s start basic and work up to it. This technique can be used to search for a TON of duplicate items like:

* Duplicate HTML IDs
* Check how many times a CSS class is used
* Duplicate java classes
* many, many more…

1.
# Search JS files in this directory for "function"
2.
grep function *.js

# Search JS files in this directory for "function"
grep function *.js

The above command will print the lines containing "function" in all JavaScript files in the current directory (NOT subdirectories). Printing out line contents would be much more helpful if we knew what files they come from and their line numbers:

1.
# Print filenames, line #s, and lines that start with "(white space)function"
2.
grep -EHn "^\s*(function \w+|\w+ \= function)" *.js

# Print filenames, line #s, and lines that start with "(white space)function"
grep -EHn "^\s*(function \w+|\w+ \= function)" *.js

Depending on how you format your JavaScript files, something like this will omit comments, anonymous functions, and also words like "functionality" giving you better results.

1.
# Print a list of: function and sort it
2.
grep -Eho "^\s*function \w+" *.js | sort

# Print a list of: function and sort it
grep -Eho "^\s*function \w+" *.js | sort

-o prints only the part that matches the regular expression. -E options gives me extended regex and -h suppresses printing of the file name. I am then piping to sort which just sorts the output so it a list of function . If you don’t have a lot of files/functions to go through, you can just scan the list and then note the duplicate function names you see. Let’s go a step further for those that DO have a big list:

1.
# Print only duplicate function names
2.
grep -hEo "^\s*function \w+" *.js | sort | uniq -d

# Print only duplicate function names
grep -hEo "^\s*function \w+" *.js | sort | uniq -d

There we go! That will list only the duplcated functions. I know that we can expand this with awk or other stuff and get the file names and line numbers of the duplicates, but I don’t want to explaining the details of awk ;). I actually had it in this article and then removed it so leave a comment or contact me if you want the code for that.
Other Examples

1.
# Count the number of functions in all JS files
2.
grep -c function *.js
3.

4.
# Print lines that DO NOT have "function"
5.
grep -v function *.js
6.

7.
# List processes that match "pidgin" (non-Windows)
8.
ps -ef | grep pidgin

# Count the number of functions in all JS files
grep -c function *.js

# Print lines that DO NOT have "function"
grep -v function *.js

# List processes that match "pidgin" (non-Windows)
ps -ef | grep pidgin

Conclusion

grep is one of the most used command-line tools, often piped to for filtering output. Understanding it is essential to increasing productivity on the command-line. There is so much more to grep than what I’ve shown here, and it would be cool to see your best uses in the comments!

Saturday, July 12, 2008

Originally Posted by cvbn
"if you shop best buy you paid 2 much"

'Not only is this inaccurate but it is such a broad statement that it just sounds idiotic. Like any retailer their non sales price is usually higher than I would like but Best Buy has some very slick deals sometimes.'


---

Thats a load of tripe. Best Buy is never actually the best buy...but often it is like a 'pretty good buy that I could get somewhere else most likely for a bit less.'

Tuesday, July 8, 2008

Archive files on Linux...

http://www.ibm.com/developerworks/linux/library/l-backup/index.html?ca=drs-


Level: Intermediate

Carlos Justiniano, Software Architect, Ecuity Inc.

08 Jul 2004
Updated 03 Jul 2008

The loss of critical data can prove devastating. Still, millions of professionals ignore backing up their data. While individual reasons vary, one of the most common explanations is that performing routine backups can be a real chore. Because machines excel at mundane and repetitive tasks, the key to reducing the inherent drudgery and the natural human tendency for procrastination, is to automate the backup process.

If you use Linux, you already have access to extremely powerful tools for creating custom backup solutions. The solutions in this article can help you perform simple to more advanced and secure network backups using open source tools that are part of nearly every Linux distribution.

Simple backups

This article follows a step-by-step approach that is quite straightforward once you follow the basic steps.

Let's begin with a simple, yet powerful archive mechanism on our way to a more advanced distributed backup solution. Let's examine a handy script called arc, which will allow us to create backup snapshots from a Linux shell prompt.


Listing 1. The arc shell script
   #!/bin/sh
tar czvf $1.$(date +%Y%m%d-%H%M%S).tgz $1
exit $?

The arc script accepts a single file or directory name as a parameter and creates a compressed archive file with the current date embedded into the resulting archive file's name. For example, if you have a directory called beoserver, you can invoke the arc script, passing it the beoserver directory name to create a compressed archive such as: beoserver.20040321-014844.tgz

The use of the date command to embed a date and timestamp helps to organize your archived files. The date format is Year, Month, Day, Hour, Minutes, and Seconds -- although the use of the seconds field is perhaps a bit much. View the man page for the date command (man date) to learn about other options. Also, in Listing 1, we pass the -v (verbose) option to tar. This causes tar to display all of the files it's archiving. Remove the -v option if you'd like the backup to proceed silently.


Listing 2. Archiving the beoserver directory
   $ ls
arc beoserver
$ ./arc beoserver
beoserver/
beoserver/bookl.dat
beoserver/beoserver_ab_off
beoserver/beoserver_ab_on
$ ls
arc beoserver beoserver.20040321-014844.tgz

Advanced backups

This simple backup example is useful; however, it still includes a manual backup process. The industry's best practices recommend backing up often, onto multiple media, and to separate geographic locations. The central idea is to avoid relying entirely on any single storage media or single location.

We'll tackle this challenge in our next example, where we'll examine a fictitious distributed network, illustrated in Figure 1, which shows a system administrator with access to two remote servers and an offsite data storage server.


Figure 1. Distributed network
Figure 1. Distributed network

The backup files on Server #1 and #2 will be securely transmitted to the offsite storage server, and the entire distributed backup process will occur on a regular basis without human intervention. We'll use a set of standard tools that are part of the Open Secure Shell tool suite (OpenSSH), as well as the tape archiver (tar), and the cron task scheduling service. Our overall plan will be to use cron for scheduling, shell programming and the tar application during the backup process, OpenSSH secure shell (ssh) encryption for remote access, and authentication, and secure shell copy (scp) to automate file transfers. Be sure to review each tool's man page for additional information.


Secure remote access using public/private keys

In the context of digital security, a key is a piece of data which is used to encrypt or decrypt other pieces of data. The public and private key scheme is interesting because data encrypted with a public key can only be decrypted with the associated private key. You may freely distribute a public key so that others can encrypt the messages they send you. One of the reasons that public/private key schemes have revolutionized digital security is because the sender and receiver don't have to share a common password. Among other things, public/private key cryptography has made e-commerce and other secure transactions possible. In this article, we'll create and use public and private keys to create a highly secure distributed backup solution.

Each machine involved in the backup process must be running the OpenSSH secure shell service (sshd) with port 22 accessible through any intermediate firewall. If you access remote servers, then there is a good chance you're already using secure shell.

Our goal will be to provide machines with secure access without requiring the need to manually provide passwords. Some people think that the easiest way to do this is to set up password-less access: do not do this. It is not secure. Instead, the approach we'll use in this article will take perhaps an hour of your time, set up a system which gives all the convenience of "passphraseless" accounts -- but is recognized as being highly secure.

Let's begin by ensuring that OpenSSH is installed and proceed to check its version number. At the time this article was written, the latest OpenSSH release was version 3.8, released on February 24, 2004. You should consider using a recent and stable release, and at the very least use a release which is newer than version 2.x. Visit the OpenSSH Security page for details regarding older version-specific vulnerabilities (see the link in Resources later in this article). At this point in time, OpenSSH is quite stable and has proven to be immune to many of the vulnerabilities which have been reported for other SSH tools.

At a shell prompt, type ssh with the capital V option to check the version number:

$ ssh -V
OpenSSH_3.5p1, SSH protocols 1.5/2.0, OpenSSL 0x0090701f

If ssh returns a version number greater than 2.x, the machine is in relatively good shape. However, it is recommended that you use the latest stable releases of all software, and this is especially important for security-related software.

Our first step is to log in to the offsite storage server machine using the account, which will have the privilege of being able to access servers 1 and 2 (see Figure 1).

$ ssh accountname@somedomain.com

Once logged on to the offsite storage machine, use the ssh-keygen program to create a public/private key pair using the -t dsa option. The -t option is required, and is used to specify the type of encryption key we're interested in generating. We'll use the Digital Signature Algorithm (DSA), which will enable us to use the newer SSH2 protocol. See the ssh-keygen man page for more details.

During the execution of ssh-keygen, you'll be prompted for the location where the ssh keys will be stored before you're asked for a passphrase. Simply press enter when asked where to save the key and the ssh-keygen program will create a hidden directory called .ssh (if one doesn't already exist) along with two files, a public and private key file.

An interesting feature of ssh-keygen is that it will allow you to simply press enter when prompted for a passphrase. If you don't supply a passphrase, then ssh-keygen will generate keys which are not encrypted! As you can imagine, this isn't a good idea. When asked for a passphrase, make sure to enter a reasonably long string message which contains alphanumeric characters rather than a simple password string.


Listing 3. Always choose a good passphrase
   [offsite]:$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/accountname/.ssh/id_dsa):
Enter passphrase (empty for no passphrase): (enter passphrase)
Enter same passphrase again: (enter passphrase)
Your identification has been saved in /home/accountname/.ssh/id_dsa.
Your public key has been saved in /home/accountname/.ssh/id_dsa.pub.
The key fingerprint is:
7e:5e:b2:f2:d4:54:58:6a:fa:6b:52:9c:da:a8:53:1b accountname@offsite

Because the .ssh directory which ssh-keygen creates is a hidden "dot" directory, pass the -a option to the ls command to view the newly created directory:

[offsite]$ ls -a
. .. .bash_logout .bash_profile .bashrc .emacs .gtkrc .ssh

Enter the hidden .ssh directory and list the contents:

[offsite]$ cd .ssh
[offsite]$ ls -lrt
id_dsa id_dsa.pub

We now have a private key (id_dsa) and a public key (id_dsa.pub) in the hidden .ssh directory. You can examine the contents of each key file using a text editor such as vi or emacs, or simply by using the less or cat commands. You'll notice that the contents consist of alphanumeric characters encoded in base64.

Next, we need to copy and install the public key on servers 1 and 2. Do not use ftp. Rather, use the secure copy program to transmit the public keys onto each of the remote machines:


Listing 4. Installing the public keys on the remote servers
   [offsite]$ scp .ssh/id_dsa.pub accountname@server1.com:offsite.pub
accountname@server1.com's password: (enter password, not new
passphrase!)
id_dsa.pub 100% |*****************************| 614 00:00

[offsite]$ scp .ssh/id_dsa.pub accountname@server2.com:offsite.pub
accountname@server2.com's password: (enter password, not new
passphrase!)
id_dsa.pub 100% |*****************************| 614 00:00

After we install the new public keys, we'll be able to sign on to each machine using the passphrase we specified when creating the private and public keys. For now, log in to each machine and append the contents of the offsite.pub file to a file called authorized_keys, which is stored in each remote machine's .ssh directory. We can use a text editor or simply use the cat command to append the offsite.pub file's contents onto the authorized_keys file:


Listing 5. Add offsite.pub to your list of authorized keys
   [offsite]$ ssh accountname@server1.com
accountname@server1.com's password: (enter password, not new
passphrase!)
[server1]$ cat offsite.pub >> ./ssh/authorized_keys

The next step involves employing a bit of extra security. First, we change the access rights for the .ssh directory so that only the owner has read, write, and execute privileges. Next, we'll make sure that the authorized_keys file can only be accessed by the owner. And finally, we'll remove the previously uploaded offsite.pub key file, since it's no longer required. It's important to ensure that access permissions are properly set because the OpenSSH server may refuse to use keys which have non-secure access rights.


Listing 6. Changing permissions with chmod
   [server1]$ chmod 700 .ssh
[server1]$ chmod 600 ./ssh/authorized_keys
[server1]$ rm offsite.pub
[server1]$ exit

After completing the same process on server2, we are ready to return to the offsite storage machine to test the new passphrase type access. >From the offsite server you could type the following:

[offsite]$ ssh -v accountname@server1.com

Use the -v, or verbose flag option, to display debugging information while verifying that your account is now able to access the remote server using the new passphrase rather than the original password. The debug output displays important information which you might not otherwise see, in addition to offering a high level view of how the authentication process works. You won't need to specify the -v flag on subsequent connections; but it is quite useful to do so while testing a connection.

Automating machine access using ssh-agent

The ssh-agent program acts like a gatekeeper, securely providing access to security keys as needed. Once ssh-agent is started, it sits in the background and makes itself available to other OpenSSH applications such as ssh and scp programs. This allows the ssh program to request an already decrypted key, rather than asking you for the private key's secret passphrase each time it's required.

Let's take a closer look at ssh-agent. When ssh-agent runs it outputs shell commands:


Listing 7. ssh-agent in action
   [offsite]$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-XX1O24LS/agent.14179; export SSH_AUTH_SOCK;
SSH_AGENT_PID=14180; export SSH_AGENT_PID;
echo Agent pid 14180;

We can instruct the shell to execute the output commands which ssh-agent displays using the shell's eval command:

[offsite]$ eval `ssh-agent`
Agent pid 14198

The eval command tells the shell to evaluate (execute) the commands generated by the ssh-agent program. Make sure that you specify the back-quote character (`) and not a single quote! Once executed, the eval `ssh-agent` statement will return the agent's process identifier. Behind the scenes, the SSH_AUTH_SOCK and SSH_AGENT_PID shell variables have been exported and are now available. You can view their values by displaying them to the shell console:

[offsite]$ echo $SSH_AUTH_SOCK
/tmp/ssh-XX7bhIwq/agent.14197

The $SSH_AUTH_SOCK (short for SSH Authentication Socket) is the location of a local socket which applications can use to speak to ssh-agent. To ensure that the SSH_AUTH_SOCK and SSH_AGENT_PID variables are always registered, enter the eval `ssh-agent` statement into your ~/.bash_profile.

ssh-agent has now become a background process which is visible using the top and ps commands.

Now we're ready to share our passphrase with ssh-agent. To do so, we must use a program called ssh-add, which adds (sends) our passphrase to the running ssh-agent program.


Listing 8. ssh-add for hassle-free login
   [offsite]$ ssh-add
Enter passphrase for /home/accountname/.ssh/id_dsa: (enter passphrase)
Identity added: /home/accountname/.ssh/id_dsa
(/home/accountname/.ssh/id_dsa)

Now when we access server1, we're not prompted for a passphrase:

[offsite]$ ssh accountname@server1.com
[server1]$ exit

If you're not convinced, try removing (kill -9) the ssh-agent process and reconnecting to server1. This time, you'll notice that server1 will request the passphrase for the private key stored in the id_dsa file in the .ssh directory:

[offsite]$ kill -9 $SSH_AGENT_PID
[offsite]$ ssh accountname@server1.com
Enter passphrase for key '/home/accountname/.ssh/id_dsa':

Simplifying key access using keychain

So far, we've learned about several OpenSSH programs (ssh, scp, ssh-agent and ssh-add), and we've created and installed private and public keys to enable a secure and automated login process. You may have realized that most of our setup work only has to be done once. For example, the process of creating the keys, installing them, and getting ssh-agent to execute via a .bash_profile only has to be done once per machine. That's the really good news.

The less than ideal news is that ssh-add must be invoked each time we sign on to the offsite machine and ssh-agent isn't immediately compatible with the cron scheduling process which we'll need to automate our backups. The reason that cron processes can't communicate with ssh-agent is that cron jobs are executed as child processes by cron and thus do not inherit the $SSH_AUTH_SOCK shell variable.

Fortunately, there is a solution which not only eliminates limitations associated with ssh-agent and ssh-add, but also allows us to use cron to automate all sorts of processes requiring secure passwordless access to other machines. In his 2001 three-part developerWorks series, OpenSSH key management (see Resources for a link), Daniel Robbins presented a shell script called keychain, which is a front-end to ssh-add and ssh-agent and which simplifies the entire passwordless process. Over time, the keychain script has undergone a number of improvements and is now maintained by Aron Griffis, with a recent 2.3.2-1 release posted on June 17, 2004.

The keychain shell script is a bit too large to list in this article because the well-written script includes lots of error checking, ample documentation, and a generous serving of cross-platform code. However, keychain can be quickly downloaded from the project's Web site (see Resources for a link).

Once you download and install keychain, using it is remarkably easy. Simply log in to each machine and add the following two lines to each .bash_profile:

keychain id_dsa
. ~/.keychain/$HOSTNAME-sh

The first time you log back in to each machine, keychain will prompt you for the passphrase. However, keychain won't ask you to reenter the passphrase on subsequent login attempts unless the machine has been restarted. Best of all, cron tasks are now able to use OpenSSH commands to securely access remote machines without requiring the interactive use of passphrases. Now we have the best of both worlds, added security and ease of use.


Listing 9. Initializing keychain on each machine
   KeyChain 2.3.2; http://www.gentoo.org/projects/keychain
Copyright 2002-2004 Gentoo Technologies, Inc.; Distributed under the
GPL

* Initializing /home/accountname/.keychain/localhost.localdomain-sh
file...
* Initializing /home/accountname/.keychain/localhost.localdomain-csh
file...
* Starting ssh-agent
* Adding 1 key(s)...
Enter passphrase for /home/accountname/.ssh/id_dsa: (enter passphrase)

Scripting a backup process

Our next task is to create the shell scripts, which will perform the necessary backup operations. The goal is to perform a complete database backup of servers 1 and 2. In our example, each server is running the MySQL database server and we'll use the mysqldump command-line utility to export a few database tables to an SQL import file.


Listing 10. The dbbackup.sh shell script for server 1
   #!/bin/sh

# change into the backup_agent directory where data files are stored.
cd /home/backup_agent

# use mysqldump utility to export the sites database tables
mysqldump -u sitedb -pG0oDP@sswrd --add-drop-table sitedb --tables
tbl_ccode tbl_machine tbl_session tbl_stats > userdb.sql

# compress and archive
tar czf userdb.tgz userdb.sql

On server 2, we'll place a similar script which backs up the unique tables present in the site's database. Each script is flagged as executable using:

[server1]:$ chmod +x dbbackup.sh

With a dbbackup.sh file on servers 1 and 2, we return to the offsite data server, where we'll create a shell script to invoke each remote dbbackup.sh script prior to initiating a transfer of the compressed (.tgz) data files.


Listing 11. backup_remote_servers.sh shell script for use on the offsite data server
   #!/bin/sh

# use ssh to remotely execute the dbbackup.sh script on server 1
/usr/bin/ssh backup_agent@server1.com "/home/backup_agent/dbbackup.sh"

# use scp to securely copy the newly archived userdb.tgz file
# from server 1. Note the use of the date command to timestamp
# the file on the offsite data server.
/usr/bin/scp backup_agent@server1.com:/home/backup_agent/userdb.tgz
/home/backups/userdb-$(date +%Y%m%d-%H%M%S).tgz

# execute dbbackup.sh on server 2
/usr/bin/ssh backup_agent@server2.com "/home/backup_agent/dbbackup.sh"

# use scp to transfer transdb.tgz to offsite server.
/usr/bin/scp backup_agent@server2.com:/home/backup_agent/transdb.tgz
/home/backups/transdb-$(date +%Y%m%d-%H%M%S).tgz

The backup_remote_servers.sh shell script uses the ssh command to execute a script on the remote servers. Because we've set up passwordless access, the ssh command is able to execute commands on servers 1 and 2 remotely from the offsite server. The entire authentication process is now handled automatically, thanks to keychain.

Scheduling

Our next and final task involves scheduling the execution of the backup_remote_servers.sh shell script on the offsite data storage server. We'll add two entries to the cron scheduling server to request execution of the backup script twice per day, at 3:34 am and again at 8:34 pm. On the offsite server invoke the crontab program with the edit (-e) option.

[offsite]:$ crontab -e

The crontab invokes the default editor, as specified using the VISUAL or EDITOR shell environment variables. Next, type two entries and save and close the file.


Listing 12. Crontab entries on the offsite server
   34 3 * * * /home/backups/remote_db_backup.sh
34 20 * * * /home/backups/remote_db_backup.sh

A crontab line contains two main sections, a time schedule section followed by a command section. The time schedule is divided into fields for specifying when a command should be executed:


Listing 13. Crontab format
          +---- minute
| +----- hour
| | +------ day of the month
| | | +------ month
| | | | +---- day of the week
| | | | | +-- command to execute
| | | | | |
34 3 * * * /home/backups/remote_db_backup.sh

Verifying your backups

You should routinely check your backups to ensure that the process is working correctly. Automating processes can remove unnecessary drudgery, but should never be a way of escaping due diligence. If your data is worth backing up, then it's also worth spot checking from time to time.

Consider adding a cron job to remind yourself to check your backups at least once per month. In addition, it's a good idea to change security keys every once in a while, and you can schedule a cron job to remind you of that as well.



Additional security precautions

For added security, consider installing and configuring an Intrusion Detection System (IDS), such as Snort, on each machine. Presumably, an IDS will notify you when an intrusion is underway or has recently occurred. With an IDS in place, you'll be able to add other levels of security such as digitally signing and encrypting your backups.

Popular open source tools such as GNU Privacy Guard (GnuPG), OpenSSL and ncrypt enable securing archive files via shell scripts, but doing so without the extra level of shielding that an IDS provides isn't recommended (see Resources for more information on Snort).





Conclusion

This article has shown you how to allow your scripts to execute on remote servers and how to perform secure and automated file transfers. I hope you'll feel inspired to start thinking about protecting your own valuable data and building new solutions using open source tools like OpenSSH and Snort.



Resources

Monday, July 7, 2008

zenhabit: patience

a zenhabits article on patience:

from http://zenhabits.net/2008/07/15-tips-for-becoming-as-patient-as-job/

15 Tips for Becoming as Patient as Job

“Patience and fortitude conquer all things.” - Ralph Waldo Emerson

In the Old Testament, the story of Job showed a very faithful man whose faith is put to test, and shows an extreme example of perseverance through suffering … but in my mind, whenever I read Job’s story, I am struck by the man’s supreme patience.

While living a very faithful and righteous life, he nevertheless endured one infliction after another without ever cursing God’s name. I think most of us would have lost our patience and become frustrated and angry much earlier in the story.

While Job’s patience is legendary, I believe that even the most impatient of us can learn to be more patient with practice.

Personally, patience is something I’ve been cultivating for a long time. And while I often fail, I believe I’ve progressed over the years, and things that used to get me hot and bothered now just float past me. I still get upset, of course, but not nearly as much as I used to.

Here are some tips that might help you become more patient, with practice:

  1. Tally marks. This is the first strategy, if you have real problems with patience: start by simply keeping tally marks on a little sheet of paper every time you lose your patience. This is one of the most effective and important methods for controlling an impulse — by learning to become more aware of it. Once you become aware of your impulses, you can work out an alternative reaction.
  2. Figure out your triggers. As you become more aware of losing your patience, pay close attention to the things that trigger you to lose that patience. Is it when your co-worker does something particularly irritating? When your spouse leaves dirty dishes in the sink? When your child doesn’t clean up her mess? Certain triggers will recur more frequently than others — these are the things you should focus on the most.
  3. Deep breaths. When you first start to lose your patience, take a deep breath, and breathe out slowly. Then take another. And another. These three breaths will often do the trick, as your frustration will slowly melt away.
  4. Count to 10. This one really works. When you feel yourself getting frustrated or angry, stop. Count slowly to 10 (you can do this in your head). When you’re done, most of the initial impulse to yell or do something out of frustation will go away. Combine this with the breathing tip for even more effectiveness.
  5. Start small. Don’t try to become as patient as Job overnight. It won’t happen. Start with something small and manageable. Look for a trigger that only induces a mild impatience within you — not something that gets your blood boiling. Then focus on this, and forget the other triggers for now. Work on controlling your temper for that one trigger. If you can get this one under control, use what you learned to focus on the next small trigger. One at a time, and with practice, you’ll get there.
  6. Take a time out. Often it’s best just to walk away for a few minutes. Take a break from the situation, just for 5-10 minutes, let yourself calm down, plan out your words and actions and solution, and then come back calm as a monk.
  7. Remember what’s important. Sometimes we tend to get upset over little things. In the long run, these things tend not to matter, but in the heat of the moment, we might forget this. Stop yourself, and try to get things in perspective.
  8. Keep practicing. Every time a situation stretches your patience to dangerous thinness, just think of it as an opportunity to practice your patience. Because that’s what it take to become patient — practice, practice, more practice, and even more practice. And then some more. And the more you practice, the better you’ll get. So cherish these wonderful opportunities to practice.
  9. Visualize. This works best if you do it before the frustrating situation comes up. When you’re alone and in a quiet place. Visualize how you want to react the next time your trigger happens. How do you handle the situation? How do you look? What do you say? How does the other person react? How does it help your relationship, your life? Think about all these things, visualize the perfect situation, and then try to actually make that happen when the situation actually comes up.
  10. Remember that things can take time. Nothing good happens right away. If you expect things to happen at the snap of your fingers, you’ll get impatient every time. Instead, realize that things will take time, and this realization can help your patience tremendously.
  11. Teach. This is something that helps me a lot. I remember that no one is perfect, and that everyone has a lot to learn. Be patient, and teach others how to do things — even if you’ve tried before, it might be the 11th time when things click. And remember, none of us learn things on the first try. Find new ways to teach something, and you’re more likely to be successful.
  12. Find healthy ways to relieve frustration. Frustration can build up like steam in a pressure cooker, and if you don’t relieve that steam, you’ll explode. So find ways to relieve that frustration in a healthy way. Punching a pillow, going outside to a place where you’re all alone and yelling, exercise, kickboxing … these are just a few examples. Once you get that frustration out of your system, you usually feel better.
  13. Try meditation. You can’t meditate in the middle of a frustrating situation, usually, but often meditation can help you to learn to find a center of calm within yourself. Once you learn how to go to this calm place, you can go there when you begin to get angry. Meditation can also help you to be in the moment, instead of always wanting to get to the future, or instead of dwelling on the past and getting angry about it.
  14. Just laugh. Sometimes we need to remind ourselves that no one is perfect, that we should be enjoying this time with our loved ones, and that life should be fun — and funny. Smile, laugh, be happy. Doesn’t always work, but it’s good to remind yourself of this now and then.
  15. Just love. Instead of reacting with anger, teach yourself to react with love. Your child spills something or has a messy room or breaks your family heirloom? Your spouse yells at you or is cranky after work? React with love. It’s the best solution.

Friday, July 4, 2008

Bad Programmer

Bad Programmers

Solving your skillset problems

Signs that you are a bad programmer

1. Inability to reason about code

Reasoning about code means being able to follow the execution path ("running the program in your head") while knowing what the goal of the code is.

Symptoms

  1. The presence of "voodoo code", or code that has no effect on the goal of the program but is diligently maintained anyway (such as initializing variables that are never used, calling functions that are irrelevant to the goal, producing output that is not used, etc.)
  2. Executing idempotent functions multiple times (eg: calling the save() function multiple times "just to be sure")
  3. Fixing bugs by writing redundant code that overwrites the result of the faulty code
  4. "YoYo code" that converts a value into a different representation, then converts it back to where it started (eg: converting a decimal into a string and then back into a decimal, or padding a string and then trimming it)
  5. "Bulldozer code" that gives the appearance of refactoring by breaking out chunks into subroutines, but that are impossible to reuse in another context (very high cohesion)

Remedies

To get over this deficiency a programmer can practice by using the IDE's own debugger as an aide if it has the ability to step through the code one line at a time. In Visual Studio, for example, this means setting a breakpoint at the beginning of the problem area and stepping through with the 'F11' key, inspecting the value of variables--before and after they change--until you understand what the code is doing. If the target environment doesn't have such a feature, then practice in one that does.

The goal is to reach a point where you no longer need the debugger to be able to follow the flow of code in your head, and where you are patient enough to think about what the code is doing to the state of the program. The reward is the ability to identify redundant and unnecessary code, as well as how to find bugs in existing code without having to re-implement the whole algorithm from scratch.

2. Poor understanding of the language's programming model

Object Oriented Programming is an example of a language model, as is Functional or Declarative programming. They're each significantly different from procedural or imperative programming, just as procedural programming is significantly different from assembly or GOTO-based programming. Then there are languages which follow a major programming model (such as OOP) but introduce their own improvements such as list comprehensions, generics, duck-typing, etc.

Symptoms

  1. Using whatever syntax is necessary to break out of the model, then writing the remainder of the program in imperative/procedural style
  2. (OOP) Attempting to call non-static functions or variables in uninstantiated classes, and having difficulty understanding why it won't compile
  3. (OOP) Writing lots of "xxxxxManager" classes that contain all of the methods for manipulating objects that have little or no methods of their own
  4. (Relational) Treating the database as an object store by giving each table an identity column (or GUID) for the primary key, and possibly going as far as serializing the state of the object to a binary column
  5. (Functional) Creating multiple versions of the same algorithm to handle different types or operators, rather than passing high-level functions to a generic implementation
  6. (Functional) Manually caching the results of a deterministic function
  7. (Pure Functional) Using cut-n-paste code from someone else's program to deal with I/O and Monads
  8. (Declarative) Setting individual values in imperative code rather than using data-binding

Remedies

If your skills deficiency is a product of ineffective teaching or studying, then an alternative teacher is the compiler itself. There is no more effective way of learning a new programming model than starting a new project and committing yourself to use whatever the new constructs are, intelligently or not. You also need to practice explaining the model's features in crude terms of whatever you are familiar with, then recursively building on your new vocabulary until you understand the subtleties as well. For example:

Phase 1: "OOP is just records with methods"
Phase 2: "OOP methods are just functions running in a mini-program with its own global variables"
Phase 3: "The global variables are called fields, some of which are private and invisible from outside the mini-program"
Phase 4: "The idea of having private and public elements is to hide implementation details and expose a clean interface, and this is called Encapsulation"
Phase 5: "Encapsulation means my business logic doesn't need to be polluted with implementation details"

Phase 5 looks the same for all languages, since they are all really trying to get the programmer to the point where he can express the intent of the program without burying it in the specifics of how. Take functional programming as another example:

Phase 1: "Functional programming is just doing everything by chaining deterministic functions together"
Phase 2: "When the functions are deterministic, they don't need to be executed until the output is called for, and only for as much as needed. This is called Lazy Evaluation and Partial Evaluation"
Phase 3: "In order to support Lazy and Partial Evaluation, the compiler requires that I write functions in terms of how to transform a single parameter, sometimes into another function. This is called Currying"
Phase 4: "When all functions are curried, the compiler can choose the best execution plan by using a constraint solver"
Phase 5: "By letting a constraint solver figure out the mundane details, I can write programs by describing what I want, rather than how to give it to me"

3. Deficient research skills / Chronically poor knowledge of the platform's features

Modern languages and frameworks now come with an awesome breadth and depth of built-in commands and features, with some leading frameworks (Java, .Net, Cocoa) being too large to expect any programmer, even a good one, to learn in anything less than a few years. But a good programmer will search for a built-in function that does what they need before they begin to roll their own, and excellent programmers have the skill to break-down and identify the abstract problems in their task, then search for existing frameworks, patterns, models and languages that can be adapted before they even begin to design the program.

Symptoms

These are only indicative of the problem if they continue to appear in the programmer's work long after he should have mastered the new platform.

  1. Re-inventing or laboring without basic mechanisms that are built-into the language, such as events-and-handlers or regular expressions
  2. Re-inventing classes and functions that are built-into the framework (eg: timers, collections, sorting and searching algorithms)
  3. "Email me teh code, plz" messages posted to help forums
  4. "Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal)
  5. Persistently using old-fashioned techniques even when new techniques are better in those situations (eg: still writes named delegate functions instead of using lambda expressions for one-offs)
  6. Having a stark "comfort zone", and going to extreme lengths to solve complex problems with primitives

Remedies

A programmer can't acquire this kind of knowledge without slowing down, and it's likely that he's been in a rush to get each function working by whatever means necessary. He needs to have the platform's technical reference handy and be able to look through it with minimal effort, which can mean either having a hard copy of it on the desk right next to the keyboard, or having a second monitor dedicated to a browser. To get into the habit initially, he should refactor his old code with the aim of reducing its instruction count by 10:1 or more.

4. Inability to comprehend pointers

If you don't understand pointers then there is a very shallow ceiling on the types of programs you can write, as the concept of pointers enables the creation of complex data structures and efficient APIs. Managed languages use references instead of pointers, which are similar but add automatic dereferencing and prohibit pointer arithmetic to eliminate entire classes of bugs. They are still similar enough, however, that a failure to grasp the concept will be reflected in poor data-structure design and bugs that trace back to the difference between pass-by-value and pass-by-reference in method calls.

Symptoms

  1. Failure to implement a linked list, or write code that inserts/deletes nodes from linked list without losing data
  2. Allocating arbitrarily big arrays for variable-length collections and maintaining a separate collection-size counter, rather than using a linked list or other dynamic data structure
  3. Inability to find or fix bugs caused by performing arithmetic on pointers
  4. Modifying the dereferenced values from pointers passed as the parameters to a function, and not expecting it to change the values in the scope outside the function
  5. Making a copy of a pointer, changing the dereferenced value via the copy, then assuming the original pointer still points to the old value
  6. Serializing a pointer to the disk or network when it should have been the dereferenced value
  7. Sorting an array of pointers by performing the comparison on the pointers themselves

Remedies

A friend of mine named Joe was staying somewhere else in the hotel, but I didn't know which room number. I did, however, know which room his acquaintance, Frank, was staying in. So I went up there and knocked on his door and asked him, "Where's Joe staying?" Frank didn't know, but he did know which room Joe's co-worker, Theodore, was staying in, and gave me that room number instead. So I went to Theodore's room and asked him where Joe was staying, and Theodore told me that Joe was in Room 414. And that, in fact, is where Joe was.

Pointers can be described with many different metaphors, and the data structures you can build translated into many analogies. The above is a simple analogy for a linked list, and anybody can invent their own, even if they aren't programmers. The comprehension failure doesn't occur when pointers are described, so you can't describe them any more thoroughly than they already have been. It fails when the programmer then tries to visualize what's going on in the computer's memory and it gets conflated with their understanding of regular variables, which are very similar. It may help to translate the code into a simple story to help reason about what's going on, until the distinction clicks and the programmer can visualize pointers and the data structures they enable as intuitively as scalar values and arrays.

5. Difficulty seeing through recursion

The idea of recursion is easy enough to understand, but programmers often have problems imagining the result of a recursive operation in their minds, or how a complex result can be computed with a simple function. This makes it harder to design a recursive function because you have trouble picturing "where you are" when you come to writing the test for the base condition or the parameters for the recursive call.

Symptoms

  1. Hideously complex iterative algorithms for problems that can be solved recursively (eg: traversing a filesystem tree), especially where memory and performance is not a premium
  2. Recursive functions that check the same base condition both before and after the recursive call
  3. Recursive functions that don't test for a base condition
  4. Recursive subroutines that concatenate/sum to a global variable or a carry-along output variable, and aren't implementing tail recursion
  5. Apparent confusion about what to pass as the parameter in the recursive call, or recursive calls that pass the parameter unmodified

Remedies

Get your feet wet and be prepared for some stack overflows. Begin by writing code with only one base-condition check and one recursive call that uses the same, unmodified parameter that was passed. Stop coding even if you have the feeling that it's not enough, and run it anyway. It throws a stack-overflow exception, so now go back and pass a modified copy of the parameter in the recursive call. More stack overflows? Excessive output? Then do more code-and-run iterations, switching from tweaking your base-condition test to tweaking your recursive call until you start to intuit how the function is transforming its input. Resist the urge to use more than one base-condition test or recursive call unless you really know what you're doing.

Your goal is to have the confidence to jump in, even if you don't have a complete sense of "where you are" in the imaginary recursive path. Then when you now need to write a function for a real project you'd begin by writing a unit test first, and proceeding with the same technique above.

Signs that you are a mediocre programmer

1. Inability to think in sets

Transitioning from imperative programming to functional and declarative programming will immediately require you to think about operating on sets of data as your primitive, not scalar values. The transition is required whenever you use SQL with a relational database (and not as an object store), whenever you design programs that will scale linearly with multiple processors, and whenever you write code that has to execute on a SIMD-capable chip (such as modern graphics cards and video game consoles).

Symptoms

The following count only when they're seen on a platform with Declarative or Functional programming features that the programmer should be aware of.

  1. Performing atomic operations on the elements of a collection within a for or foreach loop
  2. Writing Map or Reduce functions that contain their own loop for iterating through the dataset
  3. Fetching large datasets from the server and computing sums on the client, instead of using aggregate functions in the query
  4. Functions acting on elements in a collection that begin by performing a new database query to fetch a related record
  5. Writing business-logic functions with tragically compromising side-effects, such as updating a user interface or performing file I/O
  6. Classes that open their own database connections or file handles and keep them open for their lifespan

Remedies

Funny enough, visualizing a card dealer cutting a deck of cards and interleaving the two stacks together by flipping through them with his thumbs can jolt the mind into thinking about sets and how you can operate on them in bulk. Other stimulating visualizations are:

  • freeway traffic passing through an array of toll booths (parallel processing)
  • springs joining to form streams joining to form creeks joining to form rivers (parallel reduce/aggregate functions)
  • a newspaper printing press (coroutines, pipelines)
  • the zipper tag on a jacket pulling the zipper teeth together (simple joins)
  • transfer RNA picking up amino acids and joining messenger RNA within a ribosome to become a protein (multi-stage function-driven joins, see animation)
  • the above happening simultaneously in billions of cells in an orange tree to convert soil, water and sunlight into orange juice (Map/Reduce on large distributed clusters)

If you are writing a program that works with collections, think about all the supplemental data and records that your functions need to work on each element and use Map functions to join them together in pairs before you have your Reduce function applied to each pair.

2. Lack of critical thinking

Unless you criticize your own ideas and look for flaws in your own thinking, you will miss problems that can be fixed before you even start coding. If you also fail to criticize your own code once written, you will only learn at the vastly slower pace of trial and error. This is the root of lazy thinking and egocentric thinking, so its symptoms seem to come from two different directions.

Symptoms

  1. "Business Rule Engines"
  2. Fat static utility classes, or multi-disciplinary libraries with only one namespace
  3. Conglomerate applications, or attaching unrelated features to an existing application to avoid the overhead of starting a new project
  4. Architectures that have begun to require epicycles
  5. Adding columns to tables for tangential data
  6. Inconsistent naming conventions
  7. "Man with a hammer" mentality, or changing the definitions of problems so they can all be solved with one particular technology
  8. Programs that dwarf the complexity of the problem they solve
  9. Pathologically and redundantly defensive programming ("Enterprisey code")

Remedies

Start with a book like Critical Thinking by Paul and Elder, work on controlling your ego, and practice resisting the urge to defend yourself as you submit your ideas to friends and colleagues for criticism.

Once you get used to other people examining your ideas, start examining your own ideas yourself and practice imagining the consequences of them. In addition, you also need to develop a sense of proportion (to have a feel for how much design is appropriate for the size of the problem), a habit of double-checking assumptions (so you don't overestimate the size of the problem), and a healthy attitude towards failure (even Isaac Newton was wrong, but we needed him to try anyway).

Finally, you must have discipline. Being aware of flaws in your plan will not make you more productive unless you can muster the willpower to correct and rebuild what you're working on.

3. Pinball Programming

When you tilt the board just right, pull back the pin to just the right distance, and hit the flipper buttons in the right sequence, then the program runs flawlessly with the flow of execution bouncing off conditionals and careening unchecked toward the next state transition.

Symptoms

  1. One Try-Catch block wrapping the entire body of Main() and resetting the program in the Catch clause (the pinball gutter)
  2. Using strings/integers for values that have (or could be given) more appropriate wrapper types in a strongly-typed language
  3. Packing complex data into delimited strings and parsing it out in every function that uses it
  4. Failing to use assertions or method contracts on functions that make assumptions about their arguments
  5. The use of Sleep() to wait for another thread to finish its task
  6. Switch statements, on non-enumerated values, that don't have an "Otherwise" clause
  7. Using Automethods or Reflection to invoke methods that are named in unqualified user input
  8. Setting global variables in functions as a way to return multiple values
  9. Classes with one method and a couple of fields, where you have to set the fields as the way of passing parameters to the method
  10. Multi-row database updates without a transaction
  11. Hail-Mary passes (eg: trying to restore the state of a database without a transaction and ROLLBACK)

Remedies

Imagine your program's input is water. It's going to fall through every crack and fill every pocket, so you need to think about what the consequences are when it flows somewhere other than where you've explicitly built something to catch it.

You will need to make yourself familiar with the mechanisms on your platform that help make programs robust and ductile. There are three basic kinds:

  1. those which stop the program before any damage is done when something unexpected happens, then helps you identify what went wrong (type systems, assertions, exceptions, etc.),
  2. those which direct program flow to whatever code best handles the contingency (try-catch blocks, multiple dispatch, event driven programming, etc.),
  3. those which pause the thread until all your ducks are in a row (WaitUntil commands, mutexes and semaphores, SyncLocks, etc.)

There is also a fourth, Unit Testing, which you use at design time.

Using these ought to become second nature to you, like putting commas and periods in sentences. To get there, go through the above mechanisms (the ones in parenthesis) one at a time and refactor an old program to use them wherever you can cram them, even if it doesn't turn out to be appropriate (especially when they don't seem appropriate, so you also begin to understand why).

Signs that you shouldn't be a programmer

The following may not have any remedies if you still suffer from them after taking a programming course in school, so you will stand a better chance of advancing your career by choosing another profession.

1. Inability to determine the order of program execution

Symptoms

a = 5
b = 10
a = b

print a
  1. You look at the code above and aren't sure what number gets printed out at the end

Alternative careers

  1. Electrician
  2. Plumber
  3. Architect
  4. Civil engineer

2. Insufficient ability to think abstractly

Symptoms

  1. Difficulty comprehending the difference between objects and classes
  2. Difficulty implementing design patterns for your program
  3. Difficulty writing functions with low cohesion
  4. Incompetence with Regular Expressions
  5. Lisp is opaque to you
  6. Cannot fathom the Church-Turing Thesis

Alternative careers

  1. Contract negotiator
  2. Method actor

3. Collyer Brothers syndrome

Symptoms

  1. Unwilling to throw away anything, including garbage
  2. Unwilling to delete anything, be it code or comments
  3. The urge to build booby-traps for defense against trespassers
  4. Unwilling to communicate with other people
  5. Poor organization skills

Alternative careers

  1. Antique dealer
  2. Bag lady

4. Dysfunctional sense of causality

Symptoms

  1. You seriously consider malice to be a reason why the compiler rejects your program
  2. When called on to fix a bug in a deployed program, you try prayer
  3. You take hidden variables for granted and don't think twice about blaming them for a program's misbehavior
  4. You think the presence of code in a program will affect its runtime behavior, even if it is never invoked
  5. Your debugging repertoire includes rituals like shining your lucky golf ball, twisting your wedding ring, and tapping the nodding-dog toy on your monitor. And when the debugging doesn't work, you think it might be because you missed one or didn't do them in the right order

Alternative careers

  1. Playing the slot machines in Vegas