-
Notifications
You must be signed in to change notification settings - Fork 542
Description
In our company we sometimes struggle with extending schemas, particularly with extending messages with new fields. The problem is that if one person extends the schema in one repo and a second person maintains C++ code, somebody may not notice that a fields was added. This results in part of the bytes in the buffer not being initialized.
You have already added the checkEncodingIsComplete()
method which solves part of the problem - checks if all data and group elements were added. But doesn't check if all fields were set.
So I want to suggest adding a new method to the encoder which will support compilation-time checks:
msg.sbeSetAllFields(field1, field2, field3);
void sbeSetAllFields(uint16 field1, uint32 field2, uint8 field3)
{
this->field(1).field2(field2).field3(field3);
}
The basic idea is that when you add a new field to the schema, the sbeSetAllFields()
method gets extended with new arguments. A code that misses some fields simply won't compile. So every time somebody updates the schema, code stops compiling until you fix all differences. This is a very safe approach. And I believe it's also a zero-cost abstraction on top of the existing API.
There are at least several interesting edge cases which I think are worth mentioning with some rough proposal for handling:
- Composites.
You can just flatten the list of arguments
void sbeSetAllFields(uint8 field1, uint16 combo_one, uint16 combo_two, uint8 field3)
{
this->field1(field1);
this->combo().one(combo_one).two(combo_two);
this->field3(field3);
}
- Bit sets
Simply allow a raw value as the argument.
An alternative to the above examples, a lambda could be added as handler for complex types:
template <typename Handler1, typename Handler2>
void sbeSetAllFields(uint8 field1, Handler1 && combo, Handler2 && bitSet, uint8 field4)
{
this->field1(field1);
combo(this->combo());
bitSet(this->bitSet());
this->field4(field4);
}
And example use:
msg.sbeSetAllFields(
1,
[](auto & combo){combo.one(1).two(2);},
[](auto & bitSet){bitSet.clear().someFlag(true);},
8
);
Optional extensions:
- The method could be extended with
<data>
objects as those can always be set using a pair of pointer and length. - Composites and groups could also get a
sbeSetAllFields()
method.