简体   繁体   中英

How to avoid code duplication in c# project

I have a situation where I am using specflow custom plugin. Using specflow custom plugin I have two different projects let's say project_A and project_B. Both the project has their own repository.

Project_A has below class (please find the code snippet) :

public class CustomTestGeneratorProvider : IUnitTestGeneratorProvider
{
    public CustomTestGeneratorProvider (CodeDomHelper codeDomHelper)
    {
        _unitTestGeneratorProvider = new 
        NUnit3TestGeneratorProvider(codeDomHelper);
        CodeDomHelper = codeDomHelper;
    }

    public UnitTestGeneratorTraits GetTraits()
    {
        return _unitTestGeneratorProvider.GetTraits();
    }

    public void SetTestClass(TestClassGenerationContext generationContext, string featureTitle,
        string featureDescription)
    {
        _unitTestGeneratorProvider.SetTestClass(generationContext, featureTitle, featureDescription);
        generationContext.Namespace.Imports.Add(new CodeNamespaceImport("Com.MyOrg.Custom.Core.Feature"));
        generationContext.TestClass.BaseTypes.Add("MyOrgTest");
     }

    public void SetTestClassCategories(TestClassGenerationContext generationContext,
        IEnumerable<string> featureCategories)
    {
        _unitTestGeneratorProvider.SetTestClassCategories(generationContext, featureCategories);
    }

Project_B has below class (please find the code snippet) :

public class CustomTestGeneratorProvider : IUnitTestGeneratorProvider
{
    public CustomTestGeneratorProvider (CodeDomHelper codeDomHelper)
    {
        _unitTestGeneratorProvider = new 
        NUnit3TestGeneratorProvider(codeDomHelper);
        CodeDomHelper = codeDomHelper;
    }

    public UnitTestGeneratorTraits GetTraits()
    {
        return _unitTestGeneratorProvider.GetTraits();
    }

    public void SetTestClass(TestClassGenerationContext generationContext, string featureTitle,
        string featureDescription)
    {
        _unitTestGeneratorProvider.SetTestClass(generationContext, featureTitle, featureDescription);
    }

    public void SetTestClassCategories(TestClassGenerationContext generationContext,
        IEnumerable<string> featureCategories)
    {
        _unitTestGeneratorProvider.SetTestClassCategories(generationContext, featureCategories);
    }

If you look at SetTestClass method in the class has different implementation of logic. This is the only method is becoming maintence for me. Note that both the project do same thing but the user for them are different. At the time of release If I change in project_A I should take care or think about project_B also.

I would like to minimize this maintenance. What should I do to reduce the maintenance?. How to avoid code duplication? in such scenario.

Take all the common parts of the classes, and create an abstract base class from them. Leave the SetTestClass method abstract .
Put this class in a separate dll:

public abstract class TestGeneratorProvider : IUnitTestGeneratorProvider
{
    public CustomTestGeneratorProvider (CodeDomHelper codeDomHelper)
    {
        _unitTestGeneratorProvider = new 
        NUnit3TestGeneratorProvider(codeDomHelper);
        CodeDomHelper = codeDomHelper;
    }

    public UnitTestGeneratorTraits GetTraits()
    {
        return _unitTestGeneratorProvider.GetTraits();
    }

    public abstract void SetTestClass(TestClassGenerationContext generationContext, string featureTitle,
        string featureDescription)

    public void SetTestClassCategories(TestClassGenerationContext generationContext,
        IEnumerable<string> featureCategories)
    {
        _unitTestGeneratorProvider.SetTestClassCategories(generationContext, featureCategories);
    }
}

In project A, add a reference to that dll, inherit this class and provide the relevant SetTestClass implementation:

public class CustomTestGeneratorProvider : TestGeneratorProvider
{
    public override void SetTestClass(TestClassGenerationContext generationContext, string featureTitle,
    string featureDescription)
    {
        _unitTestGeneratorProvider.SetTestClass(generationContext, featureTitle, featureDescription);
        generationContext.Namespace.Imports.Add(new CodeNamespaceImport("Com.MyOrg.Custom.Core.Feature"));
        generationContext.TestClass.BaseTypes.Add("MyOrgTest");
     }
}

And do the same in project B:

public class CustomTestGeneratorProvider : TestGeneratorProvider
{
    public override void SetTestClass(TestClassGenerationContext generationContext, string featureTitle,
    string featureDescription)
    {
        _unitTestGeneratorProvider.SetTestClass(generationContext, featureTitle, featureDescription);
    }
}

Create a separate project with this class and a "base implementation" for the methods. If you need to make a modification exclusively on one use the override to override the method.

Reference: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/override

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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