Serializer_MTC breaks system on object update?

When I updated a class with a computed property string instead of a native string of the same name, two bad things happened with serialization:

(1) a type mismatch error in the serializer occurred when trying to load user data from a file.
(2) a type mismatch error occurred in other services consuming the serialized class via a REST API, which services still use the previous version of that class.

The result is that each update of an object may require every version of that class to be standardised, and updated in every service sharing serialized data, each of which then must be recompiled and redeployed. Worse, all users will lose their existing data saved by serializing the class.

Is there a better compatible version of Serializer_MTC or have I perhaps missed a step?

To be clear, you deployed a class that had property X As String. In an update, you switched X to a computed property with a getter/setter As String. Right?

Your protocol should have versioning. Together with your object, you should carry a version. Your old one should carry something like objversion = “1” and the new one “2”. Once you detect it, you should deserialize the object to a proper class, legacy for 1 and new for 2. And process it as it should. Once you change all the clients (transition) to use v2 only, you could stop support for v1 objects. This way you can introduce breaking changes over time.

Yes Kem, that’s what I did.

Rick, the idea of a services architecture with REST APIs is to allow one part of the system to be changed without having to touch all the others. So having serialization create a monolith requiring staged updates defeats the purpose.

For customer data the error can be detected and the old class can be used to transfer the data to the new class for the data to be rewritten I suppose. But that makes a mockery of OOP’s claimed benefit of polymorphism - usually the business case changing kills that but not merely updating the object.

So you keep using the prior v1 endpoint as it was.

Create a new v2 enpoint using the new architecture, AND UPGRADE all clients to it.

You changed the backend object, you need to change the client for compatibility.

I could understand that if serialisation was of the objects themselves as binaries but we are talking objects mediated by JSON dictionary data. I wasn’t expecting binary compatibility issues between loosely coupled services communicating with nothing but strings in this case.

The reason why computed property strings are replacing ordinary strings is to apply protocol or security rules. The old objects are to be replaced on systems that are third-party-facing but not on internal systems. I was hoping to only touch a few services not 20.

For technical reasons we use different versions of Xojo and different plug-ins versions so recompilation and deployment of the entire system is non-trivial. A services architecture was supposed to provide a layer of insulation.

When you create an API, you can make it with room to expansion without breaking changes, like adding new properties to the JSON container sent (we’re not talking about object serialization, just data transportation, as you said, like a dictionary). Old clients would not send the new properties and you could handle legacy and new with the same server endpoint. That’s not the case of object serialization, it don’t just transfer data, but also structures, metadata, and demands the receiver class being exactly the same (never used Kem’s serialization, but this is “the law”), you send a serialized object A, it must be deserialized as the same A class, if you change the A class in one endpoint you probably will break things. Thats different of using a vanilla JSON object as mere “data holder”. I do serialize data as JSON to send data to my APIs, not as another object serialized, just use vanilla JSONItem with all my needs added to it. It does not demand structured rigid data, it never fails. What is needed is some check, to know that the packet is really valid and not a hacker sending garbage. That also could break things.

Yes you are correct that technically serialisation isn’t data transport. However in OOP generally, modifying classes without breaking compatibility is supposed to be commonplace - function overloading for example. In our case it isn’t even that, just computed string for string.

So here’s the thing: serialisation shouldn’t break OOP or there is no point coding in OOP to start with. And there is no reason why OOP should not be compatible with a modern services architecture either.

That’s my argument anyways, even if it is admittedly a bit non-standard bleeding edge. There are different ways I can tackle the issue and one would be to modify the open source. That would take some thought and I’m in a bit of a hurry, so for now I think I’ll work around it. A loosely coupled serialiser would have advantages though…

If made correctly, yes. Removing methods or properties or changing behaviors used elsewhere breaks instantaneously.

Computed properties using the same datatypes never break compatibility which was why this issue was unexpected.

I agree, that is unexpected. Did you try tracing the code to see why it’s throwing the exception?

I didn’t look too deeply but it seemed to mistake the class object for its member although the “allow computed property” setting (I don’t have the code with me now) was true by default. I suspect the issue is with introspection, that computed_string ≤≥ string. That’s where I would look first anyway.

I’m don’t want to modify the code in a hurry (I already did to support Pair datatype) because if I get it wrong there will be all sorts of trouble in userland. And it means I will have to touch every service with the mod so it’s something that has to be right the first time,

Out of curiosity, could you please create a class as

Class Class1

  Public Property prop1 As Integer = 456

  Public Function method1() As Integer
    Return 123
  End Function

End Class

Then duplicate it, change its name to Class2, and just convert prop1 to computed, it will end as something like:

Class Class2

  Private property mprop1 As Integer = 456
  
  Public Computed Property prop1 As Integer :

    Get prop1
    Return mprop1
    End Get
    
    Set prop1
    mprop1 = value
    End Set
  
  End Property
  
  Public Function method1() As Integer
    Return 123
  End Function

End Class

Create one instance of each, serialize it using the MTC methods and post back here both JSON strings?

Yes Rick i will do it tomorrow as its already almost 2am here.
Cheers.

Good night. :wink:

Do you happen to have a same named method with the same return value as the property ? This can cause issues also.