我的职能是否违反了 SRP 或其他最佳实践?

Does my function violate SRP or other best practices?

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

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

当前的实现有效,但是,我觉得我的函数可能违反了 SRP 或其他最佳实践。是否可以重构代码以使其更好?

我会调用方法 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 接口,那么通过交换转换器来增强你的代码会更容易。

您的函数执行后续任务

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

可以通过将其作为参数引入来移除活动负载

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

那么transformer的创建也可以移到外面

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

所以我们可以把这个knowledge/logic封装成一个class

public class XObjectsProvider
{

}

此 class 应加载 YObjects 并将它们转换为 XObject。加载和创建 Transform 实例的实际实现不属于此 class - 因此我们将它们作为依赖项引入。

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 的代码的情况下更改它们 - 在 "Open/Close principle" 之后。 XObjectProvider 只有一个改变的理由——在获取 XObjects 时你需要 load/provide 一些其他信息。

我的两分钱...

我会以很少的成本使这段代码更加通用。扩展 ,为什么不继续简单地删除这个讨厌的转换器呢?任何知道如何将 Y 转换为 X 的东西都应该可以,对吗?

为什么接受和 return 一个 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!太好了,这里没有错误,我需要测试的方法少了一种,继续;)。