Interface / Abstract Class Coding Standard

后端 未结 5 783
礼貌的吻别
礼貌的吻别 2021-02-09 06:01

I spotted a proposed C# coding-standard which stated \"Try to offer an interface with all abstract classes\". Does someone know the rationale for this?

5条回答
  •  夕颜
    夕颜 (楼主)
    2021-02-09 06:35

    Test-driven development (TDD) is one key reason why you would want to do this. If you have a class that depends directly on your abstract class you cannot test it without writing a subclass that can be instantiated in your unit tests. If, however, your dependent class only depends on an interface then you can provide an 'instance' of this easily using a mocking framework such as Rhino Mocks, NMock, etc.

    Ultimately I think it's going to be down to how you ship your product. We only ever ship binaries and customers never extend our work. Internally we have interfaces for pretty much everything so classes can be isolated completely for unit testing. This offers huge benefits for refactoring and regression testing!

    EDIT: updated with example

    Consider following code in a unit test:

    // doesn't work - can't instantiate BaseClass directly
    var target = new ClassForTesting(new BaseClass());      
    
    // where we only rely on interface can easily generate mock in our tests
    var targetWithInterface = new ClassForTestingWithInterface(MockRepository.GenerateStub());
    

    where the abstract class version is:

    // dependent class using an abstract class
    public abstract class BaseClass
    {
         public abstract void SomeMethod();
    }
    
    public class ClassForTesting
    {
        public BaseClass SomeMember { get; private set; }
    
        public ClassForTesting(BaseClass baseClass)
        {
            if (baseClass == null) throw new ArgumentNullException("baseClass");
            SomeMember = baseClass;
        }
    }
    

    and the same stuff but using interface is:

    public interface ISomeInterface
    {
        void SomeMethod();
    }
    
    public abstract class BaseClassWithInterface : ISomeInterface
    {
        public abstract void SomeMethod();
    }
    
    public class ClassForTestingWithInterface
    {
        public ISomeInterface SomeMember { get; private set; }
    
        public ClassForTestingWithInterface(ISomeInterface baseClass) {...}
    }
    

提交回复
热议问题