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.
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:
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:
You can just flatten the list of arguments
Simply allow a raw value as the argument.
An alternative to the above examples, a lambda could be added as handler for complex types:
And example use:
Optional extensions:
<data>objects as those can always be set using a pair of pointer and length.sbeSetAllFields()method.