0
\$\begingroup\$

It is going to be just a fraction of the code but for the sake of the example let's say I have a class Stat

class Stat
{
    private string _name
    public Name { get { return _name; } } 

    public Stat(string name)
    {
        _name = name;
    }
}

When I serialise object of type Stat with for example TinyJSON, it produces:

{ "Name": "some random name" }

So I figured I will create StatData with public property and not a getter so then I can use it for serialisation.

class StatData
{
    public string name
}

As far as I can tell I have now 2 choices:

  1. Write converter method and, upon serialisation request, convert Stat to StatData and serialise StatData.
    Pros: single responsibility principle preserved
    Cons: more code and nested dependencies

  2. Go with private StatData _data in Stat class and using getters as previously and adding, eg.: ToJSON() method on Stat
    Pros: public interface
    Cons: generics to handle inheritance eg.: StatComposite and serialiser dependency

Is/are there any other method(s) or potentially design pattern to deal with the problem?

\$\endgroup\$
  • 1
    \$\begingroup\$ Why do you need StatData? It sounds like serialization of Stat, directly, works as you'd expect? (Basically it's unclear what you think the "problem" is here.) \$\endgroup\$ – Josh May 19 '17 at 16:54
  • \$\begingroup\$ Without StatData serialiser outputs { "Name:" ... } and what I ned is { "name": ..}. Also I want to only expose Name` as a public get so it can not be modified once created, hence idea with type conversion. \$\endgroup\$ – IndieForger May 19 '17 at 17:02
  • \$\begingroup\$ That issue with "name" versus "Name" is an issue that's very specific to the serializer you're using, far more specific than your question (as written) implies; depending on your serialization API there are ways to control that.. Is the name issue more important than the broader design issue? If so this question should probably be edited. \$\endgroup\$ – Josh May 19 '17 at 17:04
  • 1
    \$\begingroup\$ Have you tried looking into attributes? Typically, serialization APIs offer high degree of customization through attributes/annotations. \$\endgroup\$ – wondra May 19 '17 at 17:58
1
\$\begingroup\$

Specific language and technology platform notwithstanding, I generally find the ideal approach is to separate the concepts of static versions of some data (resources you will load from or save to the disk, and thus serialize) versus the potentially dynamic versions of that data you'll use at runtime.

For example, I'd have one type (class, in C#) for a WeaponResource which contains all the fixed information about a weapon type. But at runtime I'd create a Weapon class which is actually used by the player. That Weapon class is initialized with a WeaponResource reference, but also has methods to do things to the weapon at runtime (such as apply temporary buffs) that don't make sense for the resource to have. This goes towards your "separation of responsibilities" point.

It's the WeaponResource that is serialized, and thus built in such a way as to be amenable to serialization. How to do this varies depending on language and serialization tools, but generally the approach is to make the type as close to plain-old-data as possible.

I don't think this approach actually results in "more code," as you note as a con. At least not appreciably; you were already going to have all the fields in the resource type somewhere, now they're just nicely packaged away. The dependencies between the resource and the runtime consumer of the resource are nice and clear as well.

\$\endgroup\$

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.