Saturday, October 20, 2012

Mythbuster












I'm asked to use an automated code review tool at work. It's not FindBugs; nevermind the name. Given a repository URL, it checks for architectural integrity, programming practices, and documentation. It reports scores on the academic scale, with zero being the worst and 4.0 being the best possible score. It flags offensive components and presents citations to buttress its arguments.

I'm particularly bothered by one offense against architectural integrity. It says that instantiation of objects inside a loop is inefficient and gives the lowest possible architectural score. The goal is to avoid instantiation of too many objects.

How on earth is a developer supposed to populate a list of objects?

Besides, this might have been a serious issue on the earliest versions of the JVM. But object creation now rivals C in speed, and newer generational garbage collectors are also big improvements.

Rather than rail against the injustice, I decided to create a small benchmark and see for myself.

I started with a simple Person class:

package cast;

import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Person
 * @author mduffy
 * @since 9/19/12 7:38 AM
 */
public class Person {
    private static final DateFormat BIRTH_DATE_FORMATTER;
    
    private final String firstName;
    private final String lastName;
    private final Date birthDate;

    static {
        BIRTH_DATE_FORMATTER = new SimpleDateFormat("yyyy-MMM-dd");
        BIRTH_DATE_FORMATTER.setLenient(false);
    }
    
    public Person(String firstName, String lastName, Date birthDate) {
        this.firstName = (StringUtils.isBlank(firstName) ? "" : firstName);
        this.lastName = (StringUtils.isBlank(lastName) ? "" : lastName);
        this.birthDate = ((birthDate == null) ? new Date() : new Date(birthDate.getTime()));
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public Date getBirthDate() {
        return new Date(birthDate.getTime());
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Person");
        sb.append("{firstName='").append(firstName).append('\'');
        sb.append(", lastName='").append(lastName).append('\'');
        sb.append(", birthDate=").append(BIRTH_DATE_FORMATTER.format(this.birthDate));
        sb.append('}');
        return sb.toString();
    }
}

I needed to keep statistics on wall time and heap used, so I wrote a Statistics class:

package cast;

import org.apache.commons.lang3.StringUtils;

import java.util.Collection;

/**
 * Statistics accumulates simple statistics for a given quantity "on the fly" - no array needed.
 * Resets back to zero when adding a value will overflow the sum of squares.
 * @author mduffy
 * @since 9/19/12 8:16 AM
 */
public class Statistics {
    private String quantityName;
    private int numValues;
    private double x;
    private double xsq;
    private double xmin;
    private double xmax;

    /**
     * Constructor
     */
    public Statistics() {
        this(null);
    }

    /**
     * Constructor
     * @param quantityName to describe the quantity (e.g. "heap size")
     */
    public Statistics(String quantityName) {
        this.quantityName = (StringUtils.isBlank(quantityName) ? "x" : quantityName);
        this.reset();
    }

    /**
     * Reset the object in the event of overflow by the sum of squares
     */
    public synchronized void reset() {
        this.numValues = 0;
        this.x = 0.0;
        this.xsq = 0.0;
        this.xmin = Double.MAX_VALUE;
        this.xmax = -Double.MAX_VALUE;
    }

    /**
     * Add a List of values
     * @param values to add to the statistics
     */
    public synchronized void addAll(Collection values) {
        for (Double value : values) {
            add(value);
        }
    }

    /**
     * Add an array of values
     * @param values to add to the statistics
     */
    public synchronized void allAll(double [] values) {
        for (double value : values) {
            add(value);
        }
    }
    
    /**
     * Add a value to current statistics
     * @param value to add for this quantity
     */
    public synchronized void add(double value) {
        double vsq = value*value;
        ++this.numValues;
        this.x += value;
        this.xsq += vsq; // TODO: how to detect overflow in Java?
        if (value < this.xmin) {
            this.xmin = value;
        }
        if (value > this.xmax) {
            this.xmax = value;
        }
    }

    /**
     * Get the current value of the mean or average
     * @return mean or average if one or more values have been added or zero for no values added
     */
    public synchronized double getMean() {
        double mean = 0.0;
        if (this.numValues > 0) {
            mean = this.x/this.numValues;
        }
        return mean;
    }

    /**
     * Get the current min value
     * @return current min value or Double.MAX_VALUE if no values added
     */
    public synchronized double getMin() {
        return this.xmin;
    }

    /**
     * Get the current max value
     * @return current max value or Double.MIN_VALUE if no values added
     */
    public synchronized double getMax() {
        return this.xmax;
    }

    /**
     * Get the current standard deviation
     * @return standard deviation for (N-1) dof or zero if one or fewer values added
     */
    public synchronized double getStdDev() {
        double stdDev = 0.0;
        if (this.numValues > 1) {
            stdDev = Math.sqrt((this.xsq-this.x*this.x/this.numValues)/(this.numValues-1));
        }
        return stdDev;
    }

    /**
     * Get the current number of values added
     * @return current number of values added or zero if overflow condition is encountered
     */
    public synchronized int getNumValues() {
        return this.numValues;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append("Statistics");
        sb.append("{quantityName='").append(quantityName).append('\'');
        sb.append(", numValues=").append(numValues);
        sb.append(", xmin=").append(xmin);
        sb.append(", mean=").append(this.getMean());
        sb.append(", std dev=").append(this.getStdDev());
        sb.append(", xmax=").append(xmax);
        sb.append('}');
        return sb.toString();
    }
}

Then I wrote a test method to exercise creating a million instances and compared the two idioms:

package cast;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * InstantiationInsideLoopTest attempts to answer the question: Is it bad to instantiate an object inside a loop
 * with a modern JVM?
 * @author mduffy
 * @since 9/19/12 7:35 AM
 */
public class InstantiationInsideLoopTest {
    private static final int DEFAULT_INSTANCES = 1000000;
    private static final int DEFAULT_REPETITIONS = 5;
    private static final String[] FIRST_NAMES = {
            "Abel", "Bob", "Charlie", "David", "Edward", "Fred",
    };
    private static final String[] LAST_NAMES = {
            "Smith", "Jones", "Carver", "Brown",
    };

    private Random random;
    private Statistics begHeapStats     = new Statistics("beg heap (MB)");
    private Statistics endHeapStats     = new Statistics("end heap (MB)");
    private Statistics wallTimeStats    = new Statistics("wall time (sec)");


