I have a Ship class, into which components can be added which change the performance of the ship.

The question is regarding modelling this. My first approach essentially was an EAV approach (a pseudocode example, roughly on Django Models, below).

class Item(model):
    name = CharField
    desc = TextField

class Attribute(model):
    name = CharField
    desc = TextField

class AttributeValue(model):
    item = FKey(Item, related_name='attributes')
    attribute = FKey(Attribute)
    value = DecimalField(max_digits=100, decimal_places=2)

class Ship(model):
    current_hp = Integer
    vessel_class = FKey to a table containing the base attributes of a given class (hp, manoeuvre etc.)

    @property
    def max_hp(self):
        base_hp = ship.vessel_class.hp
        base_hp += reduce(lambda x, y: x+y, [item.attributes.get(attribute__name='modifies_hp').value for item in s.components.filter(attributes__attribute__name='modifies_hp')])

This requires a multitude of joins to get to the total hp of a given object.

An alternative (using postgres' JSONB)

class Item(model):
    name = CharField
    desc = TextField
    attributes = JSONField

class Ship(model):
    @property
    def max_hp(self):
        return self.vessel_class.base_hp + reduce(lambda x, y: x+y, [item.attributes['hp_modifier'] for item in self.components.filter(attributes__has_key='hp_modifier')])

This feels tidier as it keeps the attributes of each Item tied to the Item, and additionally doesn't require further database lookups (as the returned Item object has the data already loaded, rather than requiring a further database lookup for the value of the attribute).

Any preference on a given approach?

share|improve this question
1  
Why do you think that your data model is inefficient? It looks like a pretty standard normalized model for a relational database to me. – Philipp Aug 22 '16 at 10:48
    
Updated above. I guess the key query was whether the JOIN load of the normalised approach is unnecessary, and whether storing those flexible attributes in a JSONB postgres record would be better – jvc26 Aug 22 '16 at 11:21
1  
That depends on how you are going to query the database. When you always load complete ships into memory, then you can store each of them as one blob in the database. When you want to do more complex and selective queries, you should keep it in denormalized form, because normal SQL is still what databases are designed for. Those fancy unstructured data types some databases allow are a compromise between both. – Philipp Aug 22 '16 at 11:24
1  
Oh, and when you have data which never changes except through developer intervention, then it might be best to put that data in a configuration file which is parsed at startup and then kept in memory. – Philipp Aug 22 '16 at 11:36
1  
...or computed and cached in some way at startup... – Alexandre Vaillancourt Aug 22 '16 at 11:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.