views:

576

answers:

3

I have been utilizing the Fowler patterns for domain models with a Data Mapper and have run into some confusion on how to implement the creation portion of CRUD. I can't utilize existing ORM technologies as the underlying data sources are custom systems. The area that’s troubling me is how to call the underling ORM when I need to create a new object. My Domain Layer has no visibility of my ORM, with the exception of my finders.

I’m not sure if I’m on the right track but the following are the only options I can see:

  1. Handle the create functions the same way the Fowler finders are done. Create an interface in the Domain Model layer for the creation methods on the ORM classes. Then have the Domain Model call a DI container and instantiate an instance of the ORM class based on the interface.

  2. During hydration of object A in the ORM attach a delegate pointing to the creation method on the ORM for object B. Requiring domain object A is hydrated you could call the delegate on object A which would invoke the create method on object B's mapper.

  3. ???

I must be missing something, as this can’t be that complex. Any help would be much appreciated.

Thanks

+1  A: 

How about looking at how ORMs solve this problem? In languages that support dynamic creation of objects "mapping" of how the data relates to domain objects is provided as separate configuration. The classes are created through reflection or a bytecode library. I guess it depends on how general you would like to make the Data Mapper. From what I can gather from the original pattern data-mappers can exist per domain object.

Perhaps you are attempting a general solution. Otherwise it may be about configuring a general-mapper with information about how to build up the objects using reflection.

That is to day the ORM layer can deal with Strings that represent the CanonicalClass name + a list of methods to expect on those classes.

Passing an object to be persisted the Object can be inspected using this information. Creating an object can be done using reflection using the data from the database. Some ORM solution may not create the object tree in a deep way but instead create proxies for lazy fetching.

andygavin
+1  A: 

If your problem is just mapping from Type A to Type B you might want to consider AutoMapper.

Richard Nienaber
A: 

Re: "how to call the underlying ORM when I need to create a new object"

Have you looked into the idea of AGGREGATE ROOT and the REPOSITORY patterns - they might be helpful.

As a rough summary: AGGREGATE ROOT is an 'entity' that has a globally unique id within the system. Most of the time, these are the only objects that your application will need to be grabbing 'by id'. They are found through a REPOSITORY which is generally initialized to know about the data layers at application start-up / bootstrap.

FACTORIES for AGGREGATE ROOTs are also generally initialized to know about the data layers at application start-up / bootstrap.

The REPOSITORY can then mediate the process of digging up the data for the object in any way it likes. REPOSITORY delegates to the datalayer/mapper to get the raw data and tends to delegate the actual job of object reconstitution over to a FACTORY (class /method) to do the building.The REPOSITORY then returns the newly reconstituted AGGREGATE ROOT object or (collection-of) to the client that invoked the REPOSITORY's find method - i.e the application. The REPOSITORY is the interface to retrieve and save AGGREGATE ROOTs and gives the behaviour of them being stored in-memory.

An application might use a FACTORY directly, however, to create a brand new AGGREGATE ROOT object.

The Factory of an AGGREGATE ROOT has good knowledge about the ORM/Mapper Layers and, upon creation of a brand new entity it might call upon the services of some kind of 'number sequence object' to get its unique id.

AGGREGATE ROOTs are generally the only kinds of domain object that you need to 'Find by Globally Known Id' because any other domain objects are either:

  • throwaway value objects - like a money value, OR
  • 'AGGREGATE ROOT dependent' entities. I.e. objects that have ids that are only unique within the context of an AGGREGATE ROOT which implies that
    • the AGGREGATE ROOT should really be the only thing that needs to find it/use it - internally
    • they can be found by using the ORM Mapper of the AGGREGATE ROOT
    • their ids can be created by the AGGREGATE ROOT that defines its context/scope

Further Reading:

See Domain Driven Design, Eric Evans.

Aggregate Root: http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=domain%20driven%20design&pg=PA147#v=onepage&q=&f=false

Repositroies: http://books.google.co.uk/books?id=7dlaMs0SECsC&lpg=PP1&dq=domain%20driven%20design&pg=PA147#v=onepage&q=&f=false

JW