views:

67

answers:

2

I have XML files that are representation of a portion of HTML code.
Those XML files also have widget declarations.
Example XML file:

 <message id="msg">
   <p>
     <Widget name="foo" type="SomeComplexWidget" attribute="value">
        inner text here, sets another attribute or 
        inserts another widget to the tree if needed...
     </Widget>
   </p>
 </message>

I have a main Widget class that all of my widgets inherit from.
The question is how would I create it?
Here are my options:

  1. Create a compile time tool that will parse the XML file and create the necessary code to bind the widgets to the needed objects.
    • Advantages:
      • No extra run-time overhead induced to the system.
      • It's easy to bind setters.
    • Disadvantages:
      • Adds another step to the build chain.
      • Hard to maintain as every widget in the system should be added to the parser.
      • Use of macros to bind the widgets.
      • Complex code
  2. Find a method to register all widgets into a factory automatically.
    • Advantages:
      • All of the binding is done completely automatically.
      • Easier to maintain then option 1 as every new widget will only need to call a WidgetFactory method that registers it.
    • Disadvantages:
      • No idea how to bind setters without introducing a maintainability nightmare.
      • Adds memory and run-time overhead.
      • Complex code

What do you think is better? Can you guys suggest a better solution?

+1  A: 

I am not sure about the variants you've posted, but the easiest approach (not the most efficient, more like "get-it-done" approach) would be writing your loading wrapper for boost::serialization library.

In this case you would have to call to your deserializing routine, point the file (or it's mapped part) and retrieve a constructed object that can be registered in your widget container.

Note that you probably won't need to write the appropriate saving (serializing) routine, only the loading one.

Also note that you could combine some easy (maybe self-implemented) parser with your deserializing routine, so that, for example the first one grabs the code related to your Widget and the second one constructs an object from it.

Kotti
Hmm that might be a good idea. Is serialization a header only library? Can you show me a code snippet that does what I asked? Would I need to add a loading wrapper for each Widget? Also what are the advantages of this method? What are the shortcomings?
the_drow
1) It's not, you would have to link appropriate static library 2) Not so simple, because if you wish to save your current xml format, you would have to write specialized method for parsing YOUR xml file, if you agree to use *boost* xml-files, it would be much easier. 3) You would probably have something like `widgets.Add(Deserialize("file.xml"));` if you write some simple wrappers 4) Advantages of serialization technique are discussed all over the web and here they remain. Main of them is that you won't have to have some external tool and also writing standard serialization code is pretty fast
Kotti
5) Shortcomings are also obvious - having static libraries (especially in `boost` case could be a pain in the ass; the speed (if talking about `.xml` files, binary serialization is much faster) isn't enough for serializing / deserializing giant objects; also, the format of boost-xml-serialized objects is not as obvious as the xml code you've posted (but still remains editable and somewhat easy to understand)
Kotti
@Kotti: The question is would I need to write a serialization function for every widget in my system? Not all widgets share the same setters.
the_drow
@the_drow *If your `Widget` class is designed properly, then the answer is no (probably only for **absolutely** different types of widgets)*. Serialization simply means storing every POD data for the class and invoking the serializing routine recursively for every class member if it's not POD. Note that `boost::serialization` provides simple serialization wrappers for `STL` containers, `boost` containers and many other yummy things.
Kotti
@Kotti: All widgets are absolutely different by behavior and attributes. It is their nature.
the_drow
@the_drow Probably, this wasn't the best word, I should've said *different in serialization terms* - for example, when different widgets have some non-obvious pointers to other widgets, which again have them. Or if you're using non-trivial (self-implemented) containers, or you also want to serialize function objects which don't share some superclass. Probably there are some other situations where the serialization would be hard, but *hard* here means *not easy to implement, but obviously possible*.
Kotti
@the_drow I also think you should study the `boost::serialization` docs (or even some alternative library) and decide if it's suitable for your case
Kotti
@Kotti: Would you say that implementing an external tool that is added to the build chain is a better idea in terms of complexity? It is much easier to write code that sets the attributes and creates the widget.
the_drow
@the_drow It may be a good idea, *the Qt works the following way.* I've never done this before and I do think you would need to play a lot with macro / etc, but I can say that it's better than widget factory (in terms of code complexity).
Kotti
@Kotti: So which one is a better idea?
the_drow
@the_drow Tool.
Kotti
@Kotti: Thanks for your help. Can you post another answer and I'll mark it as accepted?
the_drow
+1  A: 

Create the tool, include it into your build steps and everything will be fine.

See comments to my previous answer for additional details.

Kotti