views:

826

answers:

4

Hello,

I' am a bit stuck on a peice of design which i hope this group can help. I am new to DDD and would like an opinion on how to solve this problem.

I have a Currency Value Object that needs to access a repository to get addditional data to make the class complete. The problem (or design issue) is that new instances of Currency can only be created via the Factory Method.

public class Currency
{
internal Currency()
{
}

public string Name { get; set; }

public static Currency CreateCurrencyFromAlphaCode(string alphaCode)
{
Currency cur = new Currency();
//Needs repository to set name etc
return cur;
}

public static Currency CreateCurrencyFromCountryCode(string countryCode)
{
Currency cur = new Currency();
//Needs repository to set name etc
return cur;
}

public static Currency CreateCurrencyFromCountryName(string countryName)
{
Currency cur = new Currency();
//Needs repository to set name etc
return cur;
}

}

I thought that if i need to inject a repository into the constructor then it will make the factory method pointless?

public class Currency
{
public Currency(IRepoistory repository)
{

}
}

How should i design this class given the dependency on the repository, must i make a param on each of the Factory Methods to accept a repository?

Thanks

+1  A: 

Without knowing some more about the context of your application it's difficult to be certain so forgive me if this is slightly off target, but it seems as though there are two potential issues with your design here.

Firstly you are injecting dependencies into a class that is presumably going to be used in your domain layer. Injecting dependencies into the domain layer or into dependencies of the domain layer is often seen as a symptom of a design flaw somewhere in your application.

Secondly, your currency object is taking on two responsibilities. Firstly it's being a currency (obviously), and secondly it is responsible for the creation of currencies.

To fix these issues, can you break the factory methods out of the currency class into a 'higher' layer of your application? If so you may find that everything starts to get easier as you can inject the repository dependencies into the factory with no problems. This may mean refactoring your domain layer code so you are passing 'ready built' currencies in there rather than currency codes, country codes etc, but I think that isn't a bad thing in itself. The domain layer should presumably care about a 'Currency', not necessarily about a 'Currency Code'.

Steve Willcock
Definitely agree that there is a design flaw :). I think you summary of the solution is very much silmilar to Travis's solution using the factory pattern? If so i commented that factories should have static methods and a private (or internal) constructor. So how should i be passing reference to my repository for DI?
Yes, I guess factory is the wrong term there as it brings to mind the factory pattern - builder is a better term or even as Michael Hart suggests, just a repository with Find or Get methods to return the currency you need.
Steve Willcock
+2  A: 

Why don't you move the currency building outside of the currency class? I don't like the name, but you might try something like CurrencyBuilder. It might look like this:

public class CurrencyBuilder {
  private IRepository repository;

  public CurrencyBuilder() : this(new DefaultRepository()) {
  }

  public CurrencyBuilder(IRepository repository) {
    this.repository = repository;
  }

  public Currency FromCountryCode(string countryCode) {
    string currencyName = repository.GetCurrencyNameByCode(countryCode);
    if (currencyName == null)
      throw new CurrencyCodeException(countryCode + " not found");

    Currency c = new Currency();
    c.Name = currencyName;

    return c;
  }
}

Using this setup, when you call 'new CurrencyBuilder()', it will use your default repository instance. However, for testing, you can pass a mock repository into the constructor.

Hope that helps, and stick with it. For what it's worth, this is not a great example where DI will help a lot. So, if you feel unsatisfied at the completion of this task, don't give up on DI straight away. As you get more comfortable with it, it's usefulness will become more apparent.

Travis
Yes, stick with DI, it can really change the way you approach programming!
Steve Willcock
Thanks. I think you are using the factory pattern here? if so do we need static methods FromCountryCode etc? And if the methods are static how do you manage the (what would become) private constructor. i.e where do you inject the repository?
It's not really a factory. With factory, you're returning a concrete implementation of an abstract class. Here, we're just using normal class to return certain types of information.In this case, I would not make any of the methods static - there's not really any need to do that here. The dependency injection comes in the second constructor of the CurrencyBuilder. For example, you could build FakeRepository that derives from IRepository and have it return known values. This lets you test CurrencyBuilder without having to use the database.
Travis
Also, using the pattern above, you can 'inject the IRepository' into the CurrencyBuilder using the CurrencyBuilder(IRepository repo) constructor. This is how you could change the implementation to use an XMLFile or just keep all of the data in memory, as discussed below. If I were building this, I would create a list of country objects, and then create an object that held country codes in a hashtable, and use the country code as the key.
Travis
A: 

If "repository" means "relational database", I'm not sure it should be your first choice here. After all, the number of currency codes is relatively static. They won't be changing that often, so I wouldn't think that you should have to pay the roundtrip to the database every time you create one.

I wonder if either a static data structure that's loaded on start-up from either a database or text file would be a more efficient choice. It'd be one less dependency as well.

duffymo
Yep aggreed that the data is very static. The data source could be a database or xml file. Haven't decided how yet :). It could be entirely possible that we hard code the classes. Again don't really know yet. It may well work out that we use some kind of strorage mechanism and use caching to spped things up.
I think in this case static, hard-coded data would be a defensible way to go. Caching - why? A static, read-only map that would allow you fast lookups is all you need. Reading from XML or RDBMS on creation is immaterial. Either one will work. So will a flat file.
duffymo
+3  A: 

I responded to this on the DDD list where you asked it as well, but I'll repeat my concerns here too.

I think you're getting the roles of a Factory and a Repository confused here.

Your methods named, for example, CreateCurrencyFromAlphaCode, actually look like they should be, for example, FindCurrencyByAlphaCode and they should exist in a Repository, not in a Factory. A Factory is used for creating objects that don't already exist in your persistence layer (or for instantiating objects from data you've already received from your persistence layer).

Also, your AlphaCode actually sounds like an Identity, so, if you did want to continue retrieving Currencies from your persistence layer, then I'd suggest your Currency is most likely not a Value Object, but rather an Entity.

Without knowing more about your domain, it's hard to know if this is a correct design decision or not. I'm inclined to think that duffymo's response would serve you better and then you wouldn't need to worry about fetching from a data store each time at all.

Michael Hart
Factories can and should be used for creating spanking new objects or reconstituting from the repository right? So they should go hand-in-hand? As for Currency being an Entity, i wonderd myself if i really made the right choice, but i asked myself do i really care about the identity of the currency, and the answer was no (for now). Appreciate any more counter arguments you may have about my design decsions :)
When you say "reconstituting from the repository", then I'm pretty sure you're on the wrong track. Do you have some references that you got this from?You could, in a finder-method *in your Repository itself*, use a Factory to reconstitute an object that you've retrieved data for - but the Factory would require that you had retrieved all the data to reconstitute the object (ie, all of countryCode, alphaCode and countryName) - unless you're doing lazy loading, but that's beyond the scope of your question.
Michael Hart
ok - i think i'm following you now. I got my reference from Eric Evans book, the chapter on Factories. So what i really need to do is pass the sql result set to the factory so it can reconstitue the object. The flaw in my design was that i am trying to create an object in my factory method which didn't contain ALL the info it needs to build the Currecny Object.
please correct me if my thinking is right or wrong...i am a complete DDD newbie and appreciate any advise
Yep - I think you've got it now. The only other thing I'd say is that I'd advise against passing an SQL result set around though as this would tie your Factory to your persistence layer. In this simple case, I wouldn't use a Factory at all, but would just extract the parameters out of each result row and use them in the Currency constructor. Factories are normally used for more complex object creation, or for when polymorphism is required, etc.
Michael Hart