Posts by :
A while back, I was led to Jason Cohen’s blog post on not trying to look like a big company when you’re not. Jason makes a good point, that when Lockheed Martin is ready to order 1000 copies of new software they probably won’t buy it from a small company anyway. That’s often true. But I think there’s a more important reason to knock off the high-falutin’ corporate image thing.
When Microsoft came up with .NET environment and the snazzy new C# programming language to go with it, one of the design goals was to support code that could be shoved willy-nilly across unsecure networks. Thus the Common Language Runtime (CLR), which among other things creates a runtime environment that’s a little like the Java Virtual Machine (JVM) from Sun.
Code for .NET doesn’t execute directly on the CPU, and it doesn’t talk directly to the operating system. Instead, the CLR runtime–part of that big download when you pull “the .NET Framework” from Microsoft’s download site–treats the code as input and does whatever needs to be done at the CPU and operating system level for you.
Safety first, usually
Why would anyone bother with that? Among other things, the CLR itself is assumed to be “safe.” The CLR won’t do anything to interfere with processes that it’s not supposed to control; it observes security restrictions; and it doesn’t let you access code or data through pointers. So in theory, and most of the time in practice, CLR code won’t mess up your computer and therefore it is safe to run CLR code from untrusted sources.
The downside, again one among many, is that as a programmer you don’t have access to pointers in safe code. They’re automatically considered “unsafe.” Any code with pointers in it is “unsafe.” Any code that uses code with pointers in it… is “unsafe.” Any code that uses code that uses code… blah blah blah.
When it has to be fast
Right now I’m working on a .NET application that needs to pull a few megabytes of data from a legacy device driver and do a lot of math on it. It’s too slow to load all the data into a big
byte array, and then to access each element one by one for calculations. Instead, I wrote something like this, with the names changed to protect the innocent:
unsafe public class BitContainer
private IntPtr data;
public static int Size; // initialized elsewhere
public static int Count // however many shorts can fit into Size
return Size / sizeof(short);
data = Marshal.AllocHGlobal(Size);
public void LoadFromStream(BinaryReader input)
ushort* p = (ushort*) data.ToPointer();
for (int i = 0; i < Count; i++)
*p = input.ReadUInt16();
public void GetItemsOverThreshold(int threshold, int max, ref List<Item> items)
ushort* p = (ushort *) data.ToPointer();
for (long i = 0; i < Count; i++)
if (*p >= threshold)
if (items.Count >= max)
throw new ApplicationException("Too many items passing! Turn down the gain?");
long x = i % FRAME_WIDTH;
long y = i / FRAME_WIDTH;
items.Add(new Item(x, y));
The alternative to tearing through data with a C-style pointer would have been to pick through the elements of a .NET array of byte or short values. Each array access goes through the CLR for bounds-checking and the like, and when you’re hitting literally millions of input values that’s just too slow. I originally did the BitContainer code above that way, and it took hours.
It’s a pain to test, and it’s sometimes hazardous, and it contaminates your entire application with the unsafe label, but dropping under the CLR and writing fast code with pointers is sometimes the only way to get acceptable runtime speed.
Recently I wrote about some of the Really Big Cool Commercial Things people tried to do on the Internet when it was still kind of a fad. These Big Things tended not to work out either because they didn’t make sense to begin with, or because their perpetrators could never settle for something that actually worked and delivered value.
I think (and said then) that this is probably because people often enter into business for reasons other than doing stuff that works and delivers value. If, on the other hand, you *cough* do stuff that works and delivers value it’s a lot more likely your business will do well. Notably, it doesn’t have to have an amazing idea behind it.
My favorite example of this is those nifty little PC-based cash registers. I’m a bit out of date on who has what these days, but back in the early and middle 1990s it seemed like one out of four mall stores had something from Systems for Today’s Retailer, which went by STR most of the time when I worked there.
STR started a little like this. Scott and Chuck what I call a dumb idea: to mimic those $10,000 intelligent cash registers that know how much everything costs, calculate discounts, print time cards, keep inventory up to date, and send sales data back to the corporate offices. Except they would do it for around $3,000 on an industry-standard PC.
That’s all. That was the big idea.
I’m sorry, there just isn’t very much to it.
It hit big. Everyone wanted this. They made their first sale to a small chain of jewelry stores headquartered in California. Then there were a couple of local Ohio customers. A place that sold swimming pool supplies, stuff like that. There was a chain of pet supply stores. And a nascent chain of computer superstores. None of these were gigantic wins, but they were mostly solid customers who paid a fair price for a good product.
Hey, there were a lot of problems with the software. By the time I showed up as the fifth employee, Scott’s office contained a clear box of 5.25″ floppy diskettes, generally three for the uniquely copied source code for each client’s custom applications. “Source control” was pulling things out of the box and putting them back.
What we considered the “base” application was about 160,000 lines of Clipper code, largely cut and paste from previous versions. In fact, one of my first really big refactorings involved merging eleven slightly different versions of the main item entry function into one, with just a little branching to distinguish the eleven kinds of transactions. It wasn’t the best code base to work with.
But it didn’t matter, not then, not really.
The key thing Scott and Chuck did, and this was seriously brilliant, was to figure out what people wanted to pay money for and making it work well enough to use. (Well, that and hiring me.) In a few years, STR had become fairly stable and rather profitable. We had matching 401(k) plans and good health insurance. It was a good place to work, and the software itself got quite a bit better as we improved our code and project management practices.
I started working with those guys almost twenty years ago now, and I still keep thinking… wow, it’s just a cash register with a regular computer in it. That’s all.
What’s the difference between a Great Idea and a Great Business?
One is fun to think about. The other is a lot of hard work.
And what do you know, tonight begins Startup Weekend Cleveland. In about five hours, I’m going to join about seventy other business and technical people to talk about ideas, pick a subset that the group will develop into products, and personally contribute to one of those. Which ones will be most successful? I’m betting on the ideas that make people say “I need that!” not “Oh cool!” In other words, the stuff that works and creates value.
Sometimes projects are made to suck because people are cussed and they just won’t listen.
There was this time in late 1988. It was my first job out of college, with my freshly minted B.A. in Mathematics (!) and a lot of enthusiasm. It was a little financial services company just off East 9th and Euclid.
One of the first things they asked me to do was… kind of a drudge job. See, there was this database on our IBM System/38 mini. It had a file that included (among a lot of other fields) customer identifying information, balance due, and last activity date.
I am trying, with only partial success, to apply what I’ve learned in Working Effectively With Legacy Code by Michael C. Feathers.
Feathers is a huge advocate of test-driven development. He puts it out there on page xvi: “Code without tests is bad code.” He defines “legacy code” as, strictly speaking, any code that isn’t already under unit tests. At first it struck me as a funny definition, because obviously lots of code is written today–even by me–without unit tests, and how can it be right to refer to software nobody’s even thought of yet as “legacy”? But for purposes of the book it works.
A few months ago, a client had made a few changes in some nifty little WinForms application I’d written for them and then wanted me to pick it up again from there.
I know that sounds like a nightmare, but the person who did the changes is really sharp, and he definitely improved on my work. So it wasn’t like I had to go and fix all the problems he introduced. There weren’t any.
No, I’m writing this because of a different complication.
It happens a lot, especially when working on legacy code, that you can’t figure out a “business logic” algorithm that isn’t already well documented. Sure, it’s in the code, but so are a million other things, and you can’t eyeball the part that does all the calculation. The client is asking for a change or a fix and you’re not sure where to start.
That’s when I think you can do three things at once: improve the overall structure, impose some unit testing, and solve the problem you were asked to. Refactoring does all of these.More
I must not fear.
Fear is the mind-killer.
Fear is the little-death that brings total obliteration.
–the “litany against fear” from the science fiction novel Dune
Yesterday I got a call from a prospective client whose Project Does Not Yet Suck, but it’s starting to make little slurping noises.
The situation calls for someone who is “aggressive without being arrogant” and “can handle pressure” while “getting stuff done.” And I thought hey, maybe this project isn’t necessarily right for me for some other reasons… but she did catch the spirit of what I talked about a couple weeks ago.
See here. Humility is not contradicted by effectiveness. It just isn’t. They’re different things.More