I'm referring, of course, to the long and glorious blogging tradition
of posts which apologize for how long it's been since the last post.
Since I'm perfectly sure nobody was actually on tenterhooks waiting for
me to post something, there's nobody to actually apologize to, but sorry anyway.
API design
It's occurred to me that adding a function to an API based on the
fact that many people want it can still result in making the API as a
whole worse. Adding a new function seems like it should be harmless as
long as you never call it, but it's not. Perhaps this is obvious: a
good API should provide a coherent "mental model" of the system it's
exposing, and adding a new function (even based on popular demand) can
break that mental model, making it harder to get an understanding of
how the API works.
This realization was crystallized for me by thinking about a couple of functions in the ASP.NET framework, one that exists because of implied popular demand, and one that is frequently requested but does not exist today.
The first is Request.Params. This property exists to provide
superficial backward compatibility for people who know classic ASP, and
it was presumably added to classic ASP itself based on popular demand
(I can't imagine that any API designer really thought it was a
good idea, but then again, I feel that way about quite a lot of things
in classic ASP). Request.Params is a collection of name-value pairs
that consists of an aggregation of (1) query-string parameters, (2)
form post data, (3) server variables, and (4) cookies. I think there
are actually even more than these, but those are the four I can
remember. The problem with this API is that, well, people use it. And
their code then gets completely confused if there's a form control that
happens to have the name of a query-string parameter they were
expecting. Yes, I've seen this happen. It's especially nasty because in
ASP.NET you can rely on the framework to handle the form post data, so
you almost never want to get it manually. If it's coming from a cookie
or a server variable things are even worse because most programmers
aren't even aware that these are included in Params, so they have no
hope of debugging such problems.
There's CERTAINLY no case where a value should be treated equally
regardless of whether it's a query-string parameter or a server
variable. If Request.Params didn't exist, nothing would actually be any
harder, because you can always get the data from the place it actually
is, because you always know where it actually is. But because it does exist, naive people use it, and so things break.
(Request.Params also sometimes breaks in the presence of
Server.Transfer, but that's not the reason you shouldn't use it. You
shouldn't use it because it's never what you actually wanted in the
first place.)
The function I was contemplating that doesn't exist is a way to
determine which form control caused a post-back event to happen. This
is a very natural thing to want to know, in fact there have been
situations I've wanted it myself. I never understood why it wasn't
present until someone else asked me how to get this information, and I
asked why they needed it. The ASP.NET "mental model" is that the way
you react to post-back events is by setting a handler on the event
itself, for example button.Click. But because so many programmers'
mental models are based on classic ASP and other technologies, they'd
be inclined to write code like "if (PostBackControl == button) {}",
instead, and break the mental model. While there are valid reasons you
might want the information, writing code like that defeats the clean
and elegant ASP.NET programming model. And unfortunately there's no way
to provide the function for people who have a good reason without also
providing it to the vast majority of people who want it for a bad
reason. I'm forced to conclude that Microsoft made the right tradeoff
by not providing it, although I do think it's a shame.
These Feet are Incorrect, Kate Walker
My absence has been in part due to my (re)discovery of Syberia, an
adventure game (for Windows, no idea if any of the Wine-a-likes can run
it) which puts you in the shoes of Kate Walker, a New York lawyer who
has been sent to the picturesque fictional French village of
Valedilene. Kate's ostensible mission is to obtain the signature of the
elderly Anna Voralberg to enable a routine corporate takeover. However,
the situation rapidly becomes more complex and Kate is left to unravel
the mysteries of the Voralberg family. The story is split over two
games, imaginatively titled "Syberia" and "Syberia II".
To call Syberia an incredible game is an understatement. The graphics
are simply stunning: a combination of pre-rendered (sometimes animated)
scenery, realtime 3D graphics and occasional cuts to pre-rendered
video, which serve to enhance the story without detracting from the
gameplay. The animation of the background scenery exemplifies the level
of attention to detail paid to every aspect of the game: watch out for
birds flying overhead during outdoor scenes, and keep an eye out for
the always spectactular water effects. Between the graphics and the
also wonderful music and sound effects, you're immersed in the world of
the game in a way that even many movies struggle to achieve.
The gameplay is standard adventure-game fare: explore the
environment, collect objects, interact with characters and solve
puzzles. Syberia does an impressive job of providing puzzles that are
challenging but logical, and fit well with the plot of the story. The
common adventure game problem of how to force you to collect all the
objects you're going to need later is deftly dealt with by turning it
into both a key plot point and a running gag. The story is movie-like,
too: at times infuriating, funny, moving, awe-inspiring and
exhilarating. The plot unfolds slowly as puzzles are solved, but
towards the end of the first game the pace begins to pick up.
The high point of the entire story is the end of the first game. After
a particularly heinous puzzle involving a drink-mixing machine, I
strongly suggest making sure you can devote an hour or two to finishing
the game, because from that point on things happen at a breakneck pace.
The creators of the game accomplish a truly amazing feat: a
puzzle-solving adventure game that you finish on an adrenaline high!
I honestly can find absolutely nothing to criticize about the first
game. Unfortunately the sequel, while still very good, did not quite
achieve the same high standard and I found quite a lot of small nits to
pick. The puzzles seemed less logical and required more of the "try
every object you have against every object in the environment" approach
that's the curse of the genre. I noticed several occurrences of another
common genre problem, the "gosh, isn't it lucky I happened to have a
rubber chicken" syndrome, where you have to pick up an object for no
reason at all which will then just happen to be absolutely necessary to
solve a puzzle much later in the game.
Apparently in response to criticism from players, the dialog engine was
changed to avoid having the same conversation twice. At first this
seemed like an improvement but after a while I came to the conclusion
it was actually worse. The conversations with other characters are a
key source of clues on how to solve the puzzles, but if you missed such
a clue, you could never get it back. I suspect that this was part of
the reason the puzzles seemed less logical: where in the first game if
I missed a clue I'd be likely to eventually go back to the same person
who would then tell me the clue again, in II I just had to do without
and brute-force the puzzle.
As before the atmosphere and graphics of the second game were
stunning. A dream-like sequence near the end was particularly
impressive in the way it evoked emotion. I was disappointed by the plot
and the ending, but only because my expectations had been raised so
high by the first game - by any normal standard they were still very
good.
All in all, I wholeheartedly recommend this game to anyone who likes
solving puzzles and unraveling mysterious mysteries. My only caveat is
to reset your expectations after the first game, because if you hold
the second to that impossibly high standard you're likely to be
disappointed.