12-10-2012 03:21 PM
Cross posted from here. Just greedy for more views/potential responses.
I have an incoming message that has an array of u8 data. A subset of this data is parsed to determined the "type" of the message. There are 4 different types of messages so I have a class for each type, and a factory that creates the proper one based on the type. Then I have a method for each type that futher parses the u8 array (the array is parsed differently based on message type). This gives me a bit more information, and I finally know the "final" type of message so I can generate that class.
Basically I have a hierarchy that looks like this
(ugh didn't format correctly but you get the idea)
base message
/ / \ \
type1 type2 type3 type4
/ | \
finalsubclass
The issue is, because I find out a little more information with each step of parsing the u8 array, which tells me how to parse the next step I keep having to "downcast" my class which means continually trying to preserve data that already exists in the parent class. I have seen the methods mentioned here but it gets really hairy with multiple levels of children. From purely a cosmetic standpoint, the levels of inheritance seem to make sense because they match the protocol of the messages I am receiving (there are multiple messages that can come in, these can be of different types (this is the first child class), and those types have children (grandchildren class)).
I'm just looking for suggestions that may make my life easier.
12-10-2012 04:31 PM
Ok, there is something wrong in this design, if you really need to actually downcast the object to get the final product 😉 Inheritance might not actually be the best solution here. In your own words: "A subset of data is parsed", which would point rather to composition - a subtype and 'grandsubtype' is a part of the message, not the message itself. Lets see how this would work out:
So, BaseMessage receives byte array and calls Type.Parse(), which acts as "factory method" (not as in factory method pattern) of Types. Lets assume that Type1 is parsed. It then calls Type1SubType.Parse() method to finalize the objects creation. Other Types have their "own" TypeXSubType which they use.
Now, when we want to do something, we use the delegation - BaseMessage calls Type.DoSmthng(), which calls SubType.DoSmthng().
Of course, there might be some assumptions made in this design, which your problem doesn't meet. But generally composition and creating parallel classes hierarchies can really save you much effort compared to straightforward inheritance.
Oh, and I really couldn't take it out of my mind...
Yeah, thats basically how it is
12-10-2012 05:25 PM - edited 12-10-2012 05:30 PM
I had considered composition, but was not sure if it was right for this case. After seeing your UML and thinking about it that way, I realized it may be a better option here. I'm still a bit hung up because the parsing isn't really telling me "there is a type message "x" in here" but it is saying "I am type message x." See James post in the linked thread above, as he describes what he feels is the issue here (and I tend to agree). I may attempt it with composition (which may cause reworking of some dynamic dispatching I had) but hopefully it will work out better in the end. I need to review everything first before making any changes.
12-11-2012 03:54 PM
I've read James's post. The decision here lies in your message format only. If the message is like "5 10 15", where 5 means "system message", 10 means "error" and 15 means "burning PXI", then it clearly leads to my suggestion, where you divide the message into parts. This way you can really give every class you create one and only one meaning (i.e. you'll have different hierarchy for first part, other for second part, and other for third part of the message). If you go James's way, this would probably be easier to implement at first, but you'll end up with very large class tree. And large class trees are generally harder to mantain than multiple smaller trees (if designed properly).