    public static void main(String[] args) {
        int numRepetitions = ((args.length > 0) ? Integer.valueOf(args[0]) : DEFAULT_REPETITIONS);
        int numInstances = ((args.length > 1) ? Integer.valueOf(args[1]) : DEFAULT_INSTANCES);
        boolean isInside = (args.length > 2) && "inside".equalsIgnoreCase(args[2]);
        System.out.println(String.format("# reps: %d # instances: %d inside? %b", numRepetitions, numInstances, isInside));
        InstantiationInsideLoopTest tester = new InstantiationInsideLoopTest();
        if (isInside) {
            tester.instantiateInside(numInstances, numRepetitions);
        } else {
            tester.instantiateOutside(numInstances, numRepetitions);
        }
    }

    public InstantiationInsideLoopTest() {
        this(System.currentTimeMillis());
    }

    public InstantiationInsideLoopTest(long seed) {
        this.random = new Random(seed);
    }

    private void instantiateOutside(int numInstances, int numRepetitions) {
        this.begHeapStats = new Statistics("beg heap (MB)");
        this.endHeapStats = new Statistics("end heap (MB)");
        this.wallTimeStats = new Statistics("wall time (sec)");
        for (int i = 0; i < numRepetitions; ++i) {
            long begTime = System.currentTimeMillis();
            long begHeap = Runtime.getRuntime().freeMemory();
            List persons = new LinkedList();
            Person p;
            for (int j = 0; j < numInstances; ++j) {
                p = new Person(getFirstName(), getLastName(), getBirthDate());
                persons.add(p);
            }
            long endHeap = Runtime.getRuntime().freeMemory();
            long endTime = System.currentTimeMillis();
            this.begHeapStats.add(begHeap/1024L/1024L);
            this.endHeapStats.add(endHeap/1024L/1024L);
            this.wallTimeStats.add((endTime - begTime)/1000.0);
//          summarize("outside", i, begTime, endTime, maxHeap, begHeap, endHeap, persons);
        }
        System.out.println(this.begHeapStats);
        System.out.println(this.endHeapStats);
        System.out.println(this.wallTimeStats);
    }

    private void instantiateInside(int numInstances, int numRepetitions) {
        this.begHeapStats = new Statistics("beg heap (MB)");
        this.endHeapStats = new Statistics("end heap (MB)");
        this.wallTimeStats = new Statistics("wall time (sec)");
        for (int i = 0; i < numRepetitions; ++i) {
            long begTime = System.currentTimeMillis();
            long begHeap = Runtime.getRuntime().freeMemory();
            List persons = new LinkedList();
            for (int j = 0; j < numInstances; ++j) {
                Person p = new Person(getFirstName(), getLastName(), getBirthDate());
                persons.add(p);
            }
            long endHeap = Runtime.getRuntime().freeMemory();
            long endTime = System.currentTimeMillis();
            this.begHeapStats.add(begHeap/1024L/1024L);
            this.endHeapStats.add(endHeap/1024L/1024L);
            this.wallTimeStats.add((endTime-begTime)/1000.0);
//            summarize("inside", i, begTime, endTime, maxHeap, begHeap, endHeap, persons);
        }
        System.out.println(this.begHeapStats);
        System.out.println(this.endHeapStats);
        System.out.println(this.wallTimeStats);
    }

    private String getFirstName() {
        return FIRST_NAMES[this.random.nextInt(FIRST_NAMES.length)];
    }

    private String getLastName() {
        return LAST_NAMES[this.random.nextInt(LAST_NAMES.length)];
    }

    private Date getBirthDate() {
        return new Date(this.random.nextLong());
    }

    private void summarize(String testName, int repetition, long begTime, long endTime, long maxHeap, long begHeap, long endHeap, List objects) {
        System.out.println(String.format("test name    : %s", testName));
        System.out.println(String.format("repetition # : %d", repetition));
        System.out.println(String.format("list size    : %d", objects.size()));
        System.out.println(String.format("beg heap (MB): %d", begHeap / 1024L / 1024L));
        System.out.println(String.format("end heap (MB): %d", endHeap / 1024L / 1024L));
        System.out.println(String.format("max heap (MB): %d", maxHeap / 1024L / 1024L));
        System.out.println(String.format("wall time (s): %10.3f", (endTime - begTime) / 1000.0));
        for (int i = 0; i < 5; ++i) {
            System.out.println(objects.get(i));
        }
    }
}
I ran this test case on two different machines - one running Windows XP, another using Windows 7 - and both running Sun JVMs for Java 6. The results consistently said that the idiom recommended by the automated code review suite was incorrect. I understand the dangers of benchmarks like these, but it's comforting to attempt to be scientific rather than merely complain.
profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers

Sunday, October 14, 2012

Race Day













I was nervous during the week leading up to the race. My last long run went very well. I did another six mile run the following Saturday, followed by an easy three mile jaunt the next day that included my first taste of gel packs, those doses of instant fuel that could keep me from hitting the wall at the end of the race. I followed the "don't introduce anything new on the day of the race" mantra and tried one. The vanilla flavor was delicious; it went down easily but took time to get out of the package; most importantly, it didn't upset my stomach.

It was a week to taper, according to my plan, but I ended up doing nothing. Yoga was cancelled due to Columbus Day. I didn't run at all, because my wife was in the midst of a cold for the entire week, as were my co-workers. Disease was all around me! I was concerned about waking up on race day with a whopper of a cold that would put me on the sidelines. So I went to bed early every night and hoped that my immune system would fight the good fight.

Race Day dawned bright and cold. Temperatures were below freezing overnight. What to wear? I decided to run in shorts and forego the tights. I had an Under Armor shirt with the half-marathon long-sleeved t-shirt over the top. I wore the same baseball cap that I'd done all my training in; no hat over my ears. I heeded the "no changes on race day" advice and ran in my minimals. I was determined to not give in to sneaker fear. My one concession to the cold was gloves. That turned out to be a very smart thought.

We drove into the city, parked in the convention center garage, and walked over to Bushnell Park. We had time, but there wouldn't be too much standing around. I was in line, right next to the "9 minute mile" sign, with only twenty minutes til race time. The crowd was shoulder to shoulder. Would the start be as viscous as the Manchester Road Race? It only took me two minutes to cross the starting line, and I was running comfortably right away. I hit the start button on my stopwatch and fell into my cadence - ninety right leg strikes per minute. The full and half marathon groups ran in one pack at the beginning. My biggest concern was taking a wrong turn and getting lost. But that turned out fine. There was a big sign at Main Street telling full marathons to turn left and half marathoners to turn right. After that, all I had to do was follow the crowd.

I didn't feel warm for the first mile or two, but everything was calm and relaxed. My breathing was smooth and comfortable. Nothing hurt. There was a Gatorade stop around mile two. I decided to take a cup at each stop to make sure that I didn't dehydrate. I didn't hurry. I'd stop, take the cup, gulp it down, and then head off. Drinking and running don't mix any more than drinking and driving do. I made sure that all my paper cups made it into a bin. The street was covered with crushed cups and spilled Gatorade. The volunteers would have a big cleanup job.

The training plan works. There were no official mile markers, but I got the idea that I was maintaining a nine-minute per mile pace without any strain. When I ran under the halfway arch the clock read 59 minutes. It was the first time I thought that I could actually break two hours. I noticed a woman wearing a yellow shirt that said "2:00 finish" on the back. She was the pace keeper: as long as I could stay with her I'd have a chance of meeting my time goal.

I was ahead of her when I entered Elizabeth Park, but some gentle slopes slowed me down more than I realized. I could see the Travelers tower ahead when I ran down Albany Ave past the eleven mile marker. The pace lady was within sight but ahead of me, surrounded by suffering acolytes who hoped for the reward of a two hour finish time. I had to decide: settle into a relaxed pace, call it a nice effort, and miss out on a two hour finish, or pick up my cadence and catch her. It was uncomfortable, but I decided on the latter course. I heard her say "You wanna bring it home?" as I passed her. I kept going until I couldn't hear her voice anymore. Less than two miles to go? That was all I could manage when I started this journey 16 months ago, but now it was easy. I pumped my arms and legs the whole way, under the Bushnell arch, into the chute, and under the finish arch. The clock read 1:59. My watch said 1:57. My average speed was a shade under nine minutes per mile, which was better than any training run I'd done.

I surprised my wife. I walked along like a veal calf to pick up a medal, a water bottle, and a bag with a banana and some other snacks. She sounded surprised when I called her on my cell phone. "Are you done?" she asked incredulously.

I enjoyed both the journey and the destination. It's so satisfying to say that I managed such a thing at my age. I thoroughly enjoyed the experience, so much so that I'm happily thinking about another run in November.

Most importantly, I've made myself into a runner. What other transformation can I undergo? How else might I remake myself again?

profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers

Wednesday, October 3, 2012

Ready!














Last Saturday I had my last long run before the half marathon on 13-Oct. It was overcast and threatening rain when I hit the Airline Trail at noon, so I had it mostly to myself. There were a few hardy mountain bikers and a dog walker or two, but the traffic was greatly diminished.

The plan called for 12 miles, but I was ahead of schedule for the last two long runs. I wanted to have the confidence of knowing that I could complete the distance. I had a water bottle filled with ice-cold green Gatorade in hand. I planned to stop every 3-4 miles for 30 seconds to get a drink and stay relaxed. I wanted to simulate my plan for the race.

The first mile was a warm-up. I had a sweatshirt on that may have been overkill. By the time I stopped for my first drink I was loose and lathered up. The markers for the fourth mile went by quickly. I was at nine minute miles or better the whole way. I never saw the fifth or sixth mile markers, same as the week before. The trail had a gentle upward slope. I felt anxious as I ran: would there be a marker for the turnaround point at mile 3? I crossed a road that intersected the trail, ran to the next gate - and there it was! I was surprised when I checked my watch: I was still maintaining a nine-minute mile pace! I felt good. I had a long, relaxed drink and started down the slope towards my car.

I have to compliment the folks who put together the plan that I've used to prepare for the race. They know what they're doing. I felt strong on the way back. When I passed the ten mile mark, I had plenty left. I thought back to how I felt at the end of that personal best long run two weeks ago. I was greatly improved. I was slowing down and suffering a bit more when I passed the twelve mile mark. I thought back to how knackered I felt at the end of last Saturday's run. I was beyond that. The last two miles were difficult. But I felt like a running man when I finished in 2:15.

Now I'm tapering down for the next two weeks. The longest run will be five miles. I'll do some swimming, shorter runs, and yoga. I'm looking forward to that day. I just hope I can dodge catching a cold for the next two weeks.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers

Monday, September 24, 2012

Uncharted Trails

















Saturday morning meant another long run. My training plan called for ten miles, but I'd already accomplished that. It was time to go above and beyond. I was going back to the Airline Trail for a twelve mile run, longer than anything I've attempted.

Thankfully it was another perfect day. I brought a water bottle filled with Gatorade to carry with me. I resolved to stop for a swig every three miles. I found the starting mile mark at precisely noon and hit the trail.

The first miles were easy. I had no trouble knocking off the first three at a nine minute mile pace. I stopped for my first drink and felt fine.

The next three miles were on a part of the trail that was a little rougher: washed out and slightly uphill. I missed the five mile marker the week before. I had a pretty good idea of where it was this time, so I hit my stop watch as I passed it. It's a good thing I did, because thirteen minutes later I hadn't encountered the six mile marker. I stopped for a drink, turned around, and headed back where I came from.

I was experiencing some discomfort on the way back last week. My feet were sore and tired, and my right inner thigh hurt every time I picked up my foot. Not so this week. I felt strong and determined. My pace was slower, but I was still in the 10-10:30 per mile range. I still had some energy when I passed the ten mile mark. I finished twelve miles in 2 hours 5 minutes. Not bad! Best of all, I felt okay when I walked back to the car during the cool down.

My legs were tired for the rest of the day, but I was far from wrecked. When I woke up the next day I felt stiff, but not too bad. It was another gorgeous day. I could have followed my plan and done 30 minutes of easy running. I had gas in my tank, but I decided to spend it cutting my grass instead.

Next Saturday is the last long run before the race. The plan calls for twelve; I'll go above and beyond again and shoot for 14 miles. If I can do that, I know I'll finish this race in fine style. After that, I start tapering down for the race.

I'm going to hold at this level for a while. I'd like to try a few more half marathons and see how I feel before deciding on my next step. This has been a terrific ten weeks. I doubted whether I'd be able to do this when I started, but those doubts are almost gone.




profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers

Thursday, September 20, 2012

Personal Best









I'm close to the end of week 10 in my training plan. My last entry hinted that my journey to the half marathon might be at a premature end, pending the outcome of a long run.

The results are in: all is well.

My training plan called for an eight mile run. The weather was exquisite last Saturday: sunny and cool as befits a late summer day on the cusp of autumn. I decided that long runs were best attempted on the Airline Trail, a rails-to-trails project that runs from East Hampton through Colchester, Hebron, and beyond. It's a straight shot, interrupted periodically by intersecting streets. I drove to a small parking lot off Route 85 and found the wooden post with the numeral ten on the left side of the trail. Miles are marked by numbered posts along the entire length, so keeping track of my progress was mindless and easy.

The surface is packed, dressed gravel that's easier on the feet than pavment. There's a canopy of leaves overhead. The trees seemed to act like a natural wind tunnel: there was an intermittent, comfortable breeze in my face for most of the run. Lots of other people had the same idea as me: to be out on foot, bike, or horse on a beautiful day. The traffic was still light compared to my usual routes on the road.

The first five miles felt easy. I was comfortable the whole time. I had trouble seeing the post with the five on it, because it was obscured by shrubs. I ran past it for a minute before turning back and correcting my error. The miles added up with each step. Soon I had matched my previous best of seven miles; then eight and nine went by. That last mile was a struggle mentally. My feet were tired. A muscle in my right inner thigh complained a little every time I lifted my foot. I kept waiting for "runner's high" to make an appearance and ease my suffering, but endorphins were in short supply. I only had two thoughts: to finish the run and to stop. I managed to accomplish both, finishing the run in 1:42. It was the longest run of my life. Now I know that I must have been hallucinating when I recalled a run of that distance when I was 21. There's no way I would have had the patience to run for that long a period of time.

I was dog tired for the rest of the day, but recovery was swift. I had a good yoga session at home on Sunday, and my regular ninety minute class on Monday night. I soon felt like myself again.

I've had two more runs since that personal best. I ran four miles inside on the track on Tuesday, because weather threatened to make running impossible after work. Conditions were delightful after work tonight. I ran the three miles that my plan called for. Dare I say it? The run felt easy. I experienced no pain anywhere. I could have done more. I had a lot of gas in the tank when I returned home.

Saturday will mean twelve miles on the Airline Trail. I'll be in uncharted waters again. My confidence is growing. I think I might succeed in this venture.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers




Sunday, September 9, 2012

Feet












I had a setback this week in my preparations for the Hartford half marathon. I did a seven-mile run on Sat 1-Sep. The first two miles were run under threatening clouds; the middle three had steady rain the whole time; the last two were sun-lit. My feet were very tired when I was done, but everything else felt fine.

The following Monday was the Labor Day holiday from work. The remnants of Hurricane Issac threatened us with rain for most of the week, so I decided to forego the rest day and do a four-mile run. I felt okay, which was good considering the long mileage I'd logged just two days before. I can't recall now if I stepped on something and felt a twinge in my left foot. But I wasn't concerned when I done.

I woke up the next morning and felt a lot of pain between the balls of my left foot. It was sore enough and in a spot where I feared a stress fracture at first. I put the thought out of my mind, because there wasn't any swelling. But the pain was sufficient to persuade me to take a break and stay off the road.

I consulted with a number of people about it. I have two daughters who are familiar with such things. My oldest is preparing for her third marathon next month. She got ready last Saturday by running a half marathon in 1:35. The two girls ran 18 miles together a couple of weeks ago, so they know something about running and the injuries that go along with it. Both counseled patience; all I needed was rest and exercises. I got some suggestions for exercises that were sobering. I did calf raises with my heel hanging over a stair that showed my left foot to be dramatically weaker than my right. I have to pay more attention to those. I've done yoga for five years now, but I think I'll have to redouble my efforts. Hips, knees, calves, Achilles, feet - all are connected. My left side is markedly stiffer than my right. A daily morning yoga session before work is an order.

A co-worker steered me to Fleet Feet in West Hartford. I knew that my minimal shoes were due to be replaced; I bought them last year on 22-Oct. The soles are worn away. I picked up a beautiful new pair of blue shoes and a green "Rubz" ball to roll out the knots in my feet. Damn, but that thing hurts! My left arch is in agony when I start using it. The pain subsides after a few minutes, but I'm very tender there. I'll have to be diligent about using the ball, too.

Conditions outside are spectacular today, so I decided to hit the road for a three-mile jaunt in my new shoes to see how my feet would hold up. I warmed up with 30 minutes of yoga, rolling out the knots with the ball, and some strengthening exercises. My times weren't impressive - they haven't been all along - but my feet withstood the road without a problem. They're tired, but there's no pain - until I step on that damned ball.

I've lost a week, but I don't think that's the end of the journey. I'm still hoping to run the half in a month. I'll know better after my next long run on Saturday.




profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers



Wednesday, August 29, 2012

Running The Half










One of the things that I try to practice is change. I used to work for a guy who insisted that it was impossible to read a book or learn something new or change at all "at my age."

I think I'm now as old as he was when he made that statement to me.

It's not necessarily about him, because my choices are solely my own, but I believe it's important to not give up the fight to improve physically and mentally just because we're older. I'm not what I was when I was 20 or 30, but I do what I can.

I also believe that the best way to make progress on anything is to pick a well-defined goal and take frequent, small, incremental steps in the chosen direction. New skills are best acquired by accretion of lots of small, targeted efforts.

A year ago last June I wrote about starting to run seriously for the first time since I was in my twenties. I spent a year of doing half mile repeats on the road in front of my house, thinking more about pace, cadence, and form instead of distance. I ran the Manchester Road Race on Thanksgiving Day, as tradition demands, but that was the only long run that I tried. I kept it up faithfully throughout the mild, snowless winter. I was still injury-free and feeling good in June.

Now that I had a good base, I decided that I needed a new goal. At the end of that previous posting I wrote "I'm not trying to run marathons. I don't want to race or be competitive." I don't want to race or be competitive, but I've decided to try completing a half marathon.

I needed a plan, so I fired up Google and found a schedule that I liked. I put the plan into a spreadsheet and set the start date so that race day was Saturday 13-Oct-2012: the ING Hartford half marathon. Plan the work, work the plan. I missed one whole week to attend a family wedding, but I've been faithful with the rest of it. I've completed the first half of the schedule. Now it becomes challenging. I increase the length of the long run by a mile per week until I complete a 12 mile run the week before the race.

This is uncharted territory for me. I have a vague memory of a long run when I was 20 years old. I was living in my parents' house, home from college, when I ran into a friend when I was out for a run after work. I fell in with him for a long time. I asked him how long the route was that we were taking. He told me it was a ten mile run, but now I'm not sure. The six mile run I completed last Saturday might have been the longest I've ever finished.

My times won't impress anyone. I feel comfortable at a 9-10 minute per mile pace. If I can keep that up for 13.1 miles I'll finish somewhere between 2:00 and 2:20. The most important thing will be to finish.

It's not a fait accompli that I'll be able to do it, even thought I've registered and paid my money. My ankles, knees, and hips feel fine so far. I've had no muscle problems at all, not even stiffness or soreness on the day after running. But if something blows out or gives way I'll have to postpone it for another day.

I'm hoping that won't happen. I'd like very much to see this through.

I'm most curious about the mental aspect of running for that long a time. I've never experienced "runner's high." I don't know if I'll be able to handle the discomfort and pain that's an inevitable part of crossing the finish line. How do you stay focused when running for more than two hours? I'll find out.

If I can finish this, who knows? Maybe I'll find a full marathon training plan and just keep going!

I haven't been in a pool in two months. I'm going to go back, but I've learned that daily exposure to chlorine isn't good for my lungs. I'm going to continue to mix swimming in, but it might be just a once per week Masters swim with my friends.

After all these years of pounding out yards, the biggest surprise is that I could stop swimming and actually feel better.

The journey has been a pleasure. I've achieved my real goal: my lungs are feeling much better. I don't wheeze when I run. I recently had to see a doctor. They took my pulse and blood pressure, per usual custom. "Are you a runner?" the nurse asked me. My resting heart rate was 50 bpm; my blood pressure was 98/70. I was startled to see both, because they haven't been that low in a long time.

I smiled and said "Why yes, I am a runner."

What will that next objective be? Where else could I use some change in my life? I've got some ideas.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers


Friday, July 13, 2012

Advanced Communicator Bronze







I gave my tenth and final speech towards the Advanced Communicator Bronze designation two weeks ago. Our VP of education submitted the forms to Toastmasters International last week. They sent the e-mail telling me that the next packet was on its way.

It took me two years to do it. I wasn't as crisp or diligent as I wanted to be. I chose two booklets with five speeches each. The first was Speaking To Inform; the second was The Professional Speaker. That second one was tough. Most speeches are 5-7 minutes long. The Professional Speaker has five assignments, and every one is 20-40 minutes long. I had a tough time writing and preparing for these. The difficulty slowed me down a great deal. But finally I slogged my way through.

The last speech was particularly challenging. I had to give a professional seminar. My two professions are mechanical engineering and software development. How could I manage that without losing my audience? Then my youngest daughter had a fine idea - why not talk about the Mandelbrot set that I wrote about back in March 2011? It gave me a chance to talk about sufficient mathematics to mention complex numbers. I presented some background about Benoit Mandelbrot, the mathematician for whom the set is named. I showed the Java code I wrote to perform the calculation. And then there was the payoff for all those who managed to remain in the room and not fall asleep: a presentation of the image itself.

It went very well, indeed. People were polite and feigned enthusiasm, even if they didn't feel it deeply. Some people thought I could have done a better job of tying the work and the image into real problems. Would they have been happy if I'd started talking about large eddy simulations of turbulent fluid flow? I was satisfied with how it went and my delivery. I felt comfortable and relaxed.

I was very glad to get it over with. It's motivating me to move on. I'm starting to think that perhaps I can achieve Distinguished Toastmaster status. Others have - why not me?

I think the secret is to write ten speeches out, rehearse them, and have them in pocket. Whenever there's an open speaking slot, I need to pounce on it. We have about 45 meetings a year. Each meeting has two speaking slots, so there are only 80-90 opportunities to make progress. I'd have to monopolize 11-12% of all speaking slots for an entire year to achieve my goal of earning Advanced Communicator Silver a year from now. It's a worthy goal.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers




Thursday, July 5, 2012

Higgs Boson Announcement









So what's the big news story of the day? The divorce of Scientologist Tom Cruise and his third wife, Kate Holmes?

Yes, but there's also the announcement that data collected at the CERN Large Hadron Collider in Geneva, Switzerland has gotten over the five sigma hurdle. Scientists are saying they've observed a "Higgs-like" particle. The Standard Model says that the Higgs boson is the carrier for the Higgs field, just like the photon is the carrier for the electromagnetic field. It interacts with other particles to characterize their mass.

It's a big deal for science.

So how does this affect the unemployment situation in the world? What will this do to correct the banking mess that we find ourselves in? How will this affect peace in the Middle East or the US presidential election in the fall?

Sadly, it won't affect any of those things.

I'm happy that the flame of inquiry into the way the world works is still burning, in spite of the damping effects of anti-intellectualism, superstition, magical thinking, and religion.

It saddens me to think that this was the kind of thing that my country used to lead. We were the first to the moon. Science has been responsible for much of the economic activity that makes up our modern world. There are no modern computers, no Internet, no wireless communications without science.

The Superconducting Super Collider was envisioned in 1983 and cancelled ten years later in 1993. I'm sure that the arguments against it were "practical" and "serious" and "reasonable".

Part of the problem is that economics are finite. It's true that we can't afford to do everything we'd like. When resources are scarce, choices have to be made. Those choices reflect what a people consider to be important. You find a way to do what matters.

But we had no problem anteing up $3-4T for wars in Afghanistan and Iraq. Compare that to the runaway $12B that had been spent by the time the SSC was killed. Was the benefit of the wars worth the cost?

James Clerk Maxwell published his equations for electromagnetism in 1861-1862 when the US Civil War was raging. We still live with the ramifications of that war, but the effect of Maxwell and science on the way we live today is far greater.

We value adventures in banking more today. A lot of the quants who are cooking up exotic derivatives used to be physicists. I'm sure they make a lot more money working for Goldman and Chase. What a shame!

It says something about us that we prefer short term profits over long term progress in understanding how the world works. It's a reminder that the progress we've made in enlightenment and reason is fragile. It can always be rolled back by magical, short-term thinking. I'm glad that CERN is keeping us moving forward.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers




Monday, June 18, 2012

Einstein - His Life And Universe










I just finished reading Walter Isaacson's biography "Einstein - His Life and Universe." I didn't think I'd ever have to read another Einstein biography after "Subtle Is The Lord" by Abraham Pais.

Abraham Pais was a also physicist, a younger protege of Einstein's at the Institute of Advanced Studies at Princeton. He knew Einstein personally; he was versed in the details of his work; he was uniquely qualified to write an intimate biography. His book is remarkable for its level of detail. Book publishers claim that adding a single equation, even one as "simple" and well known to the general public as , would reduce the readership by half.

If that's true, and knowing how rapidly converges to zero, then I must have been the only person on earth who ever bought and read Pais' work. Not only did he have plenty of equations, they included generalized tensors with sub-scripts and super-scripts proudly waving. I'm neither a mathematician nor a physicists, but I've taken a course that included generalized tensors. The presence of metric tensors didn't scare me away or detract from my enjoyment.

As much as I liked "Subtle", I think Isaacson's book was more fun and accessible. He made Einstein seem less like an intellectual, unapproachable deity and more like a real human being. I could appreciate him expressing his frustration towards the folks at Zurich Polytechnic for dithering about a job offer by saying on page 176: "The dear Zurich folks can kiss my..."

Einstein was a man of great humor. He was quite a hit with the ladies - divorced once, married twice, and amorous with a few more. He loved music, especially Mozart for his violin. He was detached from people, yet he had friendships that lasted his entire life.

Walter Isaacson is a terrific writer. I enjoyed this book very much. It makes me want to grad his Steve Jobs biography as soon as possible.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers



Sunday, June 3, 2012

Running Again






It's been too long since my last post. I've got a lot of pent up stuff to write about. I'll certainly improve on my poor showing so far this year.

Part of my problem was being away. I spent part of April in Ireland. Sounds like a post waiting to happen.

Another problem is that today is a perfect, beautiful, late spring day that makes it impossible to stay inside for long. I did well running throughout the winter and spring. I've stuck to half mile repeats on the road in front of my house. I try to pay attention to cadence, rhythm, breathing, pace, and staying relaxed. It's gone very well. I've had no injuries. I can actually say that I've enjoyed running! That hasn't been so for thirty years or more.

It was cool and sunny this morning, with perfect blue skies after a day of steady rain. I decided to head out for a run before lunch. I decided to go for a longer jaunt instead of half mile repeats. There's a route going in the other direction that has a long, gradual hill for the first mile, followed by a right turn and a mile of flat running with a hill at the end. I got to the end of that and took another left and kept going. Buck Road is a pretty one-mile stretch that ends at Route 66. The first three miles went very well for me. I kept up a consistent pace the whole time.

I was tired on the way back. The downhills that helped me on the way out were my enemy on the way home. Potential energy had to be paid back. I walked a couple of times, but nothing excessive; just enough to catch my breath. I finished the six mile run in a decent enough time for me. It wouldn't impress anyone to post it, but in the immortal words of Mark Logan: "Finishing is winning."

I was pleased to finish off such a long run in fine style. I never would have guessed that I'd still be able to run in impromptu fashion on a nice day at my age. We'll see how I feel tomorrow. It'll be a good sign if I recover well.

I started learning how to run again on 20-Jun last year. I've managed to keep it up the whole year through. I hope I can build on that over the next year and get strong enough to take it to another level.




profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers



Wednesday, February 22, 2012

The Sales Training Speech








I'm speaking at my Toastmasters club again tomorrow. I'm working my way through The Professional Speaker series. It's five speeches, each of which are 15-20 minutes long.

Tomorrow's assignment, the third in the series, is the Sales Training Speech. I'm supposed to be pumping up the sales troops for a company. I've chosen Astrum Solar as my company. I'll be throwing red meat to my sales force to get them to sell solar collectors.

This book is driving me crazy. The typical assignment book requires 5-10 speeches, each 5-7 minutes in length. I feel like I'm working hard to get to my Advanced Communicator Bronze designation. When I complained to one of our Distinguished Toastmasters about it, he told me that the book used to be 20-40 minutes per speech. Another of our three Distinguished Toastmasters managed to get through the more demanding version. I shut my mouth and sucked it up after hearing that. Fifteen minutes doesn't seem so bad.

A friend of mine is fond of saying that everyone should have three jobs in their life: manual labor, customer service, and selling. I've done manual labor. Does working in a grocery store count as customer service? I've never come close to selling. This will be as close as I'm likely to get.

My goal is to finish off the last two speeches before the Toastmasters year closes on 30-Jun-2012. If I can do that, I'll have achieved Advanced Communicator Bronze status. It'll be another rung on the ladder. Can I make it to Distinguished Toastmaster? We'll see.

Here's the text of my speech:

The Professional Speaker Project 3: The Sales Training Speech

(The company is Astrum Solar, a company that installs photovoltaic panels in the area.)

Solar energy has had a long, successful history. The sun has been delivering 5900 times the amount of energy that humans consume today every day for the last five billion years! A small fraction of what’s produced – just 0.016% - would be sufficient to satisfy the current needs residential, industrial, commercial, and transportation energy needs for every individual on the planet.

The source has been holding up its end of the bargain. There have been no outages, no equipment failures, no CEO mea culpas, no angry customers.
It’s the harvesting end that’s fallen short. Fellow sales professionals, I’m here to tell you that the sales process is an integral part of breaking the stranglehold that fossil fuels have on the hearts, minds, and checkbooks of consumers. It’s time for us to recognize the crucial part we have to play in changing our energy production and consumption habits.

How are we supposed to do that, you might ask?

Before I go further, let’s talk about how not to achieve this goal. Let’s look at arguments that have been made in the past and see how they’ve failed.

Solar energy was a very hot topic forty years ago. The United States experienced significant disruptions in oil supplies in 1973 and 1979. There were lines at gas stations. Prices skyrocketed. Consumers were looking for any technology that could deliver them.

If that wasn’t enough, we had the Three Mile Island meltdown in 1979. Wouldn’t such an event, one that ended the construction of new nuclear plants in the United States, make a low-cost, low-risk alternative seem more attractive?

Alas, this has not been the case. Solar energy continues to grow slowly, but it still delivers less than 10% of total consumption.

You can make appeals to serving the greater good. Individuals can use the sun to capture energy for power and heat in their home, cutting down on their reliance on public sources.

Our reliance on imported oil would be reduced. Imagine how different the world would be if we didn’t rely so heavily on oil for our energy needs! Wars to guarantee our supply would be a thing of the past. The transfer of wealth to oil-producing countries would end.

We could continue to spur economic growth without worrying about the amount of carbon dioxide we pump back into the atmosphere. Concerns about climate change and environmental impact could be decoupled from the Hobson’s choice of ceasing all economic activity.

These arguments seem pretty compelling, don’t they? Do you see solar collectors on every house? No! Are oil tankers being converted into cruise ships in the Arabian Sea? I don't see them. The appeals to the greater good have not made a dent.

They were true forty years ago. The fundamental story has not changed in all that time.

Why have customers not been persuaded? Why isn’t solar energy more popular with consumers?

Initial capital costs are relatively high. No one is going to lay out a lot of money to buy equipment that won’t pay back in twenty years.
There’s a well-established infrastructure in place to transport heating oil, gas, or electricity to our homes and to make it usable.

Affordable…proven…reliable technology.

There’s a chain of contributors that must work together to change this industry:
• Scientists need to be hard at work in their labs, driving the efficiency of photovoltaic materials up above 10% while keeping costs low.
• Engineers need to be hard at work taking progress in basic science and designing it into robust, affordable systems.
• Machinists and assembly workers need to be hard at work plying their crafts to create high quality, affordable products.
• Field service personnel need to live up to expectations as partners and representatives of Astrum Solar.

All these things are in full swing, but they don’t mean a thing unless we can make the case to customers that it’s in their best interest to make the switch from electricity generated by centralized power plants.

Do you see a theme here? What are the two things that our customers want?

First, they want energy to be affordable. Heating oil is currently around $3-4 per gallon; prices are relatively stable. A homeowner using oil to heat their home can predict what their heating costs will be for a given heating season.

Second, they want access to energy to be reliable. Sitting in the dark and cold won’t do. Breakdowns must be rare. When they do happen, there has to be a person on the other end of a phone line who can quickly sort out the situation.

Affordability is a function of large economic forces that are outside the control of the company.
1. We can’t control the price of oil.
2. We can’t wave a magic wand and make a scientific breakthrough happen.
3. We can’t change the fact that the sun doesn’t shine on rainy days.

But we can influence how our customers perceive Astrum Solar. It’s our job to tell them that this is a reliable company. We need to educate them about the fact that our products can provide power with a degree of reliability that matches or exceeds that of traditional power suppliers. We must engage them as a trusted partner, one that will stand behind the product and make right any breakdowns in a timely way.

Do you remember fall of 2011? I do. I’ve lived in my house for a long time. The worse power outage I’ve ever experienced prior to last year was the three days without power after Hurricane Gloria back in Sep 1985. For almost thirty years I’ve been able to count on power and heat in my house without fail, except for a few odd hours.

That clean record was sullied in the last six months. I had to endure not one, but two nine-day periods without power! Thank goodness both happened before winter had set in. My pipes would have been in real trouble if temperatures had dropped below freezing. Repair crews were already having trouble keeping up in the relatively mild fall conditions. Can you imagine having to repair a state-wide failure of the grid in sub-freezing temperatures or in the midst of a blizzard?

When my power was finally restored in November, my first thought was prevention: How could I ensure that this never happened again? I went out and bought a gas-powered generator and had a transfer switch wired in, but it seems like a temporary solution.

I think it’s time for something more permanent. It’s time to install solar panels at my residence that will supply electricity sufficient to meet my needs and even allow me to sell excess back to the electric company.

So how can we help?

We need to address affordability.
• Sales people need to work with field service personnel to properly size equipment to meet the needs of each individual household, taking into account special features of each site.
• Sales people need to inform customers about all available energy conservation programs. Minimizing power needs makes the installation’s job easier. Most customers can benefit from better insulation in attics and weather stripping in doors and windows.
• Sales people need to explore every subsidy from federal and state sources that might defer portions of the economic burden of installing solar equipment.

We need to address reliability.
• Sales people need to educate customers about warranty agreements that guarantee the uninterrupted operation of their installations.
• Sales people need to ensure that field service personnel are partners with customers to instill confidence and ensure reliability.

One day I was walking on a beach where the tide had gone out. The sand was covered with starfish, left behind by the sea. I encountered a small boy who was walking along, bending down from time to time, and throwing a starfish back into the ocean. I watched the boy throw starfish after starfish, yet they still stretched out on the sand as far as the eye could see. I went up to the boy and said, "Give it up! There must be thousands of starfish washed up on shore. What difference can you possibly make by throwing them back?" The boy looked at me without saying a word, then he picked up another one and threw it as far as he could. It landed with a splunk! "I made a difference to that one!" he replied.

We can fulfill that grand, large-scale goal of moving this country to a sustainable, independent, renewable energy economy. But we’ll have to do it one customer at a time. We must make Astrum Solar a trusted partner whose reliability exceeds that of traditional power suppliers. I urge you to be the public face of Astrum Solar. Our future, and more, depends on you.


profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers


Wednesday, February 15, 2012

New Haven Bound









I got a message from my wife this afternoon: our youngest daughter was officially notified that she's been accepted into the Ph.D. program at Yale. She'll matriculate in the fall to begin work on her doctorate in biophysics and biochemistry. She'll graduate in May from the University of Connecticut with both her Bachelors and Masters degrees in molecular cell biology. It only took her four years to get both.

She went to visit New Haven Thu through Sun last week. She loved everything about it: the students, the professors, the programs, the campus. It sounded like everyone was enthusiastic about what was happening, and there's a lot going on. We thought it might take a few weeks to hear the final decision, but one of the professors - the one she most wanted to work with - called her personally to tell her that Yale hoped she would come.

I have never been one to claim the accomplishments of my children as my own, and I'm not going to start now. I will say that I'm so happy for her. It's a well-deserved opportunity that she's worked hard for.

She's always had an unusual focus. Even as a young child, she could play happily by herself for hours. (Until her beloved older sister came along with other alternatives.) She loved puzzles; she sought out jigsaws that would challenge an adult, let alone a child. She was ambidextrous. She would pass the crayon from hand to hand as she colored pictures. She finally settled on her left hand for writing and preferred status, but it was touch and go for a long time.

She was quiet and reserved. She chose her words carefully and thought before she spoke. She still does, but now the words and ideas pour out of her at a faster clip. She's a confident woman these days.

She's always been a fine student. She "gets it" with math and science. I used to ask her if she needed any help with math when she was in high school. I learned right away that she didn't need my help. It was always a conversation about a topic that we both enjoyed. She would talk to me about problems she was given more as a courtesy to me than a plea for aid. She knew that it made me happy.

I've had the pleasure of repeating that experience throughout her undergraduate career. I swim on campus on Friday nights. I'll call her every once in a while after I'm done and ask if we can get together. We'll hit a dining hall or Starbucks, grab some tea and dessert, and I'll hear about everything she's doing in the lab and the classroom. Sometimes it's chemistry; other times it's quantum mechanics, math, computing, physics, or something else like a one-credit class in weight training. It astonishes me to hear how well she understands what's presented to her. She has a way of digesting the message, internalizing it, and making connections well beyond the context in which it was presented.

She is a biology major at the University of Connecticut. At the end of her freshman year she researched professors on campus and solicited them for a job in their lab. She found Robert Birge and sent him an e-mail. Did he accept undergraduates to work in his lab? He said it was rare, but told her to send in a resume anyway. He took her in and gave her a thorough grounding in research and how to conduct herself in a lab. Dr. Birge, his wife, Connie, and his team of graduate students have been so generous to our daughter. She worked without pay in the lab that first summer, but they found funds to support her after that. They've been the best mentors and examples imaginable.

I feel so fortunate to have the children I do. I wish I could point to some thing or another that my wife and I did that made this happen. Maybe I could bottle it or write a book to out-do a tiger mom.

I believe it's a combination of factors: genetics and the good fortune of peace and enough prosperity at home to meet their needs. After that it gets fuzzier. We read to them a lot when they were small and beyond. It is a common sight to see one family member or another draped on a chair or couch in silence, reading a book. The house is still full of them. We had television around, but it wasn't the 24x7 bombardment that is cable today. We didn't forbid television, but it didn't crowd everything out, either. We've never had video games; still don't. We had a computer in the house when they were young, but the Internet wasn't the distraction it has become. There were no cell phones.

They played a lot by themselves. We have an infamous book of games that they wrote together when they were small. ("The Queen Game" was a special favorite.) The rules included stuff like "If somebody gets hurt, don't cry or we'll have to go inside." Some of them make the hairs stand up on the back of your neck, but they're funny to read today. They had a lot of opportunities to use their imaginations to entertain themselves. They played with other kids, but they spent a lot of time with each other, too.

My wife is an educator, so she's always been on the same schedule as the girls: home in the afternoon when they returned from school, able to spend lazy summers at home instead of being shipped around to camps. Quality time with children cannot be scheduled. You're either there when they're ready to spill or you're not. Being at the kitchen table after school with a snack put my wife in perfect position to hear what was on their minds. I'm glad that one of us was able to be there. They're lucky to have had her: she's so attuned to them, always knowing just what to do.

They weren't home schooled. We sent them to public schools, where they had more than a few outstanding teachers, such as Mark Logan, Jason Courtmanche, and Madame Bender, and that made a great difference.

Both our daughters are a great mix of mind, body, and spirit. They're just terrific to be around. I'm grateful for the vantage point I've enjoyed. It's a great show to see.

Yale, you're in for a treat.



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers



Monday, February 13, 2012

The Volcker Rule




I find this article to be unbelievable.

Paul Volcker, the former chairman of the Federal Reserve who rescued America from high inflation, high unemployment, and high interest rates in the 1970s (remember 18% interest rates?) proposed a rule that prevents banks from making speculative bets with deposits. It sounds like Glass-Stegall redux: separate deposits from speculation.

The article feels an introductory lesson in how to spot the bias in an argument.

The very industry that brought us to the brink with their creative weapons of financial mass destruction, such as credit default swaps (selling fire insurance on your neighbor's house) and mortgage-backed securities (sending tranches of mortgages through a meat grinder to turn them into AAA rated securities, good as cash), criticizes the proposed rule. Jamie Dimon, the chairman and CEO of JP Morgan Chase, said "Paul Volcker by his own admission has said he doesn’t understand capital markets. He has proven that to me."

If that's true, I prefer the fruits of Mr. Volcker's ignorance to Mr. Dimon's subtlety and cleverness, every time.

I know less than either of these gentlemen, so I can't say that I have proof that the short-term loss of liquidity will not harm the economy. But with interest rates at an all-time low, Facebook able to raise $10B in an IPO, and the European Central Bank pumping trillions of euros into the Eurozone to prop up the PIGS, I don't think liquidity is a problem in the short term. It feels riskier to allow banks to operate unchecked. Yet nothing significant has been done to curb them in the last three years. The too big to fail are only getting bigger, and the rest of us are taking on more of the risk.

The arguments put forth in the link are the very ones that persuaded the House and Senate to send the Gramm-Leach bill to be signed by President Clinton in 1999. I'm not sure about the harm to the larger economy, but I know restricting these activities will have a tremendous impact on the bonuses paid to bankers.


profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers


Saturday, February 11, 2012

Tactical Solutions




"It's a tactical solution."

The tone was so dismissive. When did "tactical" become such a dirty word?

Software is rife with dogmatic pronouncements these days. BUFD is always bad. Unit tests are always good. Everyone knows that <insert-language-or-technique-of-your-choice-here> is better than anything else. Developers and coding are commodities. Process wins out over people; a good process can produce great code even when executed by average or below-average developers.

I personally hate dogma of all kinds. I recognize that accumulated wisdom needs to be respected. Physical laws are involate; I don't need to relearn lessons to keep fingers away from hot stoves. Gravity works. The second law of thermodynamics says that the egg I dropped on the floor might spontaneously reassemble itself before my eyes, but the probability is so small that it's never been observed. (But give it ten billion years and evolution could reconstitute it into something else, like a Boeing 737.)

Always relying on what everyone knows becomes a problem when context is ignored. Rules of thumb usually have exceptions, but the dispensers of dogma fail to bring them up or acknowledge them only grudgingly when they are pointed out.

There's also the question of who gets to decide what "everybody knows" when it's a non-scientific issue that's not entirely settled. History is full of people who have used dogma to serve their own ends. If the winners write history, it's also true that they decide questions of dogma.

I agree that slapping things together and being sloppy should not be anyone's goal in life. But prototyping something quickly, getting it out into the field, providing short-term value, and learning lessons from that experience has its place.

The objection to tactical solutions harbored by organizations is that they often become the de-facto standard solution, never to exit the portfolio again. This kind of organic growth can cause problems over time. But banning all tactical solutions feels like throwing the baby out with the bath. A better answer is to plan and budget for refactoring as needed. Retire those tactical solutions when the better, strategic thing comes along.

There's a tension between technology and economics. It doesn't pay to leap onto every new thing that comes along. The adoption curve for technology says that there are always leaders and laggards:


Organizations that are smaller, more nimble, and less risk averse get to be leaders and early adopters. If they play the game well they can get the jump on larger, slower, more conservative competitors. The larger competitors can leverage economies of scale and the damping that copious resources provide. They just need to be mindful of those tipping points that can shift the earth under their feet.

I wish that the timelines for payback were easier to quantify. Cost-benefit analysis can be made to come out to support the desired conclusion. Could Bayes and Monte Carlo be used to improve on what's done today? I'll have to think about that.

The truth is that everything is tactical. Technology is changing at a breathtaking rate. Every solution is tactical; they just have different timelines. (Just like there are no "permanent employees". We're all contractors.)

One final, funny thought: When I searched Google Image for 'tactical solution', I was surprised to see all the photos of weapons of all kinds. I had to scroll down several pages to find an image that expressed what I had in mind. The word is overloaded with military implications. It brings to mind SEAL squads and surgical strikes. That sounds effective when applied to certain problems. Why can't tactical software solutions be granted the same consideration when they apply?



profile for duffymo at Stack Overflow, Q&A for professional and enthusiast programmers