I'm making a front end to a relational database-like construct. Essentially, each column I am rendering has the following things related to it:
Metadata. Everything to do with a particular database column. Name, permissions-required, type of data, limits, etc.
Limits. What range of values this can hold: for numeric columns it's set by a min/max, for text it's set by a whitelist of possible strings, location set by a lat/long/radius.
View. A filtered view of a single col
Renderer. The thing which renders a GUI for editing this column's limits; spits out HTML. A numeric Renderer would have two textboxes, a text renderer would have something else, etc.
Generally, I have my abstract class hierarchy set up like:
abstract class Metadata{
overallLimit: Limit // a bound on anything that can go in this column
}
abstract class Limit{
def filter(...): Boolean; // checks if something can go in this column
}
abstract class Renderer{
colMetadata: Metadata // the data for the column this guy is rendering
filterLimit: Limit // any additional filter being applied to the result set
template: Template // renders stuff
}
abstract class Template{
def render: Node // splits out HTML
}
In the abstract this is fine. However, when I try to create different types of columns for various datatypes, it gets slightly messy:
class NumericMetadata;
class NumericLimit
class NumericRenderer
class NumericTemplate
class TextMetadata
class TextLimit
class TextRenderer
class TextTemplate
class LocationMetadata
class LocationLimit
class LocationRenderer
class LocationTemplate
When i define any of the subclasses, I can override the fields to make it more specific:
abstract class TextRenderer{
override colMetadata: TextMetadata // the data for the column this guy is rendering
override filterLimit: TextLimit // any additional filter being applied to the result set
}
I was just wondering if there was any other way of structuring this sort of thing? The "rectangular" grid of classes is somewhat unavoidable, given the domain i'm trying to model. This "multiple parallel class hierarchies" thing, with each horizontal component (e.g. Limit) having its own inheritance hierarchy seems a bit messy: all the inheritance hierarchies look exactly the same and have to be kept in sync, which seems like a violation of DRY. On the other hand, it's all type-safe; the compiler will yell at you if one of your hierarchies is screwed up, and overriding the abstract fields to make them more specific means each vertical component is bound together in a type-safe manner (can't give a LocationTemplate to a TextRenderer for example) and it's the best I've been able to come up with.
I've never built anything like this before, and struggled with the hierarchy and inheritance quite a lot before it ended up like this. Are there are any other class layouts or techniques that more experienced people have used for this sort of situation? None of the OOP books i've read go into situations requiring this sort of "rectangular" grid of classes.
Thanks!
-Haoyi