【问题标题】:Don't assign a field from many methods不要从许多方法中分配一个字段
【发布时间】:2018-03-18 18:12:07
【问题描述】:

我的班级里有这样一个字段:

public class Shape
{
    private Point2D m_location;

    public void Move()
    {
       m_location = ...
    }

    public void Rotate()
    {
       m_location = ...
    }

    public void Flip()
    {
       m_location = ...
    }
}

我在 NDepend 中收到一条警告:

不要从许多方法中分配一个字段

https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html

看来我可以通过在我的类中创建另一个方法来轻松解决这个问题,例如:

private void SetLocation(Point2D point)
{
    m_location = location;
}

并在所有设置m_location 的方法中调用它。现在m_location 仅以一种方法分配!

这是解决此问题的有效方法吗?我是否只是通过在这些方法中调用 SetLocation() 方法来隐藏之前检测到的代码异味 NDepend?

【问题讨论】:

  • 您可以为该字段 public SomeObject SomeObject {get; private set;} 创建一个属性,但是是的 - 拥有另一个私有 setter 方法也是有效的,因为它使您的变量完全私有。
  • 有什么理由让它成为一个类级别的字段吗?
  • 我不知道你的完整代码,所以我不能说是否有“代码气味”,但老实说,我不会仅仅因为工具而创建额外的方法给你一个警告,如果你必须从这些方法中分配字段,那就去做吧。
  • @CamiloTerevinto 是的,它是这个类的组成部分之一。
  • @R1PFake 我也永远不会这样做,我只是好奇这些东西是如何重构的。

标签: c# refactoring ndepend


【解决方案1】:

这是解决此问题的有效方法吗?

没有。正如您所怀疑的,这是代码异味。 NDepend 抱怨的是可变引用;你有代码在哪里:

var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.

解决方案是使SomeObject 不可变并返回新引用而不是更改内部结构:

public SomeObject Something()
{
    return new SomeObject(SomethingDifferentDependingOn(this.something));
}

现在你有的不是你的第一个例子:

var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.

是的,有时您需要可变引用。在这些情况下;记录它们并解释为什么它们必须是可变的。然后您可以根据具体情况override NDepend rules 以防止它显示警告。如果您有代码气味,请警告人们。不要试图隐藏它。

编辑后的示例完全不同,但一般原则仍然成立。如果您只有几个内部字段在方法调用中全部更改,您仍然可以返回不可变引用,例如:

public Shape Move()
{
    return new Shape(m_location ...);
}

如果您有许多内部字段并没有全部更改,或者您需要执行诸如共享私有字段之类的操作,则您无法轻松获得不可变引用,但您仍然可以通过使用访问器来避免警告:

public Location
{
    get { return m_location; }
    private set { m_location = value; }
}

然后在你的内部方法中只使用Shape.Location

【讨论】:

  • 感谢您的回答。我更改了问题中的示例以更好地传达我想要的内容。如您所见,在某些情况下,每次我使用 Move() 或 Rotate() 命令时都返回一个新实例并不是一个好主意。
  • 这是一个很好的建议,尽可能支持不可变类 我在过去写了一篇关于这个主题的完整文章codebetter.com/patricksmacchia/2008/01/13/…
猜你喜欢
  • 2011-07-02
  • 2011-09-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 2013-01-07
  • 2011-12-08
  • 2010-10-13
  • 2012-03-28
相关资源
最近更新 更多