3

返回 void 但更改其参数状态(即提供隐藏或隐式返回值)的方法通常是一种不好的做法吗?

我发现它们很难模仿,这表明它们可能是糟糕设计的标志。

有哪些模式可以避免它们?

一个非常人为的例子:

public interface IMapper
{
    void Map(SourceObject source, TargetObject target);
}

public class ClassUnderTest
{
    private IMapper _mapper;

    public ClassUnderTest(IMapper mapper)
    {
        _mapper = mapper;
    }

    public int SomeOperation()
    {
        var source = new SourceObject();
        var target = new TargetObject();

        _mapper.Map(source, target);

        return target.SomeMappedValue;
    }
}
4

2 回答 2

1

如果你这样做,你的代码会更容易测试:

public interface IMapper
{
    TargetObject Map(SourceObject source);
}

public class ClassUnderTest
{
    private IMapper _mapper;

    public ClassUnderTest(IMapper mapper)
    {
        _mapper = mapper;
    }

    public int SomeOperation(SourceObject source )
    {
        var target =  _mapper.Map(source, target);
        return target.SomeMappedValue;
    }
}

您现在可以分别测试 Map 操作和 SomeOperation。问题是你改变了一个对象的状态,这使得很难为测试提供一个存根。返回新对象时,您可以返回目标的测试存根并测试您的调用方方法。

于 2013-03-12T13:56:56.913 回答
1

在某种程度上是的。

你描述的是典型的副作用。副作用使程序难以理解,因为您需要理解的信息不包含在调用堆栈中。您需要其他信息,即在之前(以及以什么)顺序调用了哪些方法。

解决方案是在没有副作用的情况下进行编程。这意味着您不会更改变量、字段或任何东西。相反,您将返回您通常会更改的新版本。

这是函数式编程的基本原则。

当然,这种编程方式有它自己的挑战。只考虑 I/O。

于 2013-03-12T15:48:58.923 回答