什么时候使用assumption?

问题背景,定义三个概念先:
1。percent。就是百分比。
2。weight。如果percent是10,weight就是0.1,weight=percent/100.
3。amount。如果percent是10,总数是1000,那么amount就是100. amount=total*weight.

在程序中,我们很多时候需要在amount, weight, percent之间来回转换。根据不同模块的需要,把同一个数据点转换成percent或者weight或者amount。

目标是设计一个类Portion,它的接口如下:
public class Portion {
  public double getPercent();
  public double getWeight();
  public double getAmount();
  public double getTotal();
  public static Portion fromPercent(double total, double percent);
  public static Portion fromWeight(double total, double weight);
  public static Portion fromAmount(double total, double amount);
}

另外,程序中还使用这样一个习惯:如果total为0,那么从amount计算percent和weight的时候也是0。(以避免divide by 0)


我的pair想这样实现:

public class Portion {
  private final double total;
  private final double amount;
  Portion(double total, double amount) {
    this.total = total;
    this.amount = amount;
  }
  public double getPercent() {
    return getWeight()*100;
  }
  public double getWeight() {
    return total==0?0:amount/total;
  }
  public double getAmount() {
    return amount;
  }
  public double getTotal() {
    return total;
  }
  public static Portion fromPercent(double total, double percent) {
    return new Portion(total, total*percent/100);
  }
  public static Portion fromWeight(double total, double weight) {
    return new Portion(total, total*weight);
  }
  public static Portion fromAmount(double total, double amount) {
    return new Portion(total, amount);
  }
}


我对这个设计是不满意的。我提出了几点问题:
1。假设在某一点total不可知,那么怎样用Portion来封装唯一可知的percent/weight?Portion.fromWeight(0, 0.1).getPercent()在这个设计中不会返回我期待的10,而是0。
2。double是有误差的。如果客户写一个
assertEquals(weight, Portion.fromWeight(777, weight).getWeight(), 0)

居然也要失败,不免尴尬。

所以我提议这样做:
public class Portion {
  private final double total;
  private final double amount;
  private final double percent;
  private final double weight;
  Portion(double total, double amount, double percent, double weight) {
    this.total = total;
    this.amount = amount;
    this.percent = percent;
    this.weight = weight;
  }
  public double getPercent() {
    return percent;
  }
  public double getWeight() {
    return weight;
  }
  public double getAmount() {
    return amount;
  }
  public double getTotal() {
    return total;
  }
  public static Portion fromPercent(double total, double percent) {
    return new Portion(total, total*percent/100, percent, percent/100);
  }
  public static Portion fromWeight(double total, double weight) {
    return new Portion(total, total*weight, weight*100, weight);
  }
  public static Portion fromAmount(double total, double amount) {
    double weight = total==0?0:amount/total;
    return new Portion(total, amount, weight*100, weight);
  }
}

这样,虽然double计算有误差,我至少可以保证Portion.fromWeight(total, weight).getWeight()永远等于weight。

但是,pair对这种设计感觉不舒服,他不喜欢把逻辑放在静态工厂方法中。
而且,pair对我提出的几个他的方案的缺陷如此回应:
1。total为0的情况本身就特殊。根据整个系统目前的情况,getWeight()和getPercent()都返回0可以接受。
2。我不care是否有误差,反正我们现在比较double的时候都是用一个tolerance的。


我的pair对整个系统了解的比我多,我相信他说的话。只不过,要我做一个单独的小模块,却总要依赖于外部系统的“对特殊情况A,我们可以容忍;对情况B,我们不在乎”这些assumption,让我深藏于心底的洁癖非常不舒服。

我并不是绝对排斥使用适当的assumption来简化实现复杂度。但是当两个方案的复杂度相近时,我很反感把外界的一些assumption引进来。

那么,你怎么想?

你可能感兴趣的:(IBM,FP)