Monday, June 18, 2007

That Contest I Didn't Win (But Could Have)

After an interminable wait, the OMGWTF contest results are in. It looks like I'll have to get my MacBook by buying one, because I sure didn't win the one in this contest. Though I did make it into the top twelve, and I got a great write up. That's something, for sure, and having people like Raymond Chen and Joel Spolsky actually read your code is an honor. I just wish I knew what they thought of it, because I didn't even get mentioned in the final decision. I like to think this quote, taken out of context, was prompted by my entry: “Joel said about “clever” solutions in general, “nobody told these people that pure OO design isn’t always the best way to write a given piece of code.”

It looks like the judge's choice for the contest winner was the most "believable" entry; it contains code that is strange, but strange in a way that you might actually see in a real project. Perhaps I overshot the mark then. My entry was pervertedly clever, but was a little too strange to be believable. I didn't expect to get the "crowd favorite" award either; that clearly belonged to the OMGOCR calculator. But last I checked, my entry was doing 1 percent worse on the polls than the votes for "None of the above!"

Despite the fact that Alex gave my entry a great write-up, there was quite a bit of material I wrote to him that he had to leave out of his article due to space limitations, and I've obtained his permission to post that material here. (Alex Papadimoulis is editor of www.worsethanfailure.com, the site which held the contest.) I've been too busy to blog for several weeks, but with the contest getting over, I figured I'd better make it snappy with this post before it became old news. Here is the full text of the conversation I had with Alex about my contest entry:

• Where did you grow up and where do you live now? Anything fun/interesting about these locations? Do you have any kids, family, etc?

I grew up in poverty. My father was a working class man at a time when the type of jobs he had grown up doing were leaving the US to go to third world countries. When I was young we moved all across the country, sometimes as much as four times a year, as my father searched for work. I've lived in or been to twenty-five of the fifty states; by the time I was in sixth grade I'd gone to more schools than grades. I've seen much but held on to little - we could never afford to ship anything with us when we moved, only what could fit into the trunk of a car. So when people ask me, where did I grow up, I... don't know what to say. I guess I grew up on the road.

When I was twelve, my parents moved for the last time. My father got a settlement on his social security disability and bought a tiny house in a very small town in rural western Oklahoma. After a lifetime of wanderlust, he is content to never move again. I emphasize with him; I too am sick to death of moving. But my journey is just beginning.

I could not stay in that small town. If you live in western Oklahoma, you will be a farmer, or a rancher, or work in the oil fields. There was no place for me there. When I was seventeen I joined the Marines for no other reason than to get away from the life I felt trapped in. I did not believe I would ever go to college. Growing up in a family with no money, I was raised to believe that it just wasn't in the cards for me.

I became a Small Computer Systems Specialist in the Marine Corps. I went to school in California and was stationed in Washington, D.C. (I loved D.C!) Working alongside civilians, I came to realize that the only difference between their opportunities and mine was the degree. I liked my job, working with computers, but I did not take well to military life. I also really wanted to be a programmer, but my duties only included network administration. If I went back to school, I could do what I really wanted to do, and be a civilian.

I could have gotten a tuition scholarship on academic merit without having to join the military, but that would not provide money to live on. After I got my honorable discharge, the G.I. Bill money enabled me go to college. I chose a small college (Southwestern Oklahoma State University) because it was close to where my family lives. Since then I've been blessed by many great opportunities. I got an internship writing business software, a summer fellowship doing undergraduate research in machine learning and robotics, and most recently I became the first student from a regional university to get a NASA internship. I also met the love of my life, Melissa, in college. We will be married next year, after I graduate. For the moment I'm living in Norman, Oklahoma, finishing the second summer of my undergraduate research program at the OU.

• When and why did you get into the field of computer programming? What college/university did you attend (if any)?

In elementary school, I got my first exposure to computers playing Commander Keen on my uncle's computer. I wanted to write my own games, but without a computer of my own I satiated my desire to program by performing thought experiments, trying to figure out from first principles alone the algorithm Commander Keen used to draw tiles and sprites.

It wasn't until I was twelve that I got my own computer. Someone gave me an Epson QX-10, which was an old 8-bit Z80 machine with 256K of RAM. It was older than DOS; instead, it ran CP/M. To put this in perspective, I was running CP/M on a Z80 while my schoolmates were running Windows 95 on 586 Pentiums. My cousin asked me if my computer was a dinosaur; I told her that it wasn't even that evolved, "more like a trilobyte computer!" I loved it though.

(This topic parallels something I recently wrote in my blog: http://dennisferron.blogspot.com/2007/05/phosphor-green.html )

Most people get their start in programming by learning BASIC. I've never met anyone else who learned to program in dBASE II. Unlike most 8 bit computers, my Epson did not come with BASIC. It did come with a scattering of business software disks, including the dBASE programmable database software, and a slim, friendly introduction to programming in dBASE script. We're talking a book less than 100 pages and a language that only let you have 80 integer variables - that's all I got. But it rocked my world. As I read about if-statements and loops and variable assignments, I did not so much learn the material as experience divine revelation. I wanted to shout it from the rooftops. I would read about an algorithm and shout, "Aha! Of course! THAT'S how it's done!" Everyone thought I was nuts.

There was literally not a single soul in my small school who was interested in programming, besides me. I learned to rely on myself to overcome problems and answer questions, because there just wasn't anyone else around to ask. You learn to be resourceful that way; a child can shirk responsibilty for hard problems onto the shoulders of an authority figure, but when it came to computers I was the highest authority I had. So if I ran into something I didn't understand how to fix, I went at it like a dog with a bone until I figured it out myself.

dBASE was ultimately too limiting a programming environment to write games on. Just as I was nearing the end of what I could do with dBASE, my uncle built me a 486 machine with Win95 to replace my Epson CP/M machine. On the Windows 95 CD, tucked away in an obscure folder, I found my next great love: QBASIC. If I could not get my friends interested in programming itself, I could get them interested in the games that can be written in QBASIC. It was shortly after discovering QBASIC on my own machine that the realization hit me that not only were the Gorillas and Nibbles games on the school computers written in QBASIC, they came in source code form. I spent countless hours at school hacking those two games which came on the school computers, and my friends actually enjoyed watching me program. I learned the uncommon skill of entertaining an audience while programming, which is something that has helped me immensely whenever I have given code reviews in my professional life today. I also learned to program while explain what I was doing to someone watching over my shoulder, and still to this day I write code as though I have someone watching, trying to understand what I am doing.

Since then I've had a passion for learning every computer language I can. I'm now studying for a bachelor's in Computer Science at Southwestern Oklahoma State University. At the risk of upsetting my professors, I have to say I haven't really learned anything in class that I hadn't already picked up before I came here. But what I have had is the wonderful opportunity to do internships and participate in research activities, and it was through my university that I was enabled to do this. And furthermore I stress the words in class because while I get nothing out of lectures, I have had classes which featured projects we had to do, and I certainly learned things after class while doing those projects.

• What is your job title and where do you work? How long have you been there?

I've never liked the generic term "student" for encompassing all of the things I do. This summer I'm a undergraduate researcher in machine learning and robotics at the University of Oklahoma. I'm also a .NET software developer for a great software company called CDF Associates, which I will be rejoining when I go back to my usual college in Weatherford this Fall. I'm in my second year with the research program and have been working off and on for CDFA since my sophmore year.

• How long have you been a reader of WTF? Have a favorite article/story? Submit any?


I've never submitted an article, but I've been a long time reader of the site. I seriously thought about submitting this story: a coworker of mine designed a new user interface for submitting data in a grid (a problem which has obviously never been solved before). The grid featured different colors for validated rows depending upon whether they were new, old, canceled, or "uncanceled". (The system had appointments you could cancel or undo cancellation on.) If you hit "OK," the form saves the data. If you hit "Cancel" he wanted it to ask, "Are you sure?" Apparently it was tongue-twister Friday that week because he came up with a slightly different way of phrasing the question. Here's the message box the application brings up if you hit cancel: "The rows which were uncancelled that are now cancelled are highlighted in white. The rows which were cancelled that are now uncancelled are now highlighted in gray. Are you sure you want to cancel the uncancelled rows and/or uncancel the cancelled rows?"

He couldn't understand what I found wrong with that. I told him to say it three times fast.

• What drew you to the OMGWTF contest?

I suppose you're looking for an answer that involves the recognition of my peers, the thrill of the competition, and infinite glory (or at least infinite ego). Nope. I did it for the Mac Book. Ever since I started this undergraduate research program, I've had an acute case of Mac envy, but can't afford one for the foreseeable future. Among computer science researchers, all the cool kids have Macs. In the lab we have mostly Linux machines, some Apple, and a few Windows computers - but we put those in last kind in a corner and do not speak of them. Sometimes we make the sign of the cross and throw garlic at them, just in case. Anyhow I noticed that with me on my Windows XP laptop (I'm such a hypocrite), and some of my friends on Linux and some on Mac OS, when it came to basic day-to-day use, the people using Mac OS would actually get everything done twice as fast as the rest of us. It gets points in the usability department, to be sure. But the most important factor is that carrying a Mac around will increase my "street cred" here in the AI lab.

• How did you come up with the idea?

I drew on a number of different sources. I've been thinking lately about the difference between static and dynamic typing, since I learned Ruby after being a C++/C# aficionado. The difference is in static typing variables have types and that determines the type of value it can hold, but in dynamic typing the importance of each is reversed - only values have types, so a variable just has the type of whatever it's holding. I have finally come to the conclusion that static typing is a false savings - it appears to be helpful but ultimately causes more work than it saves. To illustrate the ridiculousness of static typing, I imagined a fictional language in which not only is the integer a type, but every value of an integer is a different type from every other value. "Two" is a different type than "Three", and you cannot store a value of type "Three" into a value of type "Two". If you, good heavens, need to store both "2" and "3" into a variable, you must create a new class and multiply inherit from both "Two" and "Three".

When I saw the calculator contest, I realized it would be fun to try to simulate this situation in C++. Of course the trouble is that under normal circumstances the "petrified values" language I described wouldn't actually be useful. However, for some time I have been aware of the concept of template metaprograms in C++. See, it turns out that C++ templates are so complex that they are actually Turing complete! They can be used as a pure functional, recursive language that "runs" at compile time. Since templates act on types, it should be possible to write C++ templates which perform recursive programmatic functions on types. Instead of passing the value 2 to a normal function, I pass the type Two to a C++ template.

Which brings me to my next point. Although I didn't actually have to use any true template metaprograms in my code (my templates are similar to metaprograms, but not really), when I found out that template metaprograms were possible in C++, it brought a startling and abrupt end to my love affair with C++. You see, the cardinal rule of good software design is to implement the same feature only once. Once I learned of the existence of template metaprograms, I understood that C++ implements two Turing-complete languages. One language runs at run time (normal C++), and it is classified as an imperative language. The other language, templates, runs at compile time but is a pure functional language. Though they are locked in a perverse embrace, the two languages could not be more different from one another. It begs the question, why would you have one language that runs one time only (templates that run at compile time), and another language whose code runs every time? That was how I came to understand that templates are just a poor work-around for the real underlying problem: you only need templates because the static typing is too limiting. A language which uses dynamic types does not need templates because you can do operations on types at run time with the same language you use for other problems.

I could go on but I'll suffice it to say that I designed the calculator to be an example of what I think it wrong with inheritance and static typing, and I also wanted to push the boundaries of what is possible with the C++ language. For instance, in the project I actually invented a new kind of method dispatch which selects base functions by namespace with the aid of templates.

• How long did it take for you to develop?

I didn't find out about the contest until there was only a week to go, and by then I had already made plans to go away over the weekend. So I had to finish it in about four days. That's nothing. I was once assigned to a project which had been worked on by two other programmers for months. It was a calendar and scheduling service. When I inherited the project the other two programmers were reassigned and the boss told me I had two weeks to finish the project for them and ship it. I looked over the code and the forms but there was one thing I just couldn't understand.

Me: "Um, it's supposed to be a scheduler, right?"
Boss: "Sure!"
Me: "Well, I don't see any calendar in here, or any code that has to do with calendars or appointments..."
Boss: "Oh, I had them do administrative and maintenance forms until you got here. You know, all the icky support stuff. Don't worry! I have faith in you!"

Two weeks to go and the application had not one line of code that actually dealt with what the app was supposed to do! Egads. In two weeks - I had it done. Didn't sleep for days and my girlfriend thought I disappeared from the Earth, but I shipped it, baby!

(This is the same place I worked where I picked up the moniker Steely Eyed Code Slinger, which I used as the name of my blog. I talk more about what that means in this entry: http://dennisferron.blogspot.com/2007/03/new-blog.html)

• Were you inspired by any WTFs that you encountered in your professional programming?

I think I was inspired by as many of my own WTF's as other people's. I used to work with someone who came in to be the software architect for our team. He and I had several differences of opinion. Joel Spolsky talks about architecture astronauts; I'm here to tell you that the opposite can be a bad thing too! Yes, we had an architect that didn't believe in abstraction. Kind of like hiring a cowboy that doesn't ride horses. He criticized my code because I would solve a "2+2" problem by making an inheritance hierarchy seven levels deep in a modular class framework with dynamic loading and package management. Yet he went too far the opposite way - in his code every class lay at the same level, and he never reused anything. (Or... maybe he did! Is cut and paste reuse?) If we had 200 tables in a database, I would make one class that could handle every table. He would make a new class for each of the 200 tables. The key is that they differred only in types; the logic was the same. Although we had many arguments, I think that ultimately I benefitted from knowing him, perhaps more than he did from me. I do not know if he ever adopted any of my viewpoints, but I took his criticism of my methods seriously. He may not have seen things the same way as I did but he did have four times the years of experience as I have, and as I too gained more experience I came to see that proper use of abstraction is a balancing act. If you go too far in optimizing for abstraction, you may pay for it in the loss of simplicity or time.

That does not, however, mean that you can't do badly in every possible facet. My use of classes was narrow and deep (deep inheritance, but few classes at each level). His use of classes was broad and shallow (short inheritance, many classes at a level). The architecture of my calculator takes the worst of both our methods - it uses many more different classes than it should and inherits as deeply as possible. Instead of 1 x Height or Width x 1, a structure that is both deep and broad results a Height x Width rectangle! According to the garbage collector inside the calculator program, instantiating an object of type NinetyNine results in the instantiation of about 2700 other objects.

• What challenges did you face in creating your solution?

Once I started down the path I set out for myself with the initial ideas, it was very difficult to rein in the project and keep it under control so that I could finish on time. At first I put in ideas as soon as I came up with them, but when I reached the halfway point I knew that I needed to turn around and swim back for shore (to wrap up the architecture I started), and sometimes I was afraid I'd gone too far and wouldn't be able to pull it off. I started out with a number of ideas that, based on what I know about the C++ type system and templates, I was pretty sure would work, but there is always the possibility of a devil in the details that keeps things from coming together. There were a couple of sticking points where I was out in uncharted territory. For instance, I decided to implement the calculator state machine using multiple inheritance, with each base class of the calculator corresponding to a different state. The function names would be the same; different implementations of the same name would just come from multiple bases. I thought that by casting the "this" pointer to a different base class, I could choose which one would be called. Like virtual functions in reverse. I cannot remember now why that didn't work - something to do with having a pointer an object under the disguise of one base class not necessarily meaning that the compiler knows how to cast that to another pointer to a different base of the same object. Information gets lost in the translation that you can't get back. So I had this brilliant state machine implementation - only problem was, it didn't actually work, due to a small detail. I was able to solve it, though. Instead of casting the "this" pointer to a new type, I pass the buck to a call-back proxy, which is a template class. This way I can store the type of the base class in the form of the specific type of callback object I create. The callback object then calls a template function on my calculator with the original T type argument it was instantiated with. And inside my template function, I have code that reads T::some_func() where "T" is a class. So if you have a state callback object which was instantiated with type "Cleared", you will get Cleared::some_func() ("T" is replaced by "Cleared", literally) but if it is state "Enter1stNumber" then T will be literally replaced with Enter1stNumber to make Enter1stNumber::some_func(). Thus it selects which base class to call some_func() for. That's an example of the kind of thing I had to solve to pull this off.

• Would you replace calc.exe on Windows with your calculator?

Absolutely. During the testing of my program, I compared my program's results to the results calc.exe produces. In the process I found an obscure bug which calc.exe has but which my program does NOT! Yes, the Windows calculator is buggier than a WTF entry. You heard it from me first.

P.S. Let me know if you'd like a WTF sticker.

Yes I would like one, thanks.

2 comments:

Anonymous said...

I won't pretend I understood more than every third word of that, but I will say that I miss Commander Keen. I've got a Gametap subscription and I can't be the only one petitioning them to add Commander Keen, but no luck so far. Do you know where I can find them, and if I could make them run on my modern computer? :)

Dennis said...

I may have them around here somewhere.

What happened with Commander Keen, in a nutshell, is that the company got bought out but it was left unclear as to who actually owned the Commander Keen franchise - the old owners, or the new ones. In the end, neither could do anything further with Commander Keen, and who has the rights to sell CK to Gametap is questionable too. A shame.