如何在类后面隐藏逻辑以提高方法的可读性并重构类以遵循SRP? [英] How to hide logic behind a class to improve readability of method and refactor class to follow SRP?

查看:97
本文介绍了如何在类后面隐藏逻辑以提高方法的可读性并重构类以遵循SRP?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种算法可以为实体创建一个版本,然后将该版本保存到下面的2个实体中:

I have an algorithm to create a version for an entity and then I save that version against below 2 entity:

1)变体

2)类别

interface IEntityVersion
{
    string GetVersion();
}

public class EntityVersion : IEntityVersion
{
    public string GetVersion()
    {
        return null;
    }
}

public interface IVariant
{
    void Process(Variant model, string connectionString);
}

public abstract class BaseVariant : IVariant
{
    private readonly IEntityVersion _entityVersion = new EntityVersion();

    public void Process(Variant model, string connectionString)
    {
        try
        {
            Transform();
            string variantVersion = _entityVersion.GetVersion();
            using (var myConnection = new SqlConnection(connectionString))
            {
                myConnection.Open();
                using (var transaction = myConnection.BeginTransaction())
                {
                    try
                    {
                        VariantRepo.UpdateVariantVersion(
                          myConnection,
                          transaction, model.VariantId, variantVersion);

                        CategoryRepo.UpdateCategoryVariantMapping(
                                     myConnection,
                                     transaction, model.CategoryId, variantVersion);

                        transaction.Commit();
                    }
                    catch (Exception)
                    {
                        transaction.Rollback();
                        DeleteStep1Data();
                    }
                }
            }
        }
        catch (Exception)
        {
            //log error
        }
    }

    protected abstract void DeleteStep1Data();
    protected abstract void Transform();
}

public class Variant
{
    public int VariantId { get; set; }
    public int CategoryId { get; set; }
}

public class VariantRepo
{
    public static void UpdateVariantVersion(SqlConnection sqlConnection,
        SqlTransaction transaction, int variantId, string version)
    {
        //save logic here
    }
}

public class CategoryRepo
{
    public static void UpdateCategoryVariantMapping(SqlConnection sqlConnection,
        SqlTransaction transaction, int categoryId, string version)
    {
        //save logic here
    }
}

我有2种派生类型( AggregateCalculator AdditionCalculator ),每个都有自己的 Transform DeleteStep1Data 方法的实现。

I have 2 derived types(AggregateCalculator and AdditionCalculator) each having their own implementation of Transform and DeleteStep1Data methods.

public class AggregateCalculator : BaseVariant
{
    protected override void DeleteStep1Data() // Is it violating SRP ?
    {
        throw new NotImplementedException();
    }

    protected override void Transform()
    {
        throw new NotImplementedException();
    }
}

public class AdditionCalculator : BaseVariant
{
    protected override void DeleteStep1Data()// Is it violating SRP ?
    {
        throw new NotImplementedException();
    }

    protected override void Transform()
    {
        throw new NotImplementedException();
    }
}

我觉得流程方法工作量很大,并且是否有可能将与版本保存相关的逻辑隐藏在类的后面,从而使处理方法看起来很简单。

I feel like the Process method is doing too much work and if it would be possible to hide version saving related logic behind the EntityVersion class so that the Process method looks simple.

Step1 Step2 是同步的,因此如果 Step2 中有错误,我将调用 DeleteStep1Data 删除保存在 Step1 中的所有数据的方法。

Step1 and Step2 are in sync so that if there is an error in Step2, I call the DeleteStep1Data method to delete all the data saved in Step1.

我也觉得我的2个派生类 AggregateCalculator AdditionCalculator 正在处理多个职责,即运行转换并删除转换过程中存储的数据,尽管我不确定是否正确。

Also I feel like my 2 derived classes AggregateCalculator and AdditionCalculator are handling more than 1 responsibility, i.e. running a transformation and also deleting the data stored during the transformation process, although I am not sure if this is true or not.

是否可以重构上述代码以提高可读性并处理SRP?

Is there a possibility to refactor above code to improve readability and handle SRP ?

推荐答案

试图理解您的问题



您有一个实体...当实体更改时,您想为您的实体创建一个变更版本。对我来说不清楚的是,为什么需要同时针对变体和类别跟踪此更改?

Trying to understand your question

You have an entity... when the entity changes, you want to create a change-version for your entity. What is not clear to me is that why this change needs to be tracked against both variant and category?

让我们假设您的实体是汽车和该实体的类别为:丰田宝马日产。现在,您的实体,例如 id = 123的丰田电晕已更改。为什么需要根据类别跟踪更改?您不能只说id = 123的实体已更改?

Let's assume your entity is car and the categories for that entity are: Toyota, BMW and Nissan. Now your entity, let's say "Toyota Corona with id = 123" is changed. Why do you need to track the change against the category? Can't you just say that entity with id = 123 has changed?

正如我在评论中提到的那样,由于您遗漏了部分逻辑,很难理解您的代码是否违反了SRP,但我可以为您提供一些一般性建议:

As I mentioned in the comment, since you have left out part of your logic, it's hard to understand if your code if violating SRP or not, but I can give you some general suggestions:

您有一个名为 AggregateCalculator ,我认为此类的主要职责是计算发生在 Transform()方法中的聚合。现在,您需要在 Transform()中执行2个步骤。这不一定违反SRP ...因为从更高的层次来看,您的聚合计算器会做一件事:计算聚合。

You have a class called AggregateCalculator, I assume the main responsibility of this class is to calculate aggregation which happens in Transform() method. Now you require to execute 2 steps inside Transform(). This is not necessarily a violation of SRP... because from a higher level, your aggregate calculator does one thing: calculate aggregation.

您可以查找SRP的一般迹象。违反:

You can look for general signs of SRP violation:


  1. 根据尼古拉·马洛维奇的IoC第二定律


任何具有超过3个依赖项的类都应受到SRP
违反的质疑

Any class having more than 3 dependencies should be questioned for SRP violation


  • 如果类的大小太大,则需要对它提出SRP违规要求。

  • If the size of your class is too big, then you need to question it for SRP violation.



    违反DRY



    两个课程: AggregateCalculator AdditionCalculator 分两步进行计算,即 step-1 步骤2 ...,您有一个通用方法:在两个类中均 DeleteStep1Data()可以删除 step-1 ,如果 step-2 失败...我假设 DeleteStep1Data()的实现对于每个此类都是不同的,但我认为它仍然包含重复的代码(不是DRY)。有人可能会说这也违反了SRP,因为 AggregateCalculator 既负责以下内容:计算聚合和镜像数据库事务(很难看到完整的代码,这很难分辨)

    Violation of DRY

    Both of your classes: AggregateCalculator and AdditionCalculator do their calculation in 2 steps, step-1 and step-2... and you have a common method: DeleteStep1Data() in both classes to delete step-1 if step-2 fails... I assume the implementation of DeleteStep1Data() is different for each of these classes, but I feel it still contains duplicated code (not DRY). One may argue that this violates SRP too, because AggregateCalculator is responsible for both: Calculating Aggregation and "Mirroring a DB Transaction" (this is hard to tell without seeing your complete code).

    看来 step-1 step-2 都是数据库事务,因此采用不同的方法将两个步骤都放在一个数据库事务中……例如,您可以编写如下存储过程:

    It appears that both step-1 and step-2 are DB transactions, so a different approach would be to put both steps inside a single DB transaction... for example you can write a stored procedure like this:

    CREATE PROCEDURE AggregateCalculationSP
    AS
    BEGIN
        BEGIN TRANSACTION t1
            BEGIN TRY
                -- do step 1
                -- do step 2
            END TRY
            BEGIN CATCH
                ROLLBACK TRANSACTION t1
            END CATCH
        COMMIT TRANSATION t1
    END
    

    现在,您可以从班级中删除 DeleteStep1Data()

    Now you can take out DeleteStep1Data() from your class.

    这篇关于如何在类后面隐藏逻辑以提高方法的可读性并重构类以遵循SRP?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