views:

51

answers:

3

I'm working on a project where I have to take data from one source and translate/tweak it so that it can be properly consumed by a different source, in this case, the database. I imagine this is a fairly common problem, and while I believe I'm off to a good start, I'm stuck as to how best to implement the middle part of the solution that is responsible for parsing the original data and making that data available to the next part of my process.

Let's say that I have a web service on my company's server that is responsible for receiving a sales order provided by a third-party vendor. After the web service is called by the vendor, I should have a strongly-typed object called MyVendor.CustomOrder. I am then responsible for parsing the MyVendor.CustomOrder instance to get the data properly formatted as an "order" in my company's system.

I already have stored procedures for inserting data into the database and I've even created helper methods to communicate with stored procs. I also have interfaces such as IOrderHeader, IOrderPayment, etc., to exist as a "contract" for the data to be consumed by those helper methods.

I'm trying to figure out if a good pattern exists for parsing the data in the original MyVendor.CustomOrder object to provide data for the IOrderHeader et al interfaces. Here's how I might visualize how the pieces come together (in a marginally helpful ASCII diagram) :

________________________________
|                              |
| Web Service to receive order | 
|                              |   
|  __________________________  |
|__|                        |__|
   |  MyVendor.CustomOrder  |
   |________________________|

               ||
               ||
               \/
   __________________________
   |                        |
   | ?????????????????????? |
   |          Parse         |
   |  MyVendor.CustomOrder  |
   |   and pass data to     |
   |        next step       |
   | ?????????????????????? |
   |________________________|

               ||
               ||
               \/
        _________________________   
        |                       |
________|________               |
| IOrderHeader  |               | 
|_______________|   Methods     |
________|________     to        |
| IOrderPayment |   Add Data    |
|_______________|     to        |
________|________   Database    |
| IOrderDiscount|               |
|_______________|               |
________|________               |
|  IOrderItem   |               |
|_______________|               |
        |_______________________|

               ||
               ||
               \/
   __________________________
   |                        |
   | Data Access Layer,     |
   | Database, etc....      |
   |________________________|      

The only idea I have thus far is to make one giant class that handles everything, possibly like so:

public class MyVendorCustomOrderParserAndDatabaseUpdater
{
     private IOrderItem _IOrderItem;
     //other private interface instantiations

     public MyVendorCustomOrderParserAndDatabaseUpdater(
                MyVendor.CustomerOrder customOrder)
     {
          ParseOrderIntoInterfaces(customOrder);
     }

     private void ParseOrderIntoInterfaces(
                 MyVendor.CustomOrder customOrder)
     {
          //Parse customOrder into _IOrderItem, etc.
     }

     public bool SendOrderToTheSystem()
     {
         //Call the helper methods with the data
         //from the private _IOrderHeader, etc. objects
         //to update "the system"
     }
}

I would then consume this object with some code like this:

... = new MyVendorCustomOrderParserAndDatabaseUpdater(
        customOrder).SendOrderToTheySystem();

I'm interested to know if there are better patterns for solving this problem of getting data from one format so that it can be consumed properly in a different environment.

A: 

So you have a class representing an order as your third party vendor sees it, and a class representing an order as your domain model sees it, correct? I don't know if this helps, but in the past I've done things like that either by attaching an extension method to my classes (DomainClass dc = ThirdPartyClass.toDomainClass()) or by having a constructor in one class that can take an instance of it's sister class and parse it (DomainClass dc = new DomainClass(ThirdPartyClass) ). I don't have translation logic in the same place that my persistence logic lives. I would end up with something like vendorRepository.SaveNewVendor(new DomainClass(ThirdPartyClass)) or vendorRepository.SaveNewVendor((ThirdPartyClass.toDomainClass())

I dunno if that is of any value to you or not.

ThatSteveGuy
+1  A: 

This seems a good case for the adapter pattern.

Convert the interface of some class b into an interface a that some client class c understands.

If you receive orders from different third-party vendors you would create one adapter for each vendor and then you could even employ a factory pattern to create the correct adapter for a given vendor.

João Angelo
A: 

In a sense, what you're doing is somewhat similar to serialization. For example, XmlSerialization converts an object to XML, then back into an object. You want to convert a MyVendor.CustomerOrder into a set of objects in your system (OrderHeader, etc.), then back into the original object.

If you follow that pattern, you would have a mapper object which knows how to convert from one "format" to the other. XmlSerialization's mapper object is the XmlSerializer object (configured for the particular type of object). You could implement an equivalent mapper object, which know how to marshal the data back and forth between the two formats.

mikemanne
That's an interesting observation. I'm not it exactly matches my model since my data only needs to be converted in one direction and I'm not needing to do string serialization, but I can see where there might be similarities.
Ben McCormack
It's definitely similar at an "abstract" level, but kinda different "when the rubber hits" the road. :) In any case, I didn't realize you were doing the conversion only in a single direction. With that in mind, I think a "mapper" class would still be a good way to handle the conversion. But you're right, it makes the analogy a little less direct. Cheers!
mikemanne