【问题标题】:Variable value assignment operation duplication变量赋值操作重复
【发布时间】:2010-10-10 03:10:21
【问题描述】:

上下文

来自The Pragmatic Programmer

每一条知识都必须有一个, 明确的,权威的代表 一个系统。

问题

  • 该语句如何与直接在多个位置在一个类中设置私有成员变量的值相协调?
  • 因为值不能有外部依赖关系,这有关系吗?
  • 直接更改除访问器外其他地方有公共访问器的私有成员变量是否重复?

示例

考虑以下代码:

public class Line {
  private boolean changed;
  private double length;
  private Point start;
  private Point end;

  public Line( Point p1, Point p2 ) {
    this.start = p1;
    this.end = p2;
    this.changed = true;
  }

  public void setStart( Point p ) { this.start = p; this.changed = true; }
  public void setEnd( Point p ) { this.end = p; this.changed = true; }
  public Point getStart() { return this.start; }
  public Point getEnd() { return this.end; }

  public double getLength() {
    if( this.changed ) {
      this.length = start.distanceTo( end );
      this.changed = false;
    }

    return this.length;
  }
}

即使changed 变量从未公开(通过公共访问器或其他方式),同一行代码基本上重复了四次:this.changed = true(三次)和this.changed = false(一次)。同样,this.startthis.end 的赋值发生了多次。相对于:

  public Line( Point p1, Point p2 ) {
    setStart( p1 );
    setEnd( p2 );
  }

  public void setStart( Point p ) { this.start = p; dirty(); }
  public void setEnd( Point p ) { this.end = p; dirty(); }

  public double getLength() {
    if( isDirty() ) {
      setLength( getStart().distanceTo( getEnd() ) );
      clean();
    }

    return this.length;
  }

更新后的代码非常相似,但删除了所有重复的赋值(假设 dirty()clean() 使用访问器)。 (由于重复使用访问器方法进行赋值,构造函数中存在对 dirty() 的重复调用。)

问题不在于this.changed = true 是否更容易理解为dirty()

澄清

问题在于this.variable = value 是否是“知识”,因此应该有一个一致使用的“单一、明确、权威的表示”:相应的访问器。因此一般情况:

public class C1 {
  private Object v;

  public C1() {
    this.v = new C1();
  }

  public void m1() {
    this.v = new String();
  }

  public void m2() {
    System.out.println( this.v );
  }
}

对比:

public class C2 {
  private Object v;

  public C2() {
    setV( new C2() );
  }

  public void m1() {
    setV( new String() );
  }

  public void m2() {
    System.out.println( getV() );
  }

  private void setV( Object o ) { this.v = o; }
  private Object getV() { return this.v; }
}

在C1中,变量v在多个地方直接赋值。在 C2 中,变量v 直接分配在一个位置。尽管在这两种情况下,v 都是完全私有的,但 C1 实现是否复制了“知识片段”?

【问题讨论】:

  • 我对这个问题有点困惑。假设dirty()clean() 是设置this.changed 的​​mutators,那么两者确实是相同的。没有理由担心他们的差异。如果您真的想讨论差异,尽管调用 mutators/accessors 只是将更多函数推入堆栈,这最终意味着更多 ASM 调用,因此执行时间更长。
  • @steven_desu:代码设计很少涉及计算汇编指令。从一次性的角度来看,dirty() 方法实际上更干净,并且比其他方法更可取。此外,现代 Java 运行时具有方法内联,因此,就运行时而言,它没有任何区别。

标签: java oop dry


【解决方案1】:

该语句如何与在多个位置在一个类中直接设置私有成员变量的值相协调?

只有一个私有成员变量。因此有一个单一的表示。改变这种表述的陈述本身并不是表述。拥有多个访问/更改表示的语句与拥有多个表示不同。

这是否重要,因为该值不能有外部依赖关系?

没有。

直接改变除了访问器在其他地方有公共访问器的私有成员变量是否重复?

没有。

这并不一定意味着这样做是个好主意。

在您的示例中,选择是直接访问和更新“脏”标志还是通过轻量级私有方法执行此操作。 IMO,这归结为一种价值判断,即哪种方法可以为您提供更具可读性的代码。我的感觉是,至少在这种情况下,这两种方法之间几乎没有区别。在其他情况下,使用内部方法访问/更新从未公开的私有状态可能会更有说服力。

如果需要在类之外公开状态,则有充分的理由将变量声明为私有并提供 getter 和 setter 供其他类使用。如果已经声明了这些 getter 和 setter,那么您可以创建一个(较弱的)案例,让类本身应该使用它们。

对于那些关心 Java 中 getter 和 setter 的效率或其他方面的人来说,它可能不会对性能产生影响。现代 JVM 中的 JIT 编译器几乎肯定会内联 clean()dirty()isDirty() 等方法,从而导致机器指令等同于直接获取和设置变量的情况。事实上,最新的 JIT 编译器甚至会内联非最终公共方法,因为它们可以推断出不需要分派这些方法。

【讨论】:

    【解决方案2】:

    dirty() 这样的方法比this.changed = true 具有更多的语义含义。如果你决定要以不同的方式处理脏跟踪,你只需要改变一个地方——从其他代码的角度来看(即使都在同一个类中),它仍然更有意义(更容易让读者掌握)。

    简而言之,我建议使用dirty() 而不是this.changed = true

    【讨论】:

      猜你喜欢
      • 2016-02-03
      • 2017-07-01
      • 2013-09-13
      • 2011-03-21
      • 2019-03-11
      • 2018-05-18
      • 2017-06-20
      • 2017-12-18
      • 1970-01-01
      相关资源
      最近更新 更多