Sean Middleditch » 2003 » July

Modules vs. Headers

Looking over projects like Mono, D, and some other C++-ish modern language, I’m seeing a recurring theme of using modules vs. headers.

With a module, you put the class declaration and implementation together. This way, you don’t have to worry about keeping header files and implementation files in synch.

Most of these new languages claim to help development by making it easier and speedier, and so on. However, this module approach has a big flaw that makes development a bit less pleasant. That problem is compile times. Long compile times after making changes is a huge problem with development of large applications.

In the separate declaration and implementation model, one only has to recompile code dependent on a class if the declaration changed (the header file has been modified). The code needs to make sure it worked with the new ABI (layout of structure fields and such). This is the best you can get; code must know when the ABI changes, and has to be recompiled to use a new ABI.

The separatation, however, lets you change the implementation of a class without recompiling any other code that uses the class. Which is great, because a good deal of bug fixes and tweaks and the like only require implementation modifications.

If you’re using a language like D or C#, tho, the compiler can no longer differentiate between an implementation and declaration change, since the declaration and implementation are merged. So if you tweak a little value in a method implementation, you now have to recompile any and all code that uses or refers to that class. Compilation times are killer.

There is a solution, tho; one which, unfortunately, doesn’t seem to be in use yet.

There is a “precompiled headers” feature in many C++ compilers. The idea of a precompiled header is to build the ABI definitions from a header once, and all source files that include the header can just let the compiler reuse those preprocessed ABI definitions, versus the compiler having having to redetermine them for each source file.

With the module system, this is already done. Source files include other modules which are already compiled. (Or recompiled when included.)

The solution to the compile time problem is to store these precompiled ABI definitions in the resulting object files. I.e., if mycode.cc includes a precompiled form of myheader.h, put the information from myheader.h in mycode.o. What does this do? Well, when we change myheader.h, it is possible that we didn’t alter the existing ABI; perhaps we only added new features, or just corrected formatting. Or, even if we did alter the ABI, perhaps we altered parts that do not affect mycode.cc.

The same goes with modules. The ABI of the included module is stored in the intermediary compiled form of the dependent module.

Using this, the compiler can check whether the dependent code _really_ need to be recompiled because of the modified included code, or not. If the header change just added a few functions, none of the source files dependent on the header actually need to be recompiled. So why bother? Likewise, if the definition of a method Foo is all that changed, none of the dependent source files that don’t use Foo need to be recompiled.

This kind of compilation dependency checking is really needed for module-based languages like D or C#. Without, I cannot imagine it being enjoyable to work on very large projects consisting of thousands of source files. The only other way to get around the compile time issues is to make excessive use of interfaces and the like. (An approach popular in C++, too.) Using interfaces because it makes the code cleaner is of course a very good idea. Using them because it’s the only way to cut compile time down to under and hour is not so good, tho.

This feature would also be great for C++ systems too, as demonstrated. I can’t count how many times I’ve needed to add a flag to a header file or whatnot, in which only the implementation file and one or two dependent files even use, but all the other dependent files (that don’t use the new flag) are recompiled, even tho they don’t change in the least.

Perhaps this kind of dependency tracking already exists? If anyone knows of any real-life compilers that use it (research projects are of no use to me, I have real work to do after all ~,^ ), I’d be most appreciative to hear of it.

ZMP

Looks like, despite me not announcing ZMP to the MUD community, it’s managed to draw attention. Hopefully it’ll serve its purpose well.

Thinking about it, I can only really see two weaknesses with ZMP, and both are easily worked around. The first weakness is that markup style commands, like how MXP offers HTML-ish tags, must be done using two RPC calls: a “start” command (like start-link), and then an end command after the text.

The second weakness is that there isn’t a good way of handling return values from commands. Each command basically needs special return commands to make it workable, which is a little ugly. Ah well.

Web

Had some fun reworking the AweMUD website. I originally planned on going in and using just using CSS to style the page, and make it nicely accessible and all that jazz.

Problem is, I couldn’t quite get things working the way I want doing that. Reading over every CSS document I could find, and drawing on my (ego aside) extensive web development knowledge, I couldn’t figure out how to get CSS to manage the layout the way I wanted it. The problem being, I need absolute positioning of certain elements, and the positions of some elements rely on the positions of others. There doesn’t seem to be a way in CSS to do that, unless you nest them, which, in my opinion, is worse than just using a table or three for layout. (Which is what I did.)

Some day when I have the time and inclination I’ll play with CSS layout on the site some more. I know I’ll have to use some “tricks” to get it working, which I wanted to avoid for now.

Games

Bought the Warcraft3 expansion to play with my friend this weekend. Of course, wonder of wonders, WineX decided to not work, yet again. That app is honestly the least reliable tool I have ever used. Yes, yes, I know trying to emulate the Windows API and environment is anything but easy, but still; when it’s that flaky, even on a game they advertise it supports (neither stock War3 nor the expansion worked, altho stock War3 did in Debian), fails to run by spitting out a cryptic error message on the terminal output (and I run the game from a GNOME menu), and their touted Point2Play tool also spits out cryptic error messages on basic operation… well, why in the nine hells would I want to give them more money for updates?

I don’t mind paying for software (people’s time isn’t free, no matter what certain zealots claim), and I don’t even mind if that software isn’t Open Source… but I do mind, a lot, when I pay for software that can’t even perform its advertised function.

Anyways, my friend still wanted to play Warcraft, and I did rather want to play the expansion I bought, so I decided to abuse the Windows box I had borrowed (for porting), to install War3 on. And, of course, WindowsXP failed to perform its advertised function (that being “operating” the system), and I couldn’t even get Warcraft installed there.

Looking at this and many other past experiences, I really think consoles are the only bright future of gaming. Linux is, well, just not there yet, and the way application installation is such a pain, and many of the core OS developers still think it’s a good thing to make it hard to use my hardware with the OS (like, say, the only video drivers that work for games: nVidia), I don’t think it’s going to get there any time soon. Even Windows, the “gaming platform”, is a complete PITA when it comes to games (driver upgrades, patches, incompatibilities, install failures, crashing, etc.).

I’ve not been much into consoles before because the kinds of games I usually enjoy don’t work well on a console. A game like Neverwinter Nights, for example (which is on the low-end of my good games list), couldn’t work well on a console because of the large amount of state needed for saved games, the interface (gamepads and thumb-joysticks just wouldn’t work), and so on don’t work well on a game console.

The newer console designs around may be fixing this, tho. Newer, varied input devices are possible, hard-drives will be standard (lets hope to $DEITY they aren’t abused to allow patches; a strength of consoles is the quality of development and lack of need for patches), networking will be standard, and so on - a game like Baldur’s Gate or whatnot could be very feasible on a console, along with the games like Zelda or Smash Brothers or so on which aren’t that fun on a computer.

English

English sucks. A lot. As a MUD coder, I have to deal with it more ways than I ever wanted. Who here knows all the rules regarding the proper times to use the definite and indefinite articles, hmm? Yet, even a slight misuse thereof is quite noticable and distracting.

Other MUDs seem to deal with this problem in less than ideal ways. Some simply remove all use of articles (similar to the current lazy approach in AweMUD, which I’m trying to fix). Others always use the indefinite article, phrase their sentances that way, and ignore the fact it sounds somewhat funny. A few make builders write in all the different ways the item can be named.

The approach I’m planning for AweMUD is based on the later idea. Due to my need for sane and proper use of colour, it’s important that the core part of the name be separate from the articles and such. (i.e., I want to print “the table” versus “the table“, so it’s clear to the player which part of the phrase is the actual name the MUD recognizes - am I spoiled by GNOME’s usability standards or what?) So, each object/npc/etc. will have a name, and then a name type. The name would be, for example, “table” or “wolf”. Name type would indicate whether the name is proper, unique, plural, vowel, or normal. Proper names (like “Sean”) never have articles. Unique names (like the “moon”) always use “the” as the article. (Unique names will, in this model, also include proper nouns that require an article, like the “King of England”.) Plural names are for things like “pants” or “glasses”, and vowel names for things like “adventurer” or “hourglass”.

It should be possible to put in some basic automatic rules, as well. Anything capitalized will be proper by default. Anything ending in “es” or a consonant and then “s” could be plural by default. Rooms and exit names will always be unique by default (exit names are unique in each room, and rooms are places, and places often require the “the” article). Many many cases will still require the builder to specify the name type tho.

Man I hate English. ;-)

Software Packages

For all of a week, I had an interest in the Autopackage project. As many people are aware, RPMs and such just don’t cut it when it comes to end-user software installation. Autopackage looked promising, but I don’t think they are heading in quite the right direction.

So, I started thinking about my own packaging system, were I to write one, and how it would work. First, I came up with some goals:

  • Easy to use with a graphical installer
  • Capable of dealing with legal issues like EULA agreements for commercial software
  • Adequate dependency tracking
  • Easy to manage components

That last requirement is the one that makes my design so different from current packaging formats. Let me explain it a bit. Take a piece of software like Mozilla. Mozilla has several different components (browser, mailer, composer, chat) that can be optionally installed. In dpkg and rpm based systems, this is usually done by making one or more base/common packages, and then several component packages. It works, but it’s not pretty; users have to deal with a bloated package namespace, complex or technical package names, and so on.

My solution would be to, basically, just offer sub-packages. This could even be implemented ontop of RPM, if one wanted, by using RPMs (or dpkgs) as the sub-package type. The user would open the Mozilla package, select the components she wants, and hit the Install/Remove/Update/whatever button.

The Mozilla package would also have several “hidden” sub-packages, which would be the libraries and common data stuff all the components need. Those components would not be shown on the normal user interface, and could not be removed; if Mozilla is installed, those packages are just simply there.

The scheme could be taken a step further by allowing these group/super packages to point to URLs that have RSS feeds for package updates. The system updater could look at all installed packages, read their RSS feeds, check against the GPG key fingerprint for the package to make sure it’s a feed, and go from there. All the management headaches of things like APT source management go away.

Dependency tracking would also hopefully be simplified a bit. One thing that will help a metric shitload would be to simply write decent packaging guidelines, a la Debian. Libraries would have a common way of being named and packaged, for example, so they Just Work(tm). Altho libraries in general are a pain, and to make them as easy for an end user as they should be, they probably need to be rethought out on a much lower level…

It’s important to note that these super packages would only be for end-user applications. Core system packages are much better suited to RPMs or dpkgs. Or perhaps a simplified package format that doesn’t have all the ugly hacks and misfeatures RPM and dpkg have included to deal with user apps. ;-)

West and Seattle

I’ll be in Seattle the first week of August. Any of you want to get a bite to eat or some coffee or something, let me know.

Doh, wait, I don’t know any of you. Dangit. ;-)

Beattles

I never was much of a Beattles fan. Lately, tho, I’m starting to become one. I don’t know what it is that now I like the music when before it irritated me, but oh well. I’ve had “Back in the USSR” and “Rocky Racoon” stuck in my head all weekend.

Pirates

Pirtes of the Carribean rules. A lot. Excellent movie. Seriously. ^,^

Comedy, action, romance, real plot, character development, good special effects, and likable characters make it one of the best films I’ve seen in a long time. Probably going to end up seeing again in theatres. ^,^

Hopefully the second time there won’t be a tear in the screen, and I won’t be stuck next to two big noisy unintelligent constantly eating food in plastic wrappers type people, either. :P

AweMUD

As always, too much to be done.

Current big tasks I want to get done including more cleanups/stabilizations to the network/input/telent layer (it’s one big ugly mess, altho I’m slowly shaping it into something lovable), to get affects in (i.e., for magick), and template stuff I’ve been needing to do forever now.

Template stuff is the most boring to work on, I think, but also the most exacerbating… probably why I haven’t done it yet.

After several attempts at doing it, I’ve realized C++ just doesn’t offer the OO features needed to do it the _proper_ way. And, since I’m not going to be switching to Smalltalk or Objective-C anytime soon in AweMUD, I’ll just have to do it the less than ideal way. Namely, a custom template type for Objects and NPCs, and modify the base Entity type to have more virtual methods; including virtualizing a few I’d much much rather keep as nice fast inline methods. (Very commonly called things like get_name() and such.)

Angry Pixels

More and more documentation work. But this is good. I _like_ documenting things out first. Too bad I don’t do that in more of my open source projects, hmm? ;-)

ZMP

The Zenith MUD Protocol draft is now officially available. Still just a draft, but it’s out there.

I’ve yet to have any negative feedback on it (except for the original name, whose acronym was SMP), so I’m quite hopeful the protocol will be popular.

Game Design

I’ve been put in charge of pulling together a gameplay spec and final storyboard for the Angry Pixels game project. That is, I’m like the ditor; I don’t actually come up with the final concepts, just help everyone get it pulled together. This is good, because we rather hadn’t bothered previously with this, and we rather needed to.

Hopefully I’ll do a less lame job on this than I have for them otherwise. ^^;

UNIX Philosophy

Most everyone here should be familiar with Programs do one thing, and do it well. I think I realized why so many apps fail on that these days. In my AweMUD work, I had started looking at some of the needed features I hadn’t implemented yet. One such feature was a reporting DB; for things like bug reporting, player abuse reporting, etc.

I spent a couple hours writing some DB interfaces; it ran off a simple text file, with a few methods for adding, querying, and removing entries. Eventually I realized the flat text file just really sucked for that work.

So next I do the smart thing, and start looking for some decent DB libraries. I wanted something BSD or MIT licensed. I found SQLite, which I’d looked at before, and thought it the perfect fit. Another hour later, I had a basic reporting system. The file storage was excellent, but the features rather lacked. It was a pretty piss poor bug/issue tracker. As I was adding the mail feature (to notify admins of new entries), I realized it would be pretty easy to just write a Perl script that took mail sent to a particular address, and insert bug/issue reports into a real issue tracker. And if I could do that, AweMUD didn’t need it’s own built in tracker.

I see where I went wrong. AweMUD is a MUD server. That’s what it does, that’s all it should do, and it will do it well. The problem I had, and that many others might be having, is that I thought that bug/abuse/etc. tracking was one of the things a MUD server has to do. If players can’t report stuff from in the game, they might not bother at all. They need to be able to report stuff, but it isn’t the MUD server that has to do all the tracking.

One just needs to remember features like that can, and should be, implemented externally. Let the tools work together. The only downside I see is that a complete AweMUD installation may take a little more work now, if you want the reporting abilities to work. Ah well.