简体   繁体   English

变量值赋值操作重复

[英]Variable value assignment operation duplication

Context 上下文

From The Pragmatic Programmer : 来自务实的程序员

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. 每一段知识都必须在系统中具有单一,明确,权威的表示。

Questions 问题

  • How is that statement reconciled with directly setting a private member variable's value throughout a class in multiple places? 如何在多个位置的整个类中直接设置私有成员变量的值来协调该语句?
  • Does it matter as there can be no external dependencies on the value? 是否重要,因为该值不存在外部依赖性?
  • Is it duplication to directly change private member variables that have public accessors in other places besides the accessor? 是否重复直接更改除访问者之外的其他地方具有公共访问者的私有成员变量?

Example

Consider the following code: 请考虑以下代码:

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;
  }
}

Even though the changed variable is never exposed (through public acccessors or otherwise), the same line of code is essentially repeated four times: this.changed = true (thrice) and this.changed = false (once). 即使changed变量从未暴露(通过公共访问者或其他方式),相同的代码行基本上重复四次: this.changed = true (三次)和this.changed = false (一次)。 Similarly, the assignment of this.start and this.end happens multiple times. 同样, this.startthis.end的赋值this.start this.end发生。 As opposed to: 相反:

  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;
  }

The updated code is quite similar, but the duplication of all assignments is removed (presume dirty() and clean() use accessors). 更新的代码非常相似,但删除了所有赋值的重复(假设dirty()clean()使用访问器)。 (There is a duplicated call to dirty() in the constructor that was not there before due to reusing the accessor methods for assignment.) (由于重用了访问器方法进行分配,构造函数中的dirty()重复调用,因为重用了访问器方法。)

The question is not about whether this.changed = true is more readily understood as dirty() . 问题不在于this.changed = true是否更容易理解为dirty()

Clarification 澄清

The question is about whether this.variable = value is a "piece of knowledge" and should therefore have a "single, unambiguous, authoritative representation" that is used consistently: a corresponding accessor. 问题是关于this.variable = value是否是“知识”,因此应该具有一致使用的“单一,明确,权威的表示”:相应的访问者。 Thus the general case: 因此一般情况:

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 );
  }
}

versus: 与:

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; }
}

In C1, the variable v is directly assigned in multiple places. 在C1中,变量v直接分配在多个位置。 In C2, the variable v is is directly assigned in a single spot. 在C2中,变量v is直接分配在单个点中。 Even though, in both cases, v is completely private, does the C1 implementation duplicate a "piece of knowledge"? 即使在这两种情况下, v都是完全私有的,C1实现是否会复制“知识”?

How is that statement reconciled with directly setting a private member variable's value throughout a class in multiple places? 如何在多个位置的整个类中直接设置私有成员变量的值来协调该语句?

There is a single private member variable. 有一个私有成员变量。 Therefore there is a single representation. 因此,只有一个代表。 The statements that change this representation are not representations themselves. 更改此表示的语句本身不是表示形式。 Having multiple statements that access / change the representation is not the same as having multiple representations. 具有访问/更改表示的多个语句与具有多个表示的不同。

Does it matter as there can be no external dependencies on the value? 是否重要,因为该值不存在外部依赖性?

No. 没有。

Is it duplication to directly change private member variables that have public accessors in other places besides the accessor? 是否重复直接更改除访问者之外的其他地方具有公共访问者的私有成员变量?

No. 没有。

That doesn't necessarily mean that it is a good idea to do it though. 这并不一定意味着尽管这样做是个好主意。

In your example, the choice is between accessing and updating a "dirty" flag directly or doing this via light-weight private methods. 在您的示例中,选择是直接访问和更新“脏”标志还是通过轻量级私有方法执行此操作。 IMO, this boils down to a value judgment as to which approach gives you more readable code. IMO,这归结为一种价值判断,即哪种方法为您提供更易读的代码。 And my feeling is that there is little difference between the two approaches, at least in this case. 我的感觉是两种方法之间几乎没有区别,至少在这种情况下。 In other cases, there could be a stronger case for using internal methods to access / update private state that is never exposed. 在其他情况下,使用内部方法访问/更新从未公开的私有状态可能会有更强的理由。

If the state needs to be exposed outside of the class then there is a strong case for declaring the variables private and providing getters and setters for other classes to use. 如果状态需要暴露在类之外,则有一个强有力的例子可以将变量声明为私有,并为其他类提供getter和setter。 And if those getters and setters have been declared, then you can make a (weaker) case that the class itself should use them. 如果已经声明了那些getter和setter,那么你可以创建一个(弱)情况,类本身应该使用它们。

For those people who are concerned about the efficiency or otherwise of getters and setters in Java, the chances are that it will make no difference to performance. 对于那些担心Java中的getter和setter的效率或其他方面的人来说,它可能对性能没有任何影响。 The JIT compiler in a modern JVM will almost certainly inline methods like clean() , dirty() and isDirty() resulting in machine instructions are equivalent to the case where you get and set the variables directly. 现代JVM中的JIT编译器几乎肯定会内联方法,如clean()dirty()isDirty()导致机器指令等同于直接获取和设置变量的情况。 Indeed, the latest JIT compilers will even inline non-final public methods when they can deduce that the methods don't need to be dispatched. 实际上,最新的JIT编译器甚至可以推断出非最终的公共方法,因为他们可以推断出这些方法不需要发送。

A method like dirty() has more semantic meaning than this.changed = true . dirty()这样的方法比this.changed = true具有更多的语义含义。 If you ever decide you want to handle the dirty-tracking a different way, you only have to change one place---and from the point of view of other code (even if all in the same class), it's still more meaningful (and easier for the reader to grasp). 如果你决定要以不同的方式处理脏跟踪,你只需要改变一个地方---从其他代码的角度来看(即使它们都在同一个类中),它仍然更有意义(并且更容易让读者掌握)。

In short, I recommend using dirty() instead of this.changed = true . 简而言之,我建议使用dirty()而不是this.changed = true

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM