3

I'm trying to model nWoD characters for a roleplaying game in a character builder program. The crux is I want to support saving too and loading from yaml documents.

One aspect of the character's is their set of skills. Skills are split between exactly three 'types': Mental, Physical, and Social. Each type has a list of skills under if. My Yaml looks like this:

PHYSICAL:
    Athletics: 0
    Brawl: 3
MENTAL:
    Academics: 2
    Computers

My initial thought was to use a Multimap of some sort, and have the skill type as an Enum, and key to my map. Each Skill is an element in the collection that backs the multimap.

However, I've been struggling to get the yaml to work. On explaining this to a colleague outside of work they said this was probably a sign of code smell, and he's never seen it used 'well'.

Are multiMaps really code smell? If so what alternate data structures would suit my goals?

  • 8
    Nice advice from your colleague there. Takes a veiled swipe at the technology without actually volunteering any useful information. – Robert Harvey Jun 26 '14 at 21:46
  • 3
    I've seen similar structures. Usually in Java it's something like a Map<String,List<String>> or Map<String,Map<String,SomeClass>>. Doesn't seem like a code-smell to me, if it fits with what you need to do. – FrustratedWithFormsDesigner Jun 26 '14 at 22:00
  • Do all characters have the same pool of skills? If so, is there any reason that you would want each character to store a copy of the skill type information? After all, athletics is physical for everyone (or so I assume). – jwodder Jun 26 '14 at 22:03
  • 4
    What kind of attribute a given attribute is. That's domain knowledge, not something you want to be configurable. No character is going to want Athletics to be a mental trait, and presumably doing this would break your application. Why does the configuration file need this flexibility? – Phoshi Jun 27 '14 at 13:34
  • 2
    If multimaps were a code smell in general, why would C++, Google Guava and .Net (experimental) include them? – svick Jun 28 '14 at 14:47
2

A couple of notes:

  • Never deserialize untrusted YAML. In most YAML parsers this allows arbitrary code execution. In SnakeYAML, you can prevent this, but you need to be very careful, and the risk seems unnecessary.

    Since you just need a key-value store I would recommend JSON instead, which brings me to:

  • Use strings as keys, and convert from strings to enums after loading (You can do this with a switch statement or by reflection.). This avoids the need for calling Java constructors from the YAML parser, and thus eliminates the security vulnerability. The conversion can easily be made where needed, and hopefully will not cause much of a slowdown.

  • | improve this answer | |
    • 2
      "Never deserialize untrusted YAML." - Wait, what? Are you saying that YAML has a "execute this code" feature, or that most YAML parsers are incredibly buggy? – Sebastian Redl Nov 20 '14 at 11:01
    • @SebastianRedl Looks like a little bit of both; YAML seems to allow deserialization into arbitrary object instances, and requires extra work to prevent code execution in dynamic languages – Izkata Nov 20 '14 at 15:47

    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.