OdeToCode IC Logo

A CEO and His BMW (Small Company Life)

Thursday, July 22, 2004 by scott
Optimism is a primary trait of startup company CEOs. With all of the risk and obstacles involved in getting a company off the ground, they have to be optimistic. The type of optimism goes beyond “glass half full” optimism. I’ve worked with CEOs who, when spotting an empty glass sitting on the hot asphalt of a desert highway, will convince everyone nearby that a freak microburst of rain is inevitable, and the glass will be full any moment now.

I worked with one of these CEOs during the bubble years. He was a charismatic factory of entrepreneurial ideas. Once the big money came in from the venture capitalists, however, the collective wisdom of higher powers decided the company needed an experienced business person at the helm. We didn’t need optimism anymore, we needed execution. So we acquired a new CEO who was equipped with the people skills of an ostrich and completely devoid of creative ideas.

Actually, I take that back – he did have one idea I can remember. We were working with a customer who built on the Java platform and wanted to use some of our COM+ components. At one point he wandered into a common engineering area and asked if we could “SQL some data around” to provide integration. Other than this, I don’t remember him ever coming out of his office, except for the monthly company meetings.

The company meetings happened every month only because we had monthly layoffs. I suppose these meetings were meant to boost the company morale and assure us everything was under control. It was during one of these meetings when the CEO described layoffs as “a way to scrub the barnacles off the bottom of the boat”. I’ll leave it as an exercise for the reader to determine if these words contain any inspirational value, because it is a subjective call. I can only remember thinking what we really needed during these times was the unabashed optimism of old. Well, that and another $30 million.

During the course of a year we dwindled from a headcount of about 150 people to 12. Sometime near my last paycheck the day came for Mr. CEO to go. The word was getting around that he was packing up in his office. We saw him roll a chair out to his 2-door sports car. We saw him carry a desktop computer to the car. A crowd gathered to watch from afar. Another computer went out the door.

I remember reading once about a contest at a car dealership. The person who could guess the number of golf balls that would fit into an SUV would win the SUV. I’m sure this guy knew exactly how many golf balls fit into his car, because he was using every square centimeter of space. Next to go was a bookshelf. It was incredible to watch.

A mob mentality began to form, and we began to collectively speculate if we should start tearing the place apart and taking it home. Being a mostly civilized group though, I think we ultimately decided just to go out for lunch and celebrate the end of an era. Not that we really had a reason to celebrate, because our time was coming soon too, and by the end of the month the company would officially close the doors. I wasn’t allowed to take any office furniture with me when I left, but it wasn’t the last time I saw my desk….

The FBI Raid (Small Company Life Flashback)

Wednesday, July 21, 2004 by scott

Years ago I used to juggle two different projects by spending my morning writing C and assembler code for 8-bit embedded CPUs, and in the afternoon I’d switch over to Windows code with Borland’s OWL framework. This was a day I’d never get to launch the Borland IDE.

My office was in a building housing two companies. My company occupied the front of the building, and the second company (let’s call it XYZ Inc.) occupied the back of the building. The only proper way into the back of the building was to go through a door just past my office. These two companies were distinct legal entities, but were closely related. By closely related, I mean the owner of company XYZ called the owner of my company “son”. It was all one big family, if you know what I mean.

As the reader, you need to imagine yourself in my position. You are in a reasonably private area, like an office. You have your favorite music on, and a caffeinated drink by your side. You are cranking out code. There could be a Mardi Gras parade happening outside your window, but you wouldn’t notice, because you are “in the zone”. Such was my situation on this particular morning.

Suddenly, a demanding voice breaks my concentration. “Is this company XYZ?”, the voice says tersely. It was like an order in the form of a question.

Now my first thought, as I was slowly coming out of my concentration, was that if the FedEx delivery guy was going to be this rude, then I had absolutely no obligation to give him a quick answer. In fact, I thought, I might just start by shooting him an annoyed look. I mean, if you value running around lost and interrupting otherwise productive members of the work force with rude questions, give up driving for UPS and join a company who performs ISO 9001 audits.

I turned slowly to the doorway, only to notice a man with a gun on his hip. You can imagine my surprise at having misjudged the situation. Now my lips were already pursed to let out an emphatic “no”, but my brain instantly went off in a number of different directions.

My first thought was how this guy, in his blue windbreaker and jeans, looked like he walked right off the set for the TV show “Cops”. Except “Cops” isn’t filmed on a TV set, it is supposedly “reality television”, and a man with a gun (and a badge on a chain around his neck) was now at the edge of my office staring intently.

My second thought centered on the man’s finger, which was pointing directly into the center of my office, as if this could be the source of all problems in the world. I knew my job now was to divert his attention to some other office in the building, but I was beginning to feel a bit queasy, which led me to my third thought.

My third thought was that I was taking entirely too long in analyzing this situation. I should have long ago calmly replied that the company he was looking for was through the doorway at the end of the hallway, thank you very much, and have a pleasant day. Instead, I was sitting here for what seemed like an eternity, and it suddenly it dawned on me I might appear guilty.

Guilty of what? I thought to myself. What could I have done to attract the attention of a law enforcement officer? But if I wasn’t guilty of something, why didn’t I just answer? Get a grip, I told myself. Quit staring like a deer in headlights and make this unpleasant situation go away.

I never did get to answer, because suddenly a voice in the hallway shouted “it’s through THAT door”, and a parade of 12 armed men moved past and into the second half of the building.

Now, I thought to myself, would be a good time to go to lunch a little early a grab a sandwich.

The deputy at the front door informed me nobody was leaving the building, so I did what everyone else at the company was doing, which was forming a circle in the lobby and speculating as to what was happening in the other half of the building.

Over the next hour or so, agents loaded file cabinets and computers into a rented U-Haul truck, which I thought was interesting. I imagine the FBI does this a few times a year, and maybe if they actually purchased a truck and took decent care of it they could save some taxpayer money over time. On the other hand, you never have to take a rental truck for an oil change, or wait for it to completely stop before switching gears from reverse to drive, so maybe it evens out.

In any case, here was what happened. It seems our sister company imported some electronic components from Japan. These components appeared in medical devices, but the U.S. custom forms said they were intended for cheese analyzers. Oops, an easy mistake to make. Unfortuantely, this lack of attention to detail attracted the attention of several government agencies, including the FDA, U.S. customs, the FBI, and the local sheriff, all who sent representatives on-site that day.

I left that company soon afterwards, but not because of the raid. I had decided I wanted to work for a company whose only product and focus was software. I didn’t know it at the time, but the bubble years were approaching, and small company life was about to get even more interesting...

Small Company Life

Tuesday, July 20, 2004 by scott
I was thinking back today at some of the weird and funny stuff I’ve lived through at startup companies over the years. Someday I should write in more detail about the following:

The FBI raid.

The CEO who, on his last day, managed to cram 1 executive leather chair, 2 desktop computers, a file cabinet, and a bookshelf into a 2 door BMW.

The intern who wore pink teddy bear clips in his beard.

The CEO who painted his toenails the company colors.

The CFO who was amazed to see how Excel could recalculate cell C3 based on the contents of cell C1.

The CTO who enlisted the aid of a software developer in chasing down escaped chickens back at the farm.

What it is like to show up for work at a new company and see the office furniture from my last company being delivered by tractor trailer.

Why I should not be given the opportunity to take the helm of a yacht for any length of time.

What it is like to have a practicing gastroenterologist at the office part time and how this leads to errant phone calls from people describing the odd color of their stool and demanding advice on what to do about it.

The vice president of global sales who drove a different vehicle to work each day yet never made a sale, and why I think this is because he wore Hawaiian shirts and Nikes during appointments at Fortune 50 companies.

Last but not least: Why engineers should not be required to move office furniture when moving to a new building.

Server Or Workstation Garbage Collection?

Friday, July 16, 2004 by scott
I did some experimentation this evening because I read something that struck me as odd in a comment on Scott H’s blog.

First, some background. There are two versions of the garbage collector for .NET. The garbage collector optimized for multi-processor machines (packaged in MSCorSvr.dll), and the workstation garbage collector (packaged in MsCorWks.dll). I can see who is running the workstation garbage collector on a Win2003 machine using tasklist from the command line:

tasklist /m mscorwks.dll
 
 
Image Name                   PID Modules
========================= ====== ==================
OUTLOOK.EXE                 3352 mscorwks.dll
mmc.exe                     2084 mscorwks.dll
w3wp.exe                    3436 mscorwks.dll

One of the comments suggested going into the .NET Configuration 1.1 MMC in Administrative Tools, right clicking on My Computer, and setting the garbage collection mode to “Run in foreground for server applications”.

This struck me as odd, because in doing some review work for the Performance and Scalability Guide I found out that choosing the garbage collector implementation with a .config file setting was not going to be a runtime feature until the Whidbey timeframe. I tried this configuration option and reset IIS. After hitting a local web application and running taskmgr again my ASP.NET worker process (W3WP.EXE) was still showing mscorwks.dll loaded, not mscorsvr.dll

After a little more digging I discovered the MMC toggles the gcConcurrent element in machine.config:

<runtime> ...
    <gcConcurrent enabled="false" />
</runtime>

It turns out the gcConcurrent setting does not change which garbage collector loads. gcConcurrent only has an impact on the workstation (MsCorWks.dll) implementation of the garbage collector (it is effectively ignored by the server implementation), and furthermore only changes the GC behavior on multiprocessor machines.

With the setting enabled the garbage collector uses an additional thread to build a graph of unreachable objects. The rule of thumb is, gcConcurrent=”true” (default setting) will provide for a more responsive application, but can also let the working set (memory usage) grow larger. You’d have to carefully test an application to see if disabling gcConcurrent actually helps an application’s performance or memory usage. The most detailed source of information I’ve found in one place on this subject is Jeffrey Richter’s book.

<SARCASM>To turn this into a spirited debate, I want to point out that developers who use MsCorSvr.dll on average earn 26% more than developers using MsCorWks.dll. </SARCASM>

Honestly, with all the cycles the .NET community burns on language debates, we could have built another language.

Generic Gotchas

Thursday, July 15, 2004 by scott
The introduction of generics will be a welcome addition to C# and VB in 2.0, except the change is little more disruptive than I would have thought. Consider the current use of Hashtable:

Hashtable lastNames = new Hashtable();
lastNames.Add("Beatrice", "Arthur");
lastNames.Add("Lucille",  "Ball");
 
object name = lastNames["Audrey"];
if (name == null)
{
    lastNames.Add("Audrey", "Hepburn");
}

Now here is how it might look after an porting to use the generic type Dictionary<K,V>:

Dictionary<string, string> lastNames;
lastNames = new Dictionary<string, string> ();
lastNames.Add("Beatrice", "Arthur");
lastNames.Add("Lucille", "Ball");
 
// the next line throws KeyNotFoundException
string name = lastNames["Audrey"];
if (name == null)
{
    lastNames.Add("Audrey", "Hepburn");
}

In Beta 1 the indexer throws an exception if the given key does not exist in the collection. If this is not desirable behavior, you can use the ContainsKey method to check safely if a given key exists. The current behavior makes porting code based on Hashtable to Dictionary<K,V> a bit trickier.

I think the current behavior is justified. What would happen with a Dictionary of integer values when you pass a key that does not exist? There is no possibility of returning null for a value type, and returning a default value (0) seems misleading and bug-prone.

Another gotcha is in the second sentence of the documentation for every generic type:

This class is not CLS-compliant

The question is: Do I care?

I’ve read articles about how being CLS compliant will allow for interoperability with a wider range of .NET languages. This could be important for library designers targeting the 0.4% of the market using Cobol.NET and Fortran.NET. I did a quick test to see the impact on the other 99.1%. First, I put the following in a C# class library:

public class Class1
{
    public Dictionary<string, int> GetDictionary()
    {
        Dictionary<string, int> foo = new Dictionary<string, int>();
        foo.Add("test", 2112);
        return foo;
    }
}

Next, a quick VB program to use the C# class. (I was a little worried I might have to dig to find generics syntax for VB, but my fingers had a spasm and intellisense auto-completed the entire program. It was amazing. Did I mention my cat wrote a Tetris knock-off with Whidbey last week?).

Sub Main()
    Dim c As New ClassLibrary1.Class1
    Dim bar As Dictionary(Of String, Int32)
    bar = c.GetDictionary()
    Console.WriteLine(bar("test").ToString())
End Sub

It all just works.

For the applications I work on, generics are powerful enough to sacrifice CLS compliance. I imagine this will be the case for the majority of developers. Porting an existing codebase heavily into collections to the generic types won’t be automatic, but nothing to sweat over if all the unit tests are written, right?

Book Shopping

Wednesday, July 14, 2004 by scott

I've been running low on reading material, so I decided it was a good time to go book shopping.

One title that has caught my eye with it's quirkiness is Coding Slave. Judging by the web site, this should be entertaining.

I also found out Neal Peart has a new book on the way. I'm just wondering if I should pre-order through Amazon, or wait until the Rush tour hits Virginia this August. Pehaps some copies might be available for sale there. Decisions, decisions.

More Fun With Generics: Action, Converter, Comparison

Sunday, July 11, 2004 by scott
As a follow up to yesterday’s blog about the Predicate<T> delegate, I wanted to try out the three additional delegate types in the generics area.

First, a new type to work with:

class Person
{
   public Person(string name, DateTime birthday)
   {
       this.name = name;
       this.birthday = birthday;
   }
 
   public string Name
   {
       get { return this.name; }
       set { this.name = value; }
   }
 
   public DateTime Birthday
   {
       get { return this.birthday; }
       set { this.birthday = value; }
   }
 
   string name;
   DateTime birthday;
}

The Comparison<T> delegate represents a method used to compare two types. If you have ever needed to define an entirely new type deriving from IComparer just to tell Array.Sort how to compare two objects, you’ll appreciate the brevity in the following sample.

List<Person> list = new List<Person>();
 
list.Add(new Person("Alex", DateTime.Now.AddYears(-30)));
list.Add(new Person("Neal", DateTime.Now.AddYears(-20)));
list.Add(new Person("Geddy", DateTime.Now.AddYears(-25)));
 
list.Sort(
      delegate(Person x, Person y)
      {
        return Comparer<DateTime>.Default.Compare(x.Birthday, y.Birthday);
      }
 );

Next is the Converter<T,U> delegate. Use this delegate to convert each object of type T in a collection to type U.

List<int> yearList;
yearList = list.ConvertAll<int>(
        delegate(Person p)
        {  
            return p.Birthday.Year;
        }
   );

Finally, there is the Action<T> delegate. Use this delegate to perform an action with each object of the collection.

yearList.ForEach(
        delegate(int year) { Console.WriteLine(year); }
    );

I am generally grouchy about any new language feature until I can write some code and figure out its purpose in life. Generics I knew would be a hit, and after writing this code I’m starting to warm up to anonymous delegates.