1

Here's a scenario I've encountered variations of on many occasions.

Imagine an XML feed which displays data about three different types of event: concerts, plays and movies. Each has a different set of parameters. We want to scrape this information and store it for our own purposes. So we create a database which has application data and three tables for this data which we'll call event_concert, event_play and event_movie. We stick an ORM over the top.

Every hour we poll the feed, looking for new data, and saving it in our database. Because our ORM creates typed objects, there are essentially two ways we can do this.

First, write three separate functions, one for each object type, which create and populate the necessary object, and put it in the database. This is clean and easily understandable. But it's more code to write and it's not necessarily the best for maintenance, since new functions muse be added to deal with new object types and there's a risk of duplicated code.

Second, write a single loop which uses reflection various functions from the ORM context to iterate over the object types (using a fixed prefix like event_ to recognize them), and then iterates over the properties to populate them before saving to the Db. This is messy and hard to understand, but done right it should be a fire-and-forget option that will semi-automatically pick up and deal with new object types with a minimum of fuss.

In this example it's easy to go with the first option since there are only three objects to save. But what if there's five? Or fifty? Or more? Suddenly handling all those different objects with their own custom functions doesn't seem so attractive any more.

Is there any other approach or design pattern which achieves a similar outcome and is both clean and capable of dealing with lots of object types?


Here's an example of what I mean in pseudocode.

If we treat the objects as different types:

GetAndInsertConcerts();
GetAndInsertMovies():
GetAndInsertPlays();
// if we need a fourth object type, we'll need to add a new function

public void GetAndInsertConcerts()
{
    var xmlConcerts = GetObjectsFromXML("Concerts");

    foreach(var xmlConcert in xmlConcerts)
    {
        Event_Concert c = new Event_Concert(xmlConcert);
        repository.InsertAndSave(c);
    }
 }
 // the functions for plays and movies will repeat this structure

And the second approach:

string[] eventTypes = repository.GetTablesStartingWithEvent();

foreach(string eventType in eventTypes)
{
    string xml = GetXmlForEventType(eventType);
    // BuildObjectFromXml function is reflection based, likely hard to code & to follow
    var obj = BuildObjectFromXml(xml);  
    repository.InsertAndSave(obj);
}

Worth repeating - the boilerplate in the first approach is fine if you're dealing with a handful of object types you don't expect to change. But writing repeat "get and save" functions for a lot of different object types is going become tiresome.

  • 2
    Not sure if I understood your problem. Supposing you already have a ORM engine (eg: hibernate), you can just populate some object A, and call the "saveOrUpdate" function from your ORM (which will handle the typing). I don't understand the usage of reflection here, since the ORM is exactly a mapping between your object and the table in DB; once you define your mapping, you just pass some object to the persistence function and the saving to DB is done. – Emerson Cardoso Jan 17 '18 at 17:32
  • Maybe you could provide some example of replicated code that you want to avoid. – Emerson Cardoso Jan 17 '18 at 17:34
  • "This is messy and hard to understand" is anathema to "deal with new object types with a minimum of fuss" – Caleth Jan 17 '18 at 17:34
  • It sounds as if you're re-inventing what your ORM already does very well. – Robert Harvey Jan 17 '18 at 17:53
  • @EmersonCardoso Thanks for looking - have provided an example. – Matt Thrower Jan 17 '18 at 20:53
2

... done right it should be a fire-and-forget option that will semi-automatically pick up and deal with new object types with a minimum of fuss.

Really? It sounds to me that the elephant in the room is impedance mismatching.

Your scenario has two databases: the first I assume to be owned by someone else; you have access to it only via exported XML. The second you own, and access with the ORM. If the schema of the first database changes, how do you detect the change? The fire-and-forget strategy seems like it would either silently corrupt your database or it would start throwing exceptions which you haven't planned to handle.

Your ORM works either by reflection or by generated code. Your question is how to handle the mapping from the XML to objects. For maintainability, the answer is surely that if your ORM uses reflection then you should use reflection, and if your ORM uses generated code then you should use generated code. That way the maintainance programmer has to deal with fewer inconsistencies.

Either way, I would use a schema for the XML (writing one myself if the supplier of the data doesn't supply one) and add compile-time and run-time checks that the schema of the XML matches the schema of the ORM, as well as a run-time check that the XML received matches the schema. In case of mismatches you want some notification: I would fail compilation in the compile-time check and send myself an e-mail in the run-time checks.

Finally, the list of object types to handle should be in a config file. Reconstructing it from the database means that you can't decide to stop handling a given type of event without losing existing data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.