views:

123

answers:

3

I'm new to DDD so please forgive me if I'm not using the terms correctly.

I am Using C# MS/SQL and NHibernate.

I have a class call Payment and this payment has a PaymentCurrency each of these is an entity in the database.

OK. In my Domain Model I want to be able to create Payment as Either

Payment p = new Payment( 100 ) // automatically uses the default currency (defined in the db )

or

Payment p = new Payment( 100, Repository.GetCurrency( "JPY" ) ) // uses Yen defined in the db.

But it seems to me that in order to initialize my Domain Object with the dfault currency I need to pollute the domain model with knowledge of persistance. i.e. before I can completed the default Payment Constructor I need to load the Default Payment object from the db.

The constructor I visualize is somehting like

public Payment( int amount ) {
   Currency = Repository.LoadDefaultCurrency();  // of cource defualt currency would be a singleton
}

public Payment( int amount, Currency c ) {
   Currency = c; // this is OK since c is passed in from outside the domain model.
}

Thanks for your advice.

A: 

Your answer would be dependency injection.

Make use of it and don't polute model with configuration. If you need to create a payment with required Amount and Currency - just do exactly that:

var currency = injectedCurrencyRepository.GetByName("JPY");
var p = new Payment(100.00m, currency);

Do not assume default currency.

or at the worst end you can add inteface:

public interface ICurrencyProvider {
   Currency GetCurrency();
}
// Implment the default:
public class DefaultCurrencyProvider : ICurrencyProvider {
   public Currency GetCurrency() {
      return new Currency("AUD");
   }
}

// And the Payment constructor will look like:
public Payment(decimal amount, ICurrencyProvider currencyProvider) {
   c = currencyProvider.GetCurrency();
}

so you can INJECT (using Windsot, Unity or whatever) that currency provider by default into method where you instantiate Payment:

var p = new Payment(100.00m, defaultCurrencyProvider);
Dmytrii Nagirniak
-1 from me - I believe there's another way to get currency information without having to resort to persistence or dependency injection.
duffymo
+2  A: 

I don't think there's a perfect solution to this, but you can avoid putting the persistence code into domain classes by having the default currency (and similar properties) stored on some other class (eg. "DomainDefaults") and have it initialised from another piece of code that logically sits "above" the domain objects. Of course, you'd have to make sure that initialisation code is called before any domain objects can be created. It should probably throw an exception if not initialised, so you can at least catch this easily.

So the constructor becomes

public Payment( int amount )
{
   Currency = DomainDefaults.DefaultCurrency;
}

And somewhere soon after you initialise NHibernate you'd call:

DomainDefaults.DefaultCurrency = Repository.GetCurrency("JPY")
Evgeny
+1  A: 

I don't see why this has to have anything to do with persistence at all.

If I were writing this in Java, I'd get the default currency from the Locale for the application.

This SO question tells me that CultureInfo is the C# equivalent. Maybe you should try that in your design, and leave strings like "JPY" and persistence out of it.

duffymo
That is a good idea... for the case of currency but it doesn;t really address the base issue. All you are really doing is moving persistnce from a database to an OS registry repository. So, if for example you moved to Unix, the locale storafe would be different and hence I'd need to change my domain model...
thrag
Move to Unix? I'll assume you're thinking of Mono. I'm more familiar with Java, so I assumed - perhaps incorrectly - that Locale/Culture would be something I would get from HTTP headers set by the client's browser if I were writing a web app.
duffymo