It does have benefits
- Persist simple data types with little (attributes) or no work.
- Create objects that rely on Constructor Initialization.
- It heavily uses reflection which may be a problem if you require very high performance.
- It ignores fields or properties which are user defined types.
.norm could address the issue of working with graphs of objects; however, the complexity may not be worth the pay off. Consider for example you have a Foo class that has a Bar property. Persisting Foo and Bar is simple. But, if Foo takes a Bar as a constructor argument things become much more complicated. Now, to return an instance of Foo you need an instance of Bar registered to DataGateway.
There are ways to work around this issue.
- Simply add a default constructor.
- Before returning an object (Foo) you could register all it's properties that are user defined types (Bar). However, there is no way to ensure that the object that was persisted as the property of type Bar was also the constructor argument of type Bar.
- Change Foo's dependency from a Bar to a BarFactory. But, now each user defined type will also need a factory. Register the BarFactory to satisfy Foo's constructor at creation time. This could clutter your domain. .norm is not supposed to be intrusive enough to force design issues.
- Add a boolean to the ColumnAttribute that specified if the decorated property (or field) should be registered as a dependency.
Remaining unfriendly to object graphs may be a superior alternative. .norm can be used as a base for a custom data mapping layer. Again, .norm isn't a silver bullet. .norm is a simple framework that automates simple tasks. When situations become more complex, classes can wrap .norm functionality and enforce the persistence/finding logic.
Consider this applied to the above Foo and Bar problem. Foo and Bar can both be persisted by .norm. But, Foo needs a Bar instance as a constructor argument. If you wrote a FooMapper class it could handle Foo persistence and persistence all of the child objects of Foo. Additionally, FooMapper could create (via .norm) or get from a factory the Bar dependency, register it with DataGateway and then return the Foo class correctly hydrated. Additionally, using FooMapper to delete could ensure that the necessary child objects are also removed.
Regardless of implementation, abstracting the dependency resolution to another class clearly has benefits. The alternative relies on .norm to make complex decisions (which increases the likelihood of mistakes).
Does this mean that .norm will not support object graphs? Absolutely not. If object graph comaptibility is required to increase adoption it will clearly be added. But, not until it's clear this is a widely requested feature.