diary at Telent Netowrks

Because, I think, for a language to be considered truly general#

Tue, 03 Jun 2003 03:52:46 +0000

Because, I think, for a language to be considered truly general purpose it must be good for evil baling-wire-and-duct-tape kludges as well as for beautiful elegant robust well-engineered solutions, I have (minimal) pleasure in showing you asdf-install.lisp (temporary location).

"Not work-viewable", as they say

Note in passing: the cclan >(foo) and :(download ...) tokens are both deprecated. If you follow these rules, you can use the new :(package ...) syntax instead.

  1. The CLiki page name must be the asdf system name, after downcasing

  2. The package link is either :(package "foo.tar.gz") for a package in cCLan, or :(package "full://url/to/host/foo.tar.gz") for a package somewhere else

  3. There is only one package link per page

  4. It must point to a gzipped tarball of an ASDF System or close approximation

  5. The package must be Free according to DFSG

Not only was yesterday's entry almost criminally dull, rereading shows it not#

Wed, 04 Jun 2003 00:24:46 +0000

Not only was yesterday's entry almost criminally dull, rereading shows it not to have been terribly clear either.

The project here is an automatic download/install tool for SBCL, along the lines of CPAN.pm. How it works: it looks up cliki pages with the same name as the package you tell it you want, and it downloads the url that the :(package ...) link on that page points at. Yes, all the stuff about deprecated tokens was talking about CLiki markup syntax. If the url pointed to is relative, it gets merged against the URL for the cclan dispatcher, so you eventually end up downloading from some cclan site that you chose earlier.

CL is actually the third language it's written in: it started life as a shell script, then as all shell scripts over twenty lines tend to do, turned into a Perl script. After a couple of hours screwing around with pathnames in Perl, I decided that CL would have been the better choice after all.

Yesterday, in accordance with the "small tools that do one thing each" Unix Philosophy, I was executing wget in a subshell to actually get the file. Due to the way that cliki and cclan are arranged, this can potentially involve several redirects. Today I determined that to additionally get the PGP signature file for the package I'd have to grep the standard output of wget -S looking for a line (actually, the last of n lines) matching Location, my "brittle interfaces" meter pegged, and so I decided it'd be quicker to write a small HTTP client.

Today's version of asdf-install.lisp is in the same place as yesterday's (see? I told you it was a temporary location) and does approximately as little as yesterday's, but in a marginally more sane way. Seems to cope with proxies (tested using the NTL proxy system) but doesn't do any lind of proxy authentication yet. Nor FTP, which limits it to cCLan nodes that are available by HTTP.

A word of warning: this represents a software engineering advance on yesterday's code. It is still not, in absolute terms, anything you should even briefly entertain the idea of reusing for other purposes: there are some much better designed network client libraries out there. The sole purpose of this one is to provide the minimal code necessary that the user can easily download and install one of them.

OK, it now also checks PGP signatures, which I think makes it#

Wed, 04 Jun 2003 04:19:05 +0000

OK, it now also checks PGP signatures, which I think makes it sufficiently complicated that any change could just as easily break it as improve it, so it's time to start using CVS.

Caption competition#

Sun, 08 Jun 2003 21:18:47 +0000

Caption competition

http://www.catb.org/~esr/graphics/raymond007-5.jpg

    1. 896 - fetchmailrc syntax
       shoot tuxedo.org proto anarchist target advocacy there is
      foot here fetchall

  1. "Eric's default emacs binding for leak-microsoft-memo proves more unwieldy than he was expecting"

For a long time I've been meaning to put the SBCL User Manual on the web#

Mon, 16 Jun 2003 20:36:52 +0000

For a long time I've been meaning to put the SBCL User Manual on the web somewhere that Google can find it. So, I was quite happy to see that Xach has done it already.

It's fashionable, I know, when speaking to an RDBMS, to write or use#

Sat, 21 Jun 2003 15:24:20 +0000

It's fashionable, I know, when speaking to an RDBMS, to write or use an interface that presents an object-oriented view of the database, typically by mapping table rows onto objects. I make the following observations mostly off the top of my head.

  1. Every object 'get' typically involves a select which fetches all columns, even if you were only going to use one of two of them. Slightly inefficient.

  2. It's very tempting to do something like
    (remove-if-not #'interesting-p (all-instances 'emp))
    
    to get a list of objects that satisfy some arbitrary interesting-p criterion. Horrendously inefficient. OK, so don't do that; encode your selection criterion as SQL.

  3. Following a chain of object references involves multiple database fetches (if done the simple way) or some probably quite complex stuff to work out when a join will save time.

         (emp-name (emp-manager *me*)) 

  4. Unless every field access does a new row fetch (or you have some kind of database driver that can give you unsolicited notifications when data changes behind your back) your object is always potentially slightly out of date w.r.t. the actual database contents.

  5. Unless you keep tabs on the objects you create, it's possible to have two non-EQ objects that refer to the same row. (Insofar as there's any concept of identity in a relational database anyway, but assume there's some kind of unique constraint on the table). This is fine for read-only data, but can be icky when updating.

  6. Links between table rows are essentially bi-directional - it's as easy to find the manager given an employee as it is to find the employees given the manager. The natural OO model gives each employee a list to his manager, or each manager a set (a list, vector, whatever) of employees. Sure, you could do both. See preceding point, though: you'd better be sure that you know whether (member me (car (manager-employees (emp-manager me)))) or not.

  7. If that was a bit weird, modelling inheritance is weirder.

In short, it's slower than doing raw relational lookups, and has trouble with object identity leading to possible data consistency issues. So what's the actual advantage of making the table rows look like objects? Presumably the theory is that table rows correspond to domain objects, and therefore we should be able to hang methods on them that do useful operations. It's my conjecture, based on looking at an UncommonSQL application I have here in front of me (bits of which are anything up to three or four years old), that that's not in general true: domain objects are bigger. In relational terms, there's a 1:n relation between an invoice and an invoiceline, but in domain terms we say that the lines are part of the invoice. This is probably why 'invoiceline' is such a poor name: if it was a useful domain concept, the domain experts would have a name for it.

So, for a lot of less, uh, "pivotal" (sorry) tables, the only methods they end up with are boring little things like "print this line as HTML, or PDF, or something". Even "delete this line", which you might suggest, is actually "remove this line from the invoice". And then you find (or at least, I found) that given n different circumstances where you want to print an object, in at least n-2 cases you want to print different columns, or you're printing HTML and want the item description to be a link to some place, or there is some important reason that you need to embed a hunk of javascript into the middle of the output. So perhaps you introduce a (print-instance o :short) and (print-instance o :full), and then suddenly you find there are a bunch of other cases where you also need (print-instance o :link-email-address) or (print-instance o :two-digit-year), and each of these is only ever called once. And if you put all the methods into the same file so you stand a chance of finding out what each of them does and reusing them for new output reports instead of creating new ones, then you find that you don't dare change any of them when your format requirement changes, because you don't know what other page or reports are using it. So, wouldn't it make more sense to define the formatting at the point where you need it?

In other news, I'm attempting to train myself to use C-delete to delete words, because in psgml mode C-M-k doesn't.