简体   繁体   English

C#类设计问题以使其可测试

[英]C# classes design questions to make it unit testable

I've a scenario which is explained with the help of the following code 我有一个场景,下面的代码可以帮助解释

namespace SyncDemo
{
    public interface IProcessorA
    {
        void FunctionA(int a);
        void FunctionB(string b);
    }
    public interface IProcessorB
    {
        void FunctionA(int a);
        void FunctionB();
    }
    public interface IRepositoryA
    {
        void Add();
        void Delete();
    }
    public interface IRepositoryB
    {
        void Add();
        Void Delete();
    }

    public class ProcessorA : IProcessorA
    {
        private readonly IRepositoryA _repositoryA;

        public ProcessorA(IRepositoryA repositoryA)
        {
            _repositoryA = repositoryA;
        }

        public void FunctionA(int a)
        {
            //business logic work
            _repositoryA.Add();
        }

        public void FunctionB(string b)
        {
            _repositoryA.Delete();
        }
    }

    public class ProcessorB : IProcessorB
    {
        private readonly IRepositoryA _repositoryA;
        private readonly IRepositoryB _repositoryB;

        public ProcessorB(IRepositoryA repositoryA, IRepositoryB repositoryB)
        {
            _repositoryA = repositoryA;
            _repositoryB = repositoryB;
        }

        public void FunctionA(int a)
        {
            //do the same business logic work as in FunctionA in Class ProcessorA
            _repositoryA.Add();
        }

        public void FunctionB()
        {
            _repositoryB.Delete();
        }
    }

    public class RepositoryA : IRepositoryA
    {
        //this repository is responsible to talk with 'A' data source
        public void Add()
        {
            throw new NotImplementedException();
        }

        public void Delete()
        {
            throw new NotImplementedException();
        }
    }

    public class RepositoryB : IRepositoryB
    {
        //this repository is reponsible to talk with 'B' data source
        public void Add()
        {
            throw new NotImplementedException();
        }

        public void Delete()
        {
            throw new NotImplementedException();
        }
    }
}

There is a common functionality wherein i have to apply the same business logic in both the processors before calling the repository. 有一个共同的功能,其中我必须在调用存储库之前在两个处理器中应用相同的业务逻辑。 Also, there are other methods in ProcessorA and ProcessorB which call the repository directly as there is no business logic to be applied. 另外,由于没有要应用的业务逻辑,因此ProcessorA和ProcessorB中还有其他方法可以直接调用存储库。

My dilemma is where to put the common business logic functionality code. 我的难题是在哪里放置通用业务逻辑功能代码。 Should i create a separate class with that common functionality in a static method or shall i create a separate class which takes the responsibility of talking with the RepositoryA and do the business logic as well? 我应该在静态方法中创建一个具有该通用功能的单独的类,还是应该创建一个单独的类来负责与RepositoryA进行通信,并且还要执行业务逻辑?

Any ideas and help is appreciated. 任何想法和帮助表示赞赏。 Thanks in advance. 提前致谢。

Suyog. Suyog。

If you are following Object-Oriented Design Guidelines like the SOLID Principles and other principles like DRY etc. you should be aware of the Single Responsibility Principle (SRP) which states that a class should have only one responsibility (purpose) and therefore only one reason to change. 如果您遵循诸如SOLID原则之类的面向对象设计准则以及诸如DRY等之类的其他原则,则应了解单一责任原则(SRP),该原则规定一类应仅承担一项责任(宗旨),因此只有一种理由改变。

Now I don't know the concrete context you are working in but according to the SRP you have to decide if that responsibility of common functionality you are talking about belongs in a separate class or not. 现在我不知道您正在使用的具体上下文,但是根据SRP,您必须确定您正在谈论的通用功能的责任是否属于单独的类。 There are also several Design Patterns like the eg the Template Method Pattern or maybe the Strategy Pattern that you can use to structure your code in a way that it is following the Don't-Repeat-Yourself Principle (DRY). 还有一些设计模式,例如模板方法模式策略模式 ,您可以使用它们遵循“请勿重复自己的原则”(DRY)的方式来构造代码。

For myself, I would first check if I can eliminate one of the repository interfaces and one of the processor interface: they seem rather similar, eg the IProcessorB interface just has an additional string parameter in its FunctionB that separates it from IProcessorA . 对于我自己,我首先要检查是否可以消除存储库接口之一和处理器接口之一:它们看起来很相似,例如IProcessorB接口在其FunctionB中仅具有一个附加的string参数,以将其与IProcessorA分开。 Can you avoid this (maybe by injecting the string to the constructor of the concrete class that implements this interface) and thus form a common interface that is implemented by several classes? 您是否可以避免这种情况(可能是通过将字符串注入实现该接口的具体类的构造函数)而形成一个由多个类实现的公共接口? This would for example allow you to introduce the Decorator Pattern into your code. 例如,这将允许您在代码中引入Decorator Pattern

Anyway these are just guesses by me as I don't know the concrete code you are working on. 无论如何,这些只是我的猜测,因为我不知道您正在使用的具体代码。 If you have any further questions, please feel free to ask. 如果您还有其他疑问,请随时提问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM