变量值赋值操作重复

时间:2010-10-10 03:10:22

标签: java oop dry

上下文

来自 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实现是否会复制“知识”?

2 个答案:

答案 0 :(得分:3)

  

如何在多个地方的整个班级中直接设置私有成员变量的值来协调该声明?

有一个私有成员变量。因此,只有一个代表。更改此表示的语句本身不是表示形式。拥有多个访问/更改表示的语句与具有多个表示形式的语句不同。

  

是否重要,因为该值不存在外部依赖性?

没有

  

直接更改除访问者之外的其他地方有公共访问者的私有成员变量是否重复?

没有

那不是必然意味着尽管这样做是个好主意。

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

如果状态需要暴露在类之外,那么很有可能将变量声明为private并为其他类提供getter和setter。如果已经声明了那些getter和setter,那么你可以创建一个(弱的)类本身应该使用它们。

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

答案 1 :(得分:1)

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

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