25 February, 2007

Smalltalk: An Application Language

When I started this project, the largest concern I had was that forcing anyone to use object-oriented programming would be extremely limiting or even detrimental to the final application. I've had some very bad experiences with OOP in the past: lots of hidden execution time and gross obfuscation of - and sometimes impossible to follow - code. OOP is a tool, and sometimes an extremely useful one. But, is it one that should be used exclusively?

My theory was that perhaps OOP wasn't the problem, but rather the implementations that I had used (namely C++ and its derivatives). Perhaps Smalltalk, the grand-daddy of OO languages had it right. Fast forward 7 months....

A typical program might begin with a few modules of "super" code - code that can do anything and everything. Then, as the program develops and molds, functionality is extracted and moved into new modules. As this continues, the code becomes easier to read, maintain, and extend. This is a good thing.

One of the many lessons learned (the hard way) by good programmers is knowing when to stop. Eventually a point will be reached when the returns are minimal, and if continued, the code may become so obfuscated that maintaining and extended (and performance) can be severely impacted.

The OO paradigm can have a way of clouding the judgment of otherwise excellent programmers with the allure of "perfect" code. The kind of code where everything is in it's place, only knows about what it needs to know about, all arrows point in one direction, and hides 90% of what all other code shouldn't be concerned with.

Sadly, that kind of code doesn't exist in the real world. It only exists on paper. I have yet to see any significantly large MFC program where the following macros (or similar functions) weren't declared globally:
#define MY_FRAME ((CMyMainFrame*)AfxGetMainWnd())
#define MY_VIEW ((CMyMainView*)MY_FRAME->GetActiveView())
#define MY_DOC ((CMyDoc*)MY_VIEW->GetDocument())
And then, little by little, the document class starts making assumptions about the view, and now someone adding functionality down the road is in a lot of trouble.

Let's just clear the air right now: arrows only pointing one direction are a great starting point, and should be maintained as long as possible, but someday your application needs to ship, bugs need to get fixed, and the end user is never going to care that your rendering engine just happens to know about this one, special level. The end user will care, however, if it can't render the level properly or efficiently.

Surely, hiding data and code is good, though, right? Well, do you want to just trust that the interface library you just plugged into your code base isn't using 10x as much memory as needed, leaking half of it every frame, and slowing down the rest of your application? I didn't think so. And neither do I.

Performance is always a concern - especially in games. And I get sick to my stomach when I purchase a new 2D, turn-based strategy game like Civilization IV at the store and find that it recommends:
  • Pentium 4 CPU with at least 1.8 GHz
  • 512 MB RAM
  • 128 MB graphics card
  • 1.7 GB free hard disk space
Seriously, we're talking about a 2D, turn-based game! Oh, and my laptop beats those specs, and it still runs slow! Maybe Firaxis shouldn't have just trusted some of the 3rd party code they used.

OOP is a tool, and can be very useful. But, it, like Mr. Worldly Wiseman, has a bad habit of "promising" the removal of a great burden from the programmer: having to write real code at the end of the day. For some reason, many programmers still think with that with the proper framework and a double-click, their application will just appear.

Now, the curtain lifts, and in walks Smalltalk...

- "What? What's gonna happen?"
- "Something wonderful!"

Let me state this unequivocally: Smalltalk is an application language! It's about creating applications; it's not about creating code. And there is a world of difference between the two. It's about removing the mundane barriers from the programmer so that he or she can focus on the real-deal, get it done, and move onto the next task.

Smalltalk dispenses with the "arrow" notion. (This is the term I use for those pretty code design diagrams that show object hierarchies and what systems know about, and how all the arrows should only point in one direction). That's left up to the programmer. It's definitely wise to design up front, and write the code as cleanly as possible for as long as possible. But, when it's a time to swing the hammer and make it work, Smalltalk doesn't make a programmer jump through hoops to get the job done.

Nothing is hidden. Nothing. Not even the compiler. Programmers like Ian Bartholomew can create profilers, that allow profiling every line of my application - including the core Smalltalk image - without having to write one extra line of code. Anyone can modify the core libraries to add, improve, or even completely remove functionality if and when it's needed.

Most languages that pride themselves on enabling the programmer to develop applications quickly are founded on the premise that programmers can't be trusted. Visual Basic and C# both jump to mind immediately.

These languages fall terribly short after the first 30 minutes of use. This is usually due to one, simple development truth: time constraints mean that prototypes have a nasty habit of turning into the final application. How often have you had to fix a bug or add a feature in an existing C# application at work, only to open it up and see this?
public partial class Form1 : public Form {
private void button1_Click(...) {
// ...
}
}
The default names given to forms, buttons, and other common controls haven't been updated. The original programmer was just trying out an idea that the boss then liked, but there wasn't time to go back and do it right. So, now you are wasting time trying to work around default code that is already difficult to follow, because you didn't code it to begin with.

Perhaps you even want to take [what should only amount to] 30 seconds and fix the problem by updating the name from button1 to SendButton, but soon give up when you realize that changing the name doesn't update the auto-generated function names, but did move it from a public place to a private place when it was renamed, and there are several places in code where button1 is directly referenced. Another 30 minutes wasted, and now enough code has changed that QA should probably have another round with it. More money wasted.

And that isn't even the worst case scenario. The worst case is when the button name was set originally, but it's text and implementation is now completely different from the original name given (the SendButton is actually the CheckSpelling button). Now it's harder to maintain, and a good programmer will feel morally compelled to fix it.

These are problems that seriously impede the development of applications. Applications that reduce overhead and iteration time, generate revenue, and give the programmer weekends with the family. An "application language" should free the programmer of such tedious, downright ridiculous, responsibilities, without treating the programmer as a miscreant who doesn't know how to properly manage code.

This is what Smalltalk does for me. I only write the code that matters. If I need to rename a class, all references everywhere else in my sources are automatically updated for me. If I change a method name, a browser window opens allowing me to see every caller so that I promptly fix them. These are just two of many, many, many features, all possible thanks to the reflective nature of Smalltalk, due in no small part, to it's object-oriented approach to problem solving.

I have learned to embrace object-oriented programming [in Smalltalk]. When it is implemented well (dare I say "properly?"), this paradigm doesn't just constitute another tool in the toolbox; it is the toolbox, from which everything else stems.

Since I started this endeavor to create a 2D game engine in Smalltalk, I've not once - wait, let me reiterate this - not once have I stopped, and started over again. I'm still working in the same image I started with in late August, 2006. All my designs began with prototypes (*cough* hacks *cough*) inside the main code base, and yet the code is clean. When they worked, it took minutes to reorganize and re-factor the code properly. And when they didn't, it took minutes to strip out bad code, and restore the old.

I've honestly never had more fun programming! Smalltalk has actually made programming more fun than it already was. It allows me to iterate the code so fast! The speed at which I can try an idea, see what's wrong, switch gears, or continue molding until it's right is so ridiculously fast, that it's fun. It's been stated that programming isn't fun. Problem solving and code design are fun. Programming in Smalltalk is just that - all the time. It's fun.

22 February, 2007

Vista Ready!

Well, it's been a while since I updated. A lot of things have gone into the engine, and I'm continually tweaking some things. But some co-workers are starting to gain interest in not only what I'm doing, but Smalltalk as well. So, I decided to compile a To-Go version of what I have so far and bring it in for all to see...

I'm not too excited about Windows Vista, but boy did everything just work out of the box. Instead of "To-Go," it should be called "Just Works!" It ran wonderfully on Windows Vista, both 32- and 64-bit versions. So, there's one worry for the future alleviated. I think I owe that more to Microsoft and their obsessive desire for backwards compatibility, but it's nice to see that Dolphin integrates so well with the OS that entire new versions of the OS don't appear to negatively impact it.

Seeing the little asteroids game running at over 1200 FPS and watching people try it out and have a little fun (it's still a very incomplete demo) was good. In my spare time away from work and the engine I've been typing up a very comprehensive post that will be a very large summary of all my experiences with Smalltalk and Object-Oriented Programming [in Smalltalk]. It will be a kind of "The Good, the Bad, and the Ugly." Stay tuned.