Empty Classes

Ovid on 2009-07-10T14:34:24

We have many objects with common attributes like titles, synopses, versions, created/modified, etc. Due to business requirements, every exposed object must have a searchable unique ID called a "pid". Thus, we've been forced to do a rather unfortunate denormalization where every pid is placed in an entity table. This table also lists the object types (brands, series, episodes, etc.) and you can look up any pid and get the object it stands for from the appropriate object type. One benefit of this is that it was (relatively) trivial to strip all titles off of objects, put them in a central "title" table, and allow arbitrary title searches and get back all objects, regardless of type, which have matching titles.

We're now doing this with versions. We'll probably do this with synopses at some point. Because every object links into the entity table, we have standard searches available for many things. If we were to take this to the logical extreme, we could do something rather interesting. We could create an object called a "preview" (we have no plans to do so), which has titles, synopses, promotions, tags and parent (the thing we're previewing) and do this:

package BBC::ResultSource::Preview;
use Moose;

extends 'BBC::ResultSource::Role::ResultSource';
with qw(
    BBC::ResultSource::Role::Titles
    BBC::ResultSource::Role::Synopses
    BBC::ResultSource::Role::Promotions
    BBC::ResultSource::Role::Tags
    BBC::ResultSource::Role::Parent
);

And with that, have a new object. Effectively, you could have a completely empty class aside from the roles being listed. The preview table might only have an id and nothing else. How would we build the XML for this? Pseudo-code:

package BBC::Builder;

use Moose;
with 'BBC::Builder::Role::DoesBuilder;

sub build {
    my $self = shift;
    my @build_data
    foreach my $role ($self->resultsource_roles) {

        # following a predefined sort order
        next unless $self->meta->does_role($behavior);
        push $build_data => $self->build_data_for($role);
    }
    return \@build_data;
}

No longer would we need to explain how separate objects are built as XML and we'd have greater consistency in our XML building. Of course, this is still "blue sky thinking", but it would tremendously simplify a lot of our code.

(Note: I know I can just ask the metaclass directly what roles that instance does, but I thought the does_role() method call would show readers more clearly what would happen under the hood.)