Who should decide how to encode a type, the type itself or the message that contains it? #210
Replies: 4 comments 2 replies
-
|
Although I generally agree with the premise that it doesn't make sense to mask For the |
Beta Was this translation helpful? Give feedback.
-
|
Another thing worth noting is: the changes you proposed to the |
Beta Was this translation helpful? Give feedback.
-
|
I'm sure a happy medium exists somewhere between the two propositions, but it'll take a bit of discussion to find it. |
Beta Was this translation helpful? Give feedback.
-
|
If were talking about future corrections to the code base (Which can be done without breaking anything) this is great starting point for a discussion. I do agree that its weird that identifier is the one off handling ddml like this. Although i have to add to this that permissions would also go the same route (vs what you propose having a match in the required messages for a permissions "type") So this is not a one-off case, and as dyrell said it would lead to A LOT of syntactic duplication. That said; think we should find something more maintainable, copy/paste around the message isnt going to do the trick. For example, we could just use a combination of Alternatively, we can still extract the |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
There are 2 common approaches to defining the encoding/decoding of a type.
The first, and straightforward one is to define the encoding of a type as an intrinsic property of the type itself. This approach will see the encoding implemented in the very same module where the type is defined, alongside its other intrinsic properties and logic. For example, the
serde::Deserializeandserde::Serializetrait implementations, or theContentWraporContentUnwrapin the case of DDML.This approach works great in simple scenarios where there's only one way to encode the types, with a single port through which they need to be serialized, and it helps getting the knowledge about the types encapsulated into their own module. However, it can get problematic quickly in the following scenarios:
In these cases, one needs to define an encoding specifically for each target port. This could still be defined in the type's module, but it would obviously derive into an improper coupling between the external port interfaces and the core domain type.
I want to expose in this discussion that the second case is what is happening with
Identifier.Identifieris a low-level type that represents the public identifier of a subscriber. This type is used within all the messages of Streams. In contrast with other types used within the messages, this one implements its ownContentWrap,ContentUnwrapandContentSizeof, and the messages delegate the wrapping and unwrapping of this type to the methodsIdentifier::wrap(),Identifier::unwrap()andIdentifier::sizeof(). The encoding of this type uses the DDML commandmaskto encode the identifier to the byte stream. However, it is not logically correct that it is always masked; in keyloads and sequence messages it should actually be absorbed.In my opinion, encoding should generally be implemented in the outer-most, port specific structure. Even if this might seem to generate a bit of duplication, I defend that this duplication is in fact not duplication but actually happy coincidence. Rushing to DRY up the code by deduplicating encoding often results in wrong abstractions and the consequently messy workarounds. In the case of Streams, I suggest getting rid of the implementation of
ContentWrap(etc) forIdentifier, and implementing the pattern matching of the different cases ofIdentifierin thewrap(etc) method of each message type.Beta Was this translation helpful? Give feedback.
All reactions