How The Game Is Played

http://blogs.sun.com/gameguy/date/20071219 Wednesday December 19, 2007

The piano has been drinking...

So, recently someone on my list pointed me to a blog by an amature game developer who wrote his game in Java.  (http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html)

To sum it up, his code base is ungainly and unmanageable and all its all the fault of the language and the tools.

This reminds me of nothing more then the Tom Waits song "The Piano Has Been Drinking."  I'll end this blog with the lyrics.  In the mean-time, lets take a closer look at some of the things he claims he's learned from this experience:

"I happen to hold a hard-won minority opinion about code bases. In particular I believe, quite staunchly I might add, that the worst thing that can happen to a code base is size."

Well there is nothing terribly new or exciting here, except that he apparently hasn't caught up from the 80s when IBM thought number of lines of code written per day was a good measure of programmer productivity.  Since then the industry has become very aware that well written code is often also the smallest and that 10 good lines of code may do the same thing that 1000 liens of crap code does, and do it better and faster as well as in a more maintainable fashion.

Today, this is part of what we call "elegance" and "good design."

"People in the industry are very excited about various ideas that nominally help you deal with large code bases, such as IDEs that can manipulate code as "algebraic structures", and search indexes, and so on. These people tend to view code bases much the way construction workers view dirt: they want great big machines that can move the dirt this way and that."

I don't know what industry people he knows, but I don't think of my code as dirt.  I;m not sure I wouldn't think of his code as dirt, based on the picture that emerges from his complaints, but thats another story.

Using his analogy though, you can't build a house in Massachusetts without moving 4 feet deep of dirt from the construction site to elsewhere.  We call this a "foundation" and a "basement."  Well, maybe he lives in Cali where they don't have basements.  My point though is that this work is unavoidable.  Its not that you want to move all that or enjoy doing it-- its that you cannot build the house any way else.

Similarly, with the genuine complexity of today's mainstream games, which rival or beat the complexity of any other software today, you are going to have a big code base.  Its inevitable to do the job.  and that means you had better have tools to manage it.  The fact that the tools are so much better today then they were when I started game programming in C is a cause for some genuine excitement, yes.

But you still have to know how to use them.  To continue his construction analogy a bit further, I love my table saw at home.  It makes projects much easier.  But I don't let anyone touch it who doesn't know how to use it properly because it is also a very efficient finger removal device.

I have a feeling he's experienced the latter with his software tools.  Especially after reading thsi next assertion.

"It turns out you have to have something bad happen to you before you can hold my minority opinion. The bad thing that happened to me is that I wrote a beautiful game in an ugly language, and the result was lovely on the outside and quite horrific internally."

I have seen beautiful assembly.  I have seen piss ugly PERL.  The biggest difference in whether code is one or the other was never the tool, or the language, but the preperation of the programmer.  Hackers produce hack work.  Designers design clean code.  Its really that simple.  A proper design phase makes all the difference.  That, and the willingness to throw away your first cut and start again when the implementation drifts too far from the original design.

In the book "Effective Java"  Josh Bloch suggests you design with Interfaces first and not write a line of Class code until your interfaces are right and compile against each other.  This is not a new idea.  Its just another way of saying "design before you implement" but Java makes it easy to see.  Before Java though I did Modula2 and C/C++.  In Modula 2 I wrote all my DEF files first.  In C/C++, I wrote .h files first.

As the article continues he shows a definite trend towards "magical thinking" in how he approaches his tools.  He seems to expect his tools to do the thinking for him.  Given that, I am not surprised he is disappointed.

"'The problem with Refactoring as applied to languages like Java, and this is really quite central to my thesis today, is that Refactoring makes the code base larger. I'd estimate that fewer than 5% of the standard refactorings supported by IDEs today make the code smaller."

To my mind he has completely missed the point of a refactoring tool.  A refactoring tool does not magically make your code smaller.  What it does is give you the flexibility to fix design mistakes later in the game.  It *may* make your code smaller IF you use it to factor out common code that you didn't realize was common in your design phase.

But this is a thinking operation, you don't just press a "refactor" button and expect your code to magically be better.  Such general automated code correctness and translation has been searched for by academics for decades now to no avail.

Programming is an art.  And it is a poor artist who blames his paintbrush.

It is ironic that his next complaint is...

"This brings us to the second obviously-bad thing that can go wrong with code bases: copy and paste. "

If your not going to refactor at all, then you *will* end up doing a fair bit of cutting and pasting by the time you are through.  Here I semi-agree with him.  If you find yourself copying lines of code from one part of your program to another, then its probably time to think about refactoring something.

This next one is interesting....

"The core problem is duplication, and unfortunately there are patterns of duplication that cannot be eradicated from Java code. These duplication patterns are everywhere in Java; they're ubiquitous, but Java programmers quickly lose the ability to see them at all."

Don't you love it when one person speaks for a whole community?  Don't you love oit even more when they claim to be an outsider to that community?  He claims that "other Java coders can't see this" but he gives no examples that *he* sees.

If he did maybe we could discuss whether its really an inherent weakness in he tool or rather the way he is using it.

His next poke is at a straw man.

"It's obvious now, though, isn't it? A design pattern isn't a feature. "

He's absolutely right  Of course he's as right in any language as he is in Java since "patterns" properly specified are not language specific.

The thing is, he again misses the entire point of the tool.  Patterns were never intended to be features.  Programmers who proudly proclaim how many patterns they used in their code miss the entire point.  Patterns are simply a common language with which to describe common code constructs.  They are a communication tool, and a recognition that certain constructs tend to repeat themselves in code.  Nothing more.

"Bigger is just something you have to live with in Java. Growth is a fact of life. "

Another empty, unsupported assertion.  Seems maybe thats one of his personal design patterns?  ;)

"I'll give you the capsule synopsis, the one-sentence summary of the learnings I had from the Bad Thing that happened to me while writing my game in Java: if you begin with the assumption that you need to shrink your code base, you will eventually be forced to conclude that you cannot continue to use Java. Conversely, if you begin with the assumption that you must use Java, then you will eventually be forced to conclude that you will have millions of lines of code."

Do I really need to say it?  Yes, its a repetition of his unsupported assertion pattern.

It's also nonsense.  Java's late binding combined with strong type checking makes it about the best language for proper data structure design and re-use I've ever used.  C++ came close but ultimately its lack of late binding led to the "fragile base class" problem and reusability of code didn't happen.

Well written and reusable modules simplify any complex problem by breaking it down into the application of already solved sub-problems.  In fact, I'll argue this is really what he is looking for and why, in the end, he gravitates to scripting languages.  The real difference is that, in scripting languages, most of the design of the reusable modules has been done for you by the scripting environment whereas in a full programming language like Java, you need to look at it and think about it yourself.

But to use his own argument style through broad analogy, thinking a scripting language all by itself reduces over-all code complexity is like thinking that shoving all your crap under your bed counts as cleaning it.  This isn't to say they can't be valuable tools.  But again, no tool is going to magically solve these programs.  No program is going to write your program for you.  Thats why we get paid to design and deliver software.

"But you should take anything a "Java programmer" tells you with a hefty grain of salt, because an "X programmer", for any value of X, is a weak player. You have to cross-train to be a decent athlete these days. Programmers need to be fluent in multiple languages with fundamentally different "character" before they can make truly informed design decisions."

Well here I semi-agree with him again, but hes ultimately still got his left shoe on his right foot.

I don't hire "programmers."  Ever.  I hire software engineers.   And the engineering is the big thing that has been lacking in his project.  Good software engineers don't train in "languages."  They train in how computers work. Underneath.  They train in the arts and techniques of good code design.  They can see the big pictures of how things like structured coding, data structures and object oriented coding all inter-relate.

And they don't get hooked on thinking that easy answers exist in the tools.

A language is just a tool like any other.  Learning new tools is a good thing.  But understanding their proper use takes more fundamental skills.  Ask a carpenter, a real one, how much of her work is pushing the button on the tool and how much is understanding the characteristics of the wood she is working on.

His whole IDE ramble I won't quote, because thats all it is.  Honestly, I can't really follow what hes trying to say.  Modern IDEs conatin many tools certainly.  Most of which are time savers and can lead to better code when used in the right way at the right time and place.  See my description of the table saw above.

In the end, as I mentioned above,  he decides he wants a scripting language...

"That narrows the field from 200+ languages down to maybe three or four: JRuby, Groovy, Rhino (JavaScript), and maybe Jython if it comes out of its coma.

Each of these languages (as does Perl 6) provides mechanisms that would permit compression of a well-engineered 500,000-line Java code base by 50% to 75%. Exactly where the dart lands (between 50% and 75%) remains to be seen, but I'm going to try it myself."

Lets ignore the "well engineered" claim for a moment and focus on the rest of the claim.

Scripting languages are "more expressive" in the sense that fewer lines of code can accomplish more work.  Note I said more, not necessarily the right work.  That depends on how closely the creator of the underlying scripting environment had your particular application in mind when they designed it.  This is the nature and purpose of scripting languages-- to address niches be they First Person Shooters in Unreal Script or web sites in Ruby on Rails.

Scripting languages are also typically loosely to non typed.  This allows for a coding freedom  and somewhat smaller code size at the cost of removing the consideration of important compatibility issues from the design time of the code.  This cna be a time saver when writing small bits of well understood code, but its a nightmare when you want to start writing modular and reusable code.

It also means more bugs.

One of the great things about Java that most who try it experience though few really think about is that Java is designed as a "fail-early" language.  Some errors that you could make in C and C++ won't even compile in Java (eg "dead code", uninitialized variables. wild pointers.)  Others are caught as soon as they occur at run-time (eg array over-flow and under-flow.)  This results in *provably working* code far faster then previous languages and a lot of it is thanks to Java's particular blend of strong
 typing mechanisms.

I've written quite a lot of C, C++, Modula2, Java and PERL in my day.  And yes, PERL code is quick to make run, and *very* hard to debug.  C is a pain to get running and also hard to debug.  Java is quick to get up and running, and well designed Java can be near bug free on the first pass.

So I wish him luck with scripting languages.  He's going to get so-far, and then fall over because his code will require complexity they can't wrangle.  At which point he'll be forced to go down back underneath and write more modules for the language in the lower level its supported by, be that Java, C or whatever.  Maybe this will actually get him to think about his modules up front, but somehow I doubt it.

He missed the most useful tool he coudl have used on this project.  I recommend it to anyone coming new to Java and software engineering.  And thats a book.

Josh Bloch's Effective Java

Had he read it and grokked it before he started, I strongly suspect he would not be in the mess he's in today.

Which brings me back around to the title of this blog.  I leave you with this apropos song:

The piano has been drinking
my necktie is asleep
and the combo went back to New York
the jukebox has to take a leak
and the carpet needs a haircut
and the spotlight looks like a prison break
cause the telephone's out of cigarettes
and the balcony's on the make
and the piano has been drinking
the piano has been drinking...

and the menus are all freezing
and the lightman's blind in one eye
and he can't see out of the other
and the piano-tuner's got a hearing aid
and he showed up with his mother
and the piano has been drinking
the piano has been drinking

cause the bouncer is a Sumo wrestler
cream puff casper milk toast
and the owner is a mental midget
with the I.Q. of a fencepost
cause the piano has been drinking
the piano has been drinking...

and you can't find your waitress
with a Geiger counter
And she hates you and your friends
and you just can't get served
without her
and the box-office is drooling
and the bar stools are on fire
and the newspapers were fooling
and the ash-trays have retired
the piano has been drinking
the piano has been drinking
not me, not me, not me, not me, not me










Powered by ScribeFire.

Comments:

You are one of Yegge's old navy buddies and you are just ragging on him right?

Posted by dave on December 20, 2007 at 01:52 AM EST #

Never met the man.

But when one rants in public one invites response. As one who himself is wont to rant in public this is something I know well and accept as "part of the game."

Posted by 192.18.128.5 on December 20, 2007 at 11:59 AM EST #

Such valid points. Only wish people would listen to what you say here!

Posted by Remi on December 21, 2007 at 12:18 AM EST #

Post a Comment:
Comments are closed for this entry.