我有一种算法可以为实体创建一个版本,然后将其保存到下面的2个实体中:
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
方法的实现。
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();
}
}
我觉得Process
方法工作量很大,并且是否有可能将与版本保存相关的逻辑隐藏在EntityVersion
类的后面,以使Process
方法看起来很简单。
Step1
和Step2
是同步的,因此,如果Step2
中存在错误,我将调用DeleteStep1Data
方法来删除保存在{{1 }}。
我还觉得我的2个派生类Step1
和AggregateCalculator
正在处理1个以上的职责,即运行转换并删除转换过程中存储的数据,尽管我不确定是否这是真的还是不正确的。
是否可以重构以上代码以提高可读性并处理SRP?
答案 0 :(得分:5)
您有一个实体...当实体更改时,您要为您的实体创建一个更改版本。我不清楚的是,为什么需要同时针对变体和类别跟踪此更改?
我们假设您的实体为car
,并且该实体的类别为:Toyota
,BMW
和Nissan
。现在您的实体,假设“ id = 123的丰田电晕”已更改。为什么需要根据类别跟踪更改?您不能只说id = 123的实体已更改吗?
正如我在评论中提到的那样,由于您遗漏了部分逻辑,因此很难理解您的代码是否违反了SRP,但是我可以给您一些一般性建议:
您有一个名为AggregateCalculator
的类,我认为此类的主要职责是计算发生在Transform()
方法中的聚合。现在,您需要在Transform()
内部执行2个步骤。这不一定违反SRP ...,因为从更高层次上讲,您的聚合计算器会做一件事:计算聚合。
您可以查找违反SRP的一般迹象:
根据Nikola Malovic's 2nd law of IoC:
任何具有超过3个依赖项的类都应向SRP询问 违反
如果您的课程太大,那么您需要对它的SRP违规提出质疑。
您的两个课程:AggregateCalculator
和AdditionCalculator
分两步进行计算,分别是 step-1 和 step-2 ...并且您有一个通用方法:如果两个 step-2 失败,则在两个类中都DeleteStep1Data()
删除 step-1 ...我假设{{1 }}对于每个此类都是不同的,但我觉得它仍然包含重复的代码(不是DRY)。有人可能会说这也违反了SRP,因为DeleteStep1Data()
同时负责:计算聚合和“镜像数据库事务”(这很难在没有看到完整代码的情况下分辨出来)。
看来 step-1 和 step-2 都是数据库事务,因此另一种方法是将两个步骤都放在一个数据库事务中...例如,您可以编写这样的存储过程:
AggregateCalculator
现在,您可以从班级中抽出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
。