4
votes

I've just refactored out a new domain class from a presenter class but I can't figure out where to instantiate it.

This is part of a larger ongoing refactoring effort with a poorly maintained legacy project.

The Presenter is currently being created by the view's OnLoad event and the view is passed as a parameter in the constructor. All public methods in the presenter are parameterless and return void. They communicate with the view using public properties of the view.

The view, being essentially a humble form depends entirely on the presenter for everything.

This is the typical Passive View pattern and I'd like to continue to adhere to it. Which brings me to my dilemma. I need to create an instance of my new domain object for the presenter to use.

  • If I pass it through the constructor then the view has to create it and gains an unnecessary dependency.
  • If I create it anywhere within the presenter, I can't replace it with a mock object in my unit tests.
  • If I make it a public property of the presenter then I introduce a creation order dependency on the presenter methods where it is used and I still haven't solved what external class gets responsibility for creating it.

I am not currently using any dependency injection frameworks. While I'm interested it using one in the future the source code is still much to fragile to introduce a third party framework into the mix.

I'm open to any suggestions.

3

3 Answers

2
votes

I have it already done !!! Have a look here in my repository. My choice here is to use constructor ... satisfying the greediest I'm sure that presenter is Up. In your case you can provide from view specific impl for dependencies.

have fun :)

1
votes

I found a much simpler solution. Here's an example of my original class:

public Presenter(IView view)
{
    this.View = view;
}

I wanted to pass my new dependency as a constructor argument but didn't want to add this dependency to my view as well. Constructor chaining to the rescue!

public Presenter(IView view):this(view, new Dependency()){}

public Presenter(IView view, IDependency dependency)
{
    this.View = view;
    this.Dependency = dependency;
}

Now the production code continues to use the original interface while the unit tests use the new one passing in mocks for both the view and dependency. If the number of dependencies continues to grow some refactoring will be needed but for the immediate future this is an ideal solution.

0
votes

I'd go for a repository or a factory for now. It would be testable immediately. In the future, you can replace its implementation to go to a DI library.

public class DomainObjectsRepository
{
    /// <summary>
    /// can not be instantiated, use <see cref="Instance"/> instead.
    /// </summary>
    protected DomainObjectsRepository()
    {

    }

    static DomainObjectsRepository()
    {
        Instance = new DomainObjectsRepository();
    }

    public static DomainObjectsRepository Instance { get; set; }


    public virtual ICustomerDao GetCustomerDao()
    {
        return new CustomerDao();
    }
}

public class DomainObjectsRepositoryMock : DomainObjectsRepository
{
    public override ICustomerDao GetCustomerDao()
    {
        return new CustomerDaoMock();
    }
}