Update
I spent this last week in the Boston area, visiting a customer
site. The work went well, so I'm feeling pretty good about the trip.
While I was there, I had dinner with Norm Megill (of Metamath fame). I'm really glad I
finally got to meet him in person. While we have had a great
correspondence solely over the Internet, there's nothing like really
getting to know a person. I want to make more room in my life for this
kind of thing.
Cross-platform UI design
There's been quite a thread on the recentlog, with contributions by
elanthis,
haruspex,
mathrick,
and davidw.
I'm not claiming that my way is necessarily best, but for the time
being I am building a separate UI for each platform, and trying to
factor as much as possible into platform-independent code.
And so far it seems to be going well. It helps that (at least so far)
my app is not very "UI-heavy", meaning that I don't have lots of
buttons, menus, special widgets, and the like.
There's some duplication, but actually less than I
expected. I deal with duplication all the time when I code. When
Excessive duplication is a sign that the code needs re-factoring, and
I generally find I can do that. On the other hand, if such refactoring
would add more bloat with the new abstraction layer or whatever than
saved by eliminating the duplication, it's maybe not such a great
idea.
I also want to make a distinction between the problems of
coding, which I don't mind, and problems of building and
packaging, which I do. I expect that my lightweight C approach,
without taking on lots of dependencies to libraries, scripting
language implementations, and so on, will generate small, simple
executables (or app bundles or whatever the hell platforms want) that
should be generally pretty easy to build and package.
I've been thinking about these issues a bit, so...
A small rant about building and packaging
It's not hard to get a program written, compiled, and running on your
own development system. It is generally harder to get that program
packaged so that others can do development on it, and so that end
users can get it installed correctly.
The problem gets a lot worse if you want your program to be
cross-platform. Most IDE's and other development tools have a strong
tendency to lock you into a specific platform. For example, I
generally find using XCode pleasant,
but it's not really helpful if you want to deploy those projects to
other platforms. I'm sure the reasons for encouraging lock-in are more
political than technical, but I also think there is a technical
issue at the core.
An analogy comes to mind. Many, many programmers feel that they
shouldn't have to deal with manual memory management. A good
implementation of garbage collection in the runtime avoids the time
investment needed to match up all the mallocs with corresponding
frees, not to mention avoiding the problems that inevitably happen
when the programmer gets it wrong: memory leaks, double-free and
similar bugs, and, in many cases, security holes.
I actually don't feel this way strongly about memory management, at
least for the type of programming I usually do. Typically, I spend so
much time and effort working out the algorithms that I don't really
mind the additional time needed to nail down the memory
management. And, of course, since most of what I do is very
performance-sensitive (2D graphics), I really appreciate the control
over things like memory layout, with its strong implications on cache
efficiency and so on. But if I were doing a different kind of
programming (say, focussed on user interaction), I could totally
understand the feeling. Why spend the time?
And I do feel that way about the build and packaging issues. Why
should I have to spend a significant fraction of the time it takes me
to write a program to write makefiles, config scripts, and so on?
Further, why should I have to do so much more of that work if I want
my program to be cross-platform, even though for the most part the
algorithms should be equally valid on any platform?
To make matters worse, I consider most of the extra packaging work to
be man-made, and quite ephemeral. Twenty years from now, I think there
will still be runtimes with manual memory management, for which
carefully crafted code is still useful (I grant that GC runtimes are
likely to gain in popularity, though). However, I doubt that .pbxproj
directories, MS Visual Studio Solution files, or the like will still
be of much use.
Interpreted languages, or JIT bytecodes for that matter, have the
potential to solve some of these packaging issues, but just being
interpreted is nowhere near sufficient. I want to be able to take a
source directory, press a button, and have ready-to-use packages for
Linux, Win32, and Mac pop out. By "ready-to-use", I mean that the end
user doesn't have to manually install prerequisite packages or
libraries (as is almost invariably the case with, say, Java). In
theory, it shouldn't be hard to do something like this; you just glue
your source directory to a template that contains everything you need,
and tar it up in whatever package format the target system expects.
When it comes down to it, though, even using an interpreted language
doesn't buy you all that much. Cross-compiling C (or, for that matter,
most any currently popular language) into x86 or PPC machine code is a
solved problem. As far as I can see it, the only thing that's really
missing is the will to actually make an infrastructure for
cross-platform package building.