Problem: 3000 business objects, each with some regular data (~20-30 shallow fields, JSON) and its own unique small behavior (often just a one-line javascript function).

Possible solutions on my mind:

  • Solution 0: business_objects.js (~1 MB) data and functions on same object.
  • Solution 1: data.json (~800KB) + only_behavior.js(30-40KB), joined by shared ID
  • Solution 2: data.json (~800KB) + behavior_annotated.js (~200KB), joined by shared ID, but also has some human readable information (denormalized/duplicated) to ease understanding
  • Solution 3: DB (mongo/postgre), and store functions as string, then revive them with new Function constructor.
  • Solution 4: each function in separate file (means folder with 3000+ files).
  • Solution 5: arbitrary split 3000 objects in hierarchy with branching coefficient of 10 (10 files with 300 objects in each, or 10 folders, each with 10 files, each with 30 objects).
  • Solution 6: write JSON/String based DSL for declarative definitions of behavior.

Extra constraint: business objects can change by "force of nature", and we need to update our repository fast, when this happens.

All solutions look quite ugly to me.

Maybe anyone can suggest a good pattern to deal with such issue ?

  • 4
    I suggest you tell us the story that lead to you considering how to manage 3000 business objects as one lump. May 16 '17 at 22:12
  • the story is quite simple: a card game with different abilities per card. Abilities and cards already exist )
    – c69
    May 16 '17 at 22:16
  • 1
    3000 of the objects you described hardly sounds like a significant amount of data as far as a computer is concerned. From a performance standpoint, which seems to be your concern, anything that isn't totally brain dead will do just fine. Organize your data for data's sake, not performance. May 17 '17 at 4:19
  • 2
    This is Hearthstone / Magic the Gathering type game, so unique behavior that i need to store separately is only the "special cases" - from "when you summon minion deal 1dmg to random enemy" or "at the beginning of your turn lower the cost of cards in your hand by 1" or "whenever friendly Beast dies give +1/+1 to your Hero", to harder stuff like "if you are holding a dragon, destroy legendary minion when this is played from hand" or "summon back all your Dragons that died during game". I.e. mostly operations upon arrays, but they a) still need to be a code b) have to match actual implementation
    – c69
    May 17 '17 at 4:49
  • 1
    I only see two types of objects, cards and behavior.
    – Jon Raynor
    May 17 '17 at 14:30

First, you should think about in which form you finally need the cards/business objects in your program to do something meaningful with it. From what you wrote I assume if you have all those objects in form of Javascript code/objects, you can actually shuffle or deal the cards as well as execute the code when a player decides to use one of his cards. Note, for these use cases, you do not need any hierarchy, the hierarchy is something you only need for maintaining the card types and their "business rules".

If you do not have a full team of five to ten people implementing (and maintaining) the code for these 3000 objects, you need definitely some declarative approach to describe / implement most of them. And I am pretty sure in 3000 objects, there will be all kind of repetitions/similarities in the behaviour. For example, I can imagine your example

"when you summon minion deal 1dmg to random enemy"

might occur often in the form

"when you summon <X> deal <Y> to enemies of type <Z>"

So you could try to make use of that and create an object generator, based on some tabular input and some rules, and try if you can generate most of the objects, including the Javascript code for the behaviour, based on code templates with placeholders. Of course, there will be some objects with rules too complex for your generator, so you will need to implement them manually, but you should aim for these being only a small portion of the whole set of objects.

So what you finally need to store is

  • the tabular input for your generator
  • the implementation for the (hopefully few) objects which cannot be generated

The input data for your generator maybe stored in a spreadsheet, "DSL like" text, XML or JSON files, or in a (lightweight) database, depending on what you feel most comfortable with. If there is only one person at a time maintaining the rules, I would probably go for a spreadsheet, for many people I would probably try a database. In both cases it might be necessary to provide "template strings" or fields with code snippets in the table. Call this a "generator DSL", if you like. 3000 rows in a spreadsheet is quite manageable by one person, especially when you can make use of the filter and sorting capabilities. "name", "color", "rarity", "expansion", "type of enemy" or "business rule type" - with a spreadsheet program you can filter or sort your cards "ad hoc" according to these attributes, without having the need to invest too much thought beforehand into the hierarchies you might need.

The remaining "non-generatable" objects might be implemented in ordinary text files, directly in Javascript. Or, you can generate even those objects, but provide some "hook" where you can add manually written code. The technique for organizing this additional code (one file for all, one file per object, whatever) is mostly dependent of how many of them there will finally be.

  • True - no free lunch - i wish i had a team of 5 people to do the grunt work ))) In reality i think i will use the hybrid approach - move every spell i can to declarative serializable templates, but still split behavior files per expansion (7) and class (11). Will see how it works out. Thank you, both Doc Brown and @CandiedOrange for the feedback )
    – c69
    May 18 '17 at 3:24

Solutions 0 through 6 are ugly because they've been striped of any meaning. That's what leads to "everything in one box". What's missing here is some organizational structure.

If these were playing cards they'd have suits and ranks to organize them by. If they were magic the gathering cards they'd have color and set to organize them by.

Whatever your 3000 cards are, you had better use a solution that allows them to be organized in a way that would allow people to find the card they're looking for.

These are business objects. So they need to represent the business domain well.

So no, everything in one box and mix is not a good solution. Use a solution that allows for some structure.

  • Yeah, - by color, rarity, expansion - but they are still kindof arbitrary categories.. just imho.
    – c69
    May 17 '17 at 4:53
  • This btw is Solution #5 - split in arbitrary categories. //upvoting anyway, thanks for the input. Maybe that's the way to go.
    – c69
    May 17 '17 at 4:57
  • 1
    Well no, it's not solution 5. Arbitrary is not meaningful. Give us meaningful categories. May 17 '17 at 5:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.