我的功能是否违反了SRP或其他最佳做法?

时间:2017-07-17 08:29:25

标签: c# refactoring single-responsibility-principle

我有以下代码,一个函数将获取一个对象列表(我称之为Y Objects)并调用另一个方法将其转换为X Objects。

public List<X> GetXObjects()
{
    var yObjects= GetYObjects();
    var transformer = new Transformer();
    var xObjects = transformer.Transform(yObjects);
    return xObjects;
}

目前的实施方式有效,但我觉得我的功能可能会违反SRP或其他最佳做法。有可能重构代码更好吗?

3 个答案:

答案 0 :(得分:2)

我会调用方法TransformObjects并将变换器添加为参数,这样就可以使用不同的变换器,并且每次调用方法时都不会初始化变换器。 yObjects也是如此。因此,该方法的唯一责任是转换对象。

public List<X> TransformObjects(List<Y> yObjects, Transformer transformer)
{
    var xObjects = transformer.Transform(yObjects);
    return xObjects;
}

调用方法:

var yObjects= _crmWrapper.GetActivitiesByOpportunities();
var transformer = new Transformer();
myTransformer.TransformObjects(yObjects, transformer);

如果您创建一个接口ITransformer接口,通过交换变压器可以更轻松地增强您的代码。

答案 1 :(得分:2)

我的两分钱......

我会以很少的代价使这段代码更加通用。扩展enter image description here,为什么不继续前进,只需删除这个讨厌的变压器?知道如何将Y转换为X的任何内容都可以,对吧?

为什么接受并返回List?让消费者决定是否要急切地使用枚举,除非必要,否则不要为他做出决定。

public IEnumerable<TResult> TransformObjects<TResult, TSource>(
    IEnumerable<TSource> source, Func<TSource, TResult> transformer)
    => source.Select(transformer);

现在突然你意识到了;嘿!这只是一个常规的好老Enumerable.Select,不是吗?那么,为什么重新发明轮子?

var xObjects = GetYObjects().Select(transformer.Transform);

所以你的代码最后是Enumerable.Select!很好,没有错误,我需要测试一种方法,继续前进;)。

答案 2 :(得分:1)

您的功能执行下一个任务

  • 加载活动
  • 创建变压器实例
  • 转换加载的对象

可以通过将其作为参数

引入来删除活动的加载
public List<X> GetXObjects(List<Y> yObjects)
{
    var transformer = new Transformer();
    return transformer.Transform(yObjects);
}

然后创建变压器也可以移到外面

public List<X> GetXObjects(Trnasformer transformer, List<Y> yObjects)
{
    return transformer.Transform(yObjects);
}   

所以现在在代码中你可以像这样称呼

var yObjects= _crmWrapper.GetActivitiesByOpportunities();
var transformer = new Transformer();
var xObjects = GetXObjects(yObjects, transformer);

但点击意味着您需要加载XObjects的每个地方,您需要知道如何加载YObjects以及如何创建Transformer

因此我们可以将这些知识/逻辑封装在一个类

public class XObjectsProvider
{

}

此类应加载YObjects并将它们转换为XObject。加载和创建Transform实例的实际实现不是此类的责任 - 所以我们将它们作为依赖项引入。

public class XObjectsProvider
{
    private Loader _loader;
    private Transformer _transformer;

    public XObjectsProvider(Loader loader, Transformer transformer)
    {
        _loader = loader;
        _transformer = transformer;
    }

    public XObjects Get()
    {
        var yObjects = _loader.GetYObjects();
        return transformer.Transform(yObjects);
    }
}

LoaderTransformer可以作为抽象引入,并且可以在不更改XObjectProvider的代码的情况下更改它们 - 遵循“打开/关闭原则”。 并且XObjectProvider只有一个原因需要改变 - 当获取XObjects时,您需要加载/提供其他信息。