This site has moved

June 26, 2006

If you're still reading my feed here (and I see that a few of you are), you might want to come take a look at CeaMuS Developer The new weblog for CeaMuS.  While not as feature-rich as WordPress, it is kept current with the latest news on CeaMuS, and it does showcase the capabilities of the software quite nicely.

CeaMuS Update

April 17, 2006

CeaMuS has a new release pending that's fairly exciting for me, and hopefully for you too, as my hopefully loyal readers (both of you).

The next version fixes a host of bugs (<a href="http://www.ceamus.com/cgi-bin/trac/rptview?rn=4">Open Tickets</a>) and adds an important new feature. Ticket #7, while not officially closed just at this moment, is actually resolved in code. Two tickets, #12 and #13, need to be addressed before a final release.

The weblog management features of ticket #7 are particularly interesting to me. For one thing, they probably mean that this weblog will be moving to the CeaMuS site. After all, it's very hard to justify maintaining a second site when my own site will be perfectly capable of maintaining this weblog, and it will also be easier for my customers to access.

Multi-part Primary Key

March 31, 2006

I've gotten myself into an interesting situation right now.  I have this app with a large installed base.  It was written in Paradox, and makes use of multi-field primary keys throughout.  We've just moved it to SQL Server, and we'd love to use Object Builder to generate active record objects.

The problem that I'm running into is that I'm not enough of an XSL wizard to manage multi-part primary keys.   So I'm asking any XSL wizards out there who are familiar with Object Builder to see if they can take a stab at this problem.  There's no common element among these fields that can be used as a clue, other than their presence in the primary key.

Hidden Shadows

March 31, 2006

Over the last week I've run into this crazy problem in two separate applications, and it's directly related to Object Builder. More specifically, it's related to how I was using Object Builder. I realized that I was declaring some common elements in each object, such as the SQDataSet qry member that each active record object gets.

Even a first year computer science student can tell you why that's bad: common elements should be declared in the common ancestor class, so that if you even need to change how that item is handled it's fairly trivial. I decided to put the qry member into the ancestor class, initialize it with a database connection there and recompiled the app. Then my apps crashed with an inexplicable "Database Not Set" error.

The trick is that I didn't have the good sense to update my templates and regenerate my objects. The old Active Record objects all had a member called qry declared in the active record class. So when I was initializing the dborecord::qry member in the dborecord constructor, the dbo_author::qry member didn't get a connection to the database, since it's a separate object from the dborecord::qry. It's called a shadow parameter, and it's a classic mistake.
The proper solution is to redesign the templates so that there's no shadow parameter and regenerate the objects. It's easy to do, but also easy to forget. It all took about two hours to work out the first time, and another half hour to figure out the second time.

If you find yourself in a similar situation, take heart that you aren't alone, and check for shadows.

This post by Tim Almond on the Joel on Software forum reminded me that there are some serious perception issues related to Active Record that need to be corrected in the public eye.

For instance, ActiveRecord. It is interesting, but in the end, nowhere I’ve worked has simply wanted a simple “update” for their databases. They typically want some audit information stored.

He’s right, of course, you almost always want to do something more than just store the raw data of a record. You may wish to track who made the updates and when. You may wish to encode some of the information, or verify its validity against some other source. Sadly, Tim goes on to say this:

Nothing out of the box will deliver this, so you are then into thinking about either coding your needs on each instance, or modifying the base code of the framework to run with your default behaviour.

I don’t know which framework he’s talking about, and it doesn’t really matter from the perspective of Tim being wrong, at least about Active Record in the general sense. It may be perfectly true in instances of specific frameworks.

In a generic Active Record solution such as Object Builder the obvious solution is to derive the Active Record objects from a base object that has the behavior you’re interested in. That’s exactly what I’ve done in every instance of Object Builder that I’ve used. On some occasions I’ve gone so far as to have two different, but similar base classes that I derive from. For instance I may need to track the last modification for a significant percentage of my tables, but it could be entirely irrelevant for others. So for tables with fields for this audit table I derive from the base class that tracks this information, and for the other tables I use a different class (an xsl:choose statement based on the presence of a field handles the matter).

For behavior that’s specific to a single table, a custom class is written that descends from that table’s Active Record object. Let’s say that I need to encode user passwords before saving the user records to the database. In my descendent class, in the save operation, I check the password to see if it’s already encrypted using the OS crypt function. Typically an encrypted password will be of a specific length, and will begin with something like $1$. If I don’t find those criteria met, I run the encryption on the presented password, then call the inherited Save method. This, of course, assumes that I’ve done something in my interface code to prevent the user from entering a password that matches these criteria.

I’ll be the first to admit that Active Record isn’t the perfect design solution to every problem. There are certainly areas where it isn’t appropriate. But Active Record is a good deal more flexible than a lot of people give it credit for.

Object Builder

February 10, 2006

There are two items on the Object Builder front worth mentioning. The first is that I have presented it to outsiders for the first time. The second is the bold new success that I have had with it, generating nearly the entirety of a web application using only Object Builder. The speed at which this application came together was truely astounding, and convinces me even more that this is powerful technology.

On the first point, I presented this technology to my local Linux User’s Group last night. I didn’t have any slick videos like the Ruby On Rails people have, just a series of slides and some example files. There were several people though who were interested and managed to ask intelligent questions, which I found heartening. It helped that the week before they had seen a presentation about Ruby On Rails, so their brains were ready for the concept.

The downside is that my laptop and the projector weren’t on speaking terms. That means that I couldn’t show off the slick new app that I’d built. That’s just as well, because when I got home and tried to investigate I discovered that one of the pieces of technology that I’d depended on, that worked magnificantly on my development machine, was a no-go on my laptop. To be blunt, the PDO module for PHP doesn’t install correctly when built from source. This whole experience shows why it’s so important to do a dry run of any presentation.

The second point, my bold new success with Object Builder, is much more exciting. When I first built Object Builder I had the idea that I could build not only my active record, but possibly interface controllers as well. I’d never done it before, until this week. If you’re not hip to what an application controller is, it’s the bit of code that manages the interface for a particular table (or related tables) in your application. Once the active record objects are built, this is the part where most of the time is spent; it’s definitely where I’ve spent most of my time on CeaMuS.

I spent a couple of days on getting this to work, fine tuning the templates until I got something that was really slick. I spent another day to tweak some of the interaction with PHP’s PDO module. It’s a really neat little module, but unfortunately it’s the broken piece of technology I mentioned earlier. Fortunately the Windows version comes pre-compiled and it’s excellent. It’s what the other PHP-based database abstraction modules aren’t. It’s also in the C source. Sometimes I get buggy about speed, so this is a really great thing from my perspective.

The downside to this overwhelming success is that I’m starting to question the direction I’ve taken with CeaMuS. I’ve put a lot of time into making CeaMuS what it is in C++. But in the space of a week I was able to build a solid shell in PHP, and it would be trivially easy to expand. It’s very tempting to do the same thing for C++ and rebuilt CeaMuS from the ground up, on a more expandable foundation. The pragmatic side of me resists it, but when I build the hosted version of CeaMuS I may start afresh using this technology.

In spite of the appearances on the CeaMuS site, there actually has been a respectable amount of activity in software development. The version has been bumped from 2.0c to 2.0e, and some of the results from beta testing are finding their way into the code. Some other things are being done to make it easier to expand CeaMuS when new features are necessary. So what are the changes?

The biggest change that you’ll see as an end user is that configuration got a lot easier. In 2.0c all of the configuration was handled through the ceamus.conf file. While the format of this file isn’t difficult, it simply can’t be edited online via a web browser and there are too many opportunities for things to go wrong. This was abundantly clear during beta testing. The structure of the file was also something of a nuisance to manage in the code.

Version 2.0e stores only the most crucial information in the ceamus.conf file. All the other configuration–the menus and galleries–are now stored in the database. A lot of things are also “handled” for you. One of my least favorite tasks in setting up a site was always setting up the directory structure for galleries. Now when the images are generated for a gallery the directory structure is automatically put into place. The same feature will be available for menus by the time 2.0e is actually released to the public.

The biggest changes, and the things holding up release, are architectural. Much of this can be blamed on my cousin, who bought me two excellent programming books for Christmas this year. Eric Gamma’s Design Patterns helped me to solidify solutions to some problems that had been bothering me for a while. Scott Meyer’s Effective C++ and Effective STL helped me to straighten out some problems that I’d been having, and that had been limiting development of new features in CeaMuS.

The other big change is that I finally decided to automate the building of database objects. CeaMuS always used the Active Record design pattern. Before the classes were always written by hand, but once they were done it was very easy to write interfaces that used the database. Over the fall a lot of ideas that had been swirling in my head about how to automate this took final shape, and I have a fully automated system for generating active record objects. I’ll post more about that later. For right now, all of the data objects and interfaces are being retrofitted to use these automatic objects.

The current state of the code is that it’s all ripped up. It’s definitely not following the Agile Manifesto of always being in a shippable state. But the upside is that as of Sunday last all of the individual components were compiling well together. A high level of paranoia will set in now as I put together a reasonably comprehensive test suite to make sure that it all actually works well together.

With just a little bit of luck I’ll be able to release 2.0e soon, something that will almost certainly make my beta testers a good deal happier.