I have two big C structures used in a C legacy code, and I need to convert from one to another, and the other way around. Something like this :
#include <iostream>
struct A {
int a;
float b;
};
struct B {
char a;
int b;
};
struct C {
A a;
B b;
};
struct D {
int a;
char b;
float c;
};
void CtoD( const C& c, D &d ) {
d.a = c.a.a;
d.b = c.b.a;
d.c = c.a.b;
}
void DtoC( const D &d, C& c ) {
c.a.a = d.a;
c.b.a = d.b;
c.a.b = d.c;
}
int main()
{
C c = { { 1, 3.3f }, { 'a', 4 } };
D d = { 1, 'b', 5.5f };
#if 0
CtoD( c, d );
#else
DtoC( d, c );
#endif
std::cout<<"C="<<c.a.a<<" "<<c.a.b<<" "<<c.b.a<<" "<<c.b.b<<std::endl;
std::cout<<"D="<<d.a<<" "<<d.b<<" "<<d.c<<std::endl;
}
Functions CtoD
and DtoC
are doing the same thing, but in opposite direction. Changing one structure requires changing both of them.
To minimize possibility of an error, and to avoid repetition, I would like to implement some kind of mapping, where I define the connections only once, and then I copy one value to another. This way, only one change is needed if a structure changes.
So, the question is : how to do it? Is there perhaps a design pattern I could use?
My real structures have hundreds of fields. The above is just simplified example.
In your literal example, I don't think it's worth the hassle. Just write tests so that you ensure your conversions work well.
In your real code, if your structs have "hundreds of fields", your structs may be badly designed. Maybe they should be composed of smaller objects. I've never designed anything which required hunderds of fields in exactly the same struct object - instead, these fields allowed some kind of classification so that they could be treated in smaller bunches.
Since your code is legacy and you don't want to rewrite it, just write tests for your conversions functions, as I said above for the example.
Well tested code is no longer legacy code. Legacy code is basically code for which you don't have automated tests.
If rewriting it is not an option, testing it is a must.
About the cost of testing it "both ways", Idan Arye's comment below says everything:
Since the conversion is symmetric, testing it both ways is not that much more work than testing it one way. All you need to do is init two structs -
C c
andD d
- and set them to be the converted versions of each other. Then you just have to check thatCtoD(c)==d
andDtoC(d)==c
(or use comparison functions if you happen to have them defined). The big work here is initializingc
andd
- but you would have to do that anyways if you wanted to test one way conversion, so adding the test for the other way is very cheap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With