dimanche 14 juin 2020

Should I pass a context object to client object, or create client object and pass all required information to constructor?

For example, I write a game where I need to parse json with data definitions, which may refer to assets. The game supports modding, and in order to properly resolve paths to assets I need to carry mod reference along with every asset reference.

Currently I do this:

class ConverterContext(val mod: Mod)

interface DefinitionConverter<T> {
   fun fromJson(json: JsonValue, context: ConverterContext): T
}

class AssetRef<T: Any>(val path: String, val type: KClass<T>, val mod: Mod)

class TreeDefinition (
   val name: String,
   val texture: AssetRef<Texture>,
   val maxHealth: Float
) {
   companion object Converter: DefinitionConverter<TreeDefinition> {
      override fun fromJson(json: JsonValue, context: ConverterContext) = 
       TreeDefinition(
          name = json["name"].toString(),
          texture = AssetRef(json["texture"].toString(), Texture::class, context.mod),
          matHealth = json["maxHealth"].toFloat()
       )
   }
}

As you can see, texture path is converted into AssetRef which holds reference to mod, that the definition is being loaded from. This allows me to properly resolve paths, later, when I need to load textures, sounds, etc. But I wounder, would be better/worse to create it like this:

interface DefinitionConverter<T> {
   fun fromJson(json: JsonValue): T
}

class AssetRef<T: Any>(val path: String, val type: KClass<T>, val mod: Mod)

class TreeDefinition (
   val name: String,
   val texture: AssetRef<Texture>,
   val maxHealth: Float
) {
   class Converter(val mod: Mod): DefinitionConverter<TreeDefinition> {
      override fun fromJson(json: JsonValue) = 
       TreeDefinition(
          name = json["name"].toString(),
          texture = AssetRef(json["texture"].toString(), Texture::class, mod),
          matHealth = json["maxHealth"].toFloat()
       )
   }
}

I currently use the first approach. And this is by far the first time I used the context object pattern(it's a pattern, right?). What I can tell, is that suites better for this case, because I can create converter once and use it to convert data from any mod. The second option however, has less classes, but forces me to instantiate each of converters for every mod. I would like to hear some thoughts of more experienced developers, which option is better for which situation?

Aucun commentaire:

Enregistrer un commentaire