views:

190

answers:

1

Hi all,

I am having a little bit a class design issue. I will outline the three patterns I am considering.

Example 1:

Class MyObject
{
    public MyObject(IWrapper wrapper,string name)
    {//set properties.}

    public Void Declare()
    {
        //Some COM stuff with IWrapper
     } 
}

Use:

MyObject testobj = new MyObject(fakewrapper,"test");
testobj.Declare();

Example 2:

Class MyObject
{
    public MyObject(IWrapper wrapper,string name)
    { //set properties.}

    public MyObject Declare()
    {
        //Some COM stuff with IWrapper
        return this;
     } 
}

Use:

MyObject testobj = new MyObject(fakewrapper,"Test");
testobj = testobj.Declare();

Example 3: Using private constructor

Class MyObject
{
    private MyObject(IWrapper wrapper,string name)
    {//set properties.}

    public static MyObject Declare(IWrapper wrapper,string name)
    {
        //Some COM stuff with IWrapper
        return new MyObject(wrapper,name);
     } 
}

Use:

MyObject testobj = MyObject.Declare(fakewrapper,"Test");

My main questions are; Which one do you think is the better design?
Is it bad practice to hide the constructor in favor of a static factory method?

I am also trying to make this as testable as possible. The only reason I can't seem to make up my mind is because the MyObject class is a wrapper around another object in a COM application.

The problem is that this object has to be declared in the COM application which is what the declare method is doing before any other method can be called, but if I hide the constructor and then add more work to the Declare method I think it will make the rest of the class hard to test, becuase I have to go through the Declare method first.

Cheers.

+1  A: 

Option 3 seems like the cleanest API for your class to me. If you can't really use MyObject until Declare is called, to me it would make sense to wrap the new and Declare into a factory method, to make sure that users of your class don't try to use MyObject without first calling Declare. Factory methods can also help with maintenance down the road.

One way to help with testability might be to wrap the Declare operation in a pluggable "IDeclarer" interface in the class. Your production app would use an implementation of IDeclarer that calls the COM app, while your test code could plug in a mock IDeclarer. Maybe something like this (you'll probably have to tweak this...):

class MyObject
{
    public IDeclarer Declarer { get; set; }

    private MyObject(IWrapper wrapper,string name)
    {
        // set properties
    }

    public static MyObject Declare(IWrapper wrapper,string name)
    {
        //Some COM stuff with IWrapper
        MyObject newMyObject = new MyObject(wrapper,name);
        return Declarer.Declare(newMyObject);
    } 
}

public interface IDeclarer
{
    MyObject Declare(MyObject obj);
}

public class ComDeclarer : IDeclarer
{
    public MyObject Declare(MyObject obj)
    {
        // do COM work
        return comObj;
    }
}

public class TestDeclarer : IDeclarer
{
    public MyObject Declare(MyObject obj)
    {
        // do nothing... or whatever
        return testObj;
    }
}
Andy White