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?

17
  • 8
    Nice advice from your colleague there. Takes a veiled swipe at the technology without actually volunteering any useful information. Jun 26, 2014 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. Jun 26, 2014 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, 2014 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, 2014 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, 2014 at 14:47

1 Answer 1

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.

  • 2
    • 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? Nov 20, 2014 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, 2014 at 15:47

    Your Answer

    By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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