Thursday, August 18, 2016

SPlayerState, mossbin

Today I straightened out an issue with PlayerState and SPlayerState that I was unsatisfied with. As written, SPlayerState extended PlayerState compositionally. It did this because of serialization. One of my original design choices for mossbin was that serialization was heritable. that is, if you had:

[WritableClass]
PlayerState {}

SPlayerState : PlayerState {}

SPlayerState would inherit the WritableClass attribute and implicitly become a serializable class (with the exact same fields as its parent).

But now imagine on the server you have this:

[WritableClass]
LoginResponse
{
   [WritableField]
   PlayerState m_state
}

If you fill out m_state with an SPlayerState, the server will write out an SPlayerState--even though that type is defined in the server dll! Obviously the client won't know what to do with this thing. For this reason, SPlayerState contained a PlayerState via composition. However, as I'm about ready to build out the client side, including creating a CPlayerState, I began to feel the limitations of this pattern. Actual inheritance would be tidier for my purposes.

So I changed my tune. Now [WritableClass] is NOT an inheritable attribute. In addition, if mossbin encounters a [WritableField] that is a base-type reference pointing to a non-serializable child, it will automatically walk up the inheritance tree, looking for a base type to serialize as. So you CAN assign SPlayerState to the PlayerState reference, and have it serialize as a PlayerState that the client can understand.

In a way, this is its own sharp edge (I can imagine someone--maybe future me--being bamboozled by the fact that I had a class with m_parent->child on one side of a serialization, and got back m_parent->parent on the other side). But it's super-convenient for this server-client relationship, where specializations on both sides want to communicate by their common base class.

This actually created a new missing feature I had to document. Say you have:

[WritableField]
Parent m_parent; //(points to type Child after instantiation)

You might want to serialize this as a Parent in one situation (say, sending something down to the client, but actually serialize it as the Child that it is in another (say, the server saving its own specialized state into the database). This will entail a new property on WritableField, and some extra logic in mossbin.

I'm still not sure writing my own serialization layer was a good idea, but it sure is fun being able to tune things at this level of detail.




No comments:

Post a Comment

Note: Only a member of this blog may post a comment.