可变/不可变方法的命名约定

时间:2018-06-12 13:40:47

标签: language-agnostic naming-conventions immutability

两个通用名方法执行相同的操作时,命名约定是什么,而一个是不可变,另一个是可变

示例

考虑按顺序操作接受2个数字数组:不可变版本创建一个新数组以放入结果,而可变版本将结果存储在第一个数组参数中。

由于方法名称是通用的,如apply,因为操作策略(add,sub,mul,div)由第三个参数指定,因此不能使用add之类的常用词来表示可变性(a = a + 1)和plus的不变性(c = a + b)。

代码(待跳过)

以下详细信息可能是非正式的,但为了说明我正在谈论的方法:

@FunctionalInterface 
public interface BinaryOperation { double apply(double a, double b); }

public final class BinaryOperations {
    private BinaryOperations() {}

    public static final BinaryOperation ADD = (a, b) -> a + b;
    public static final BinaryOperation SUB = (a, b) -> a - b;
    public static final BinaryOperation MUL = (a, b) -> a * b;
    public static final BinaryOperation DIV = (a, b) -> a / b;
}

public final class DoubleArraysMath {
    private DoubleArrayMath() {}

    // ---> METHOD NAME OF INTEREST
    public static void applyAsMutable(double[] a, double[] b, BinaryOperation o) {
        apply(a, a, b, o);
    }
    // ---> METHOD NAME OF INTEREST
    public static double[] applyAsImmutable(double[] a, double[] b, BinaryOperation o) {
        double[] c = new double[a.length];
        return apply(c, a, b, o);
        return c;
    }
    private static void apply(double[] result, double[] a, double[] b, BinaryOperation o) {
        for (int i = 0; i < a.length; i++) { result[i] = o.apply(a[i], b[i]); }
    }
}

// just an example of usage
double[] r = DoubleArraysMath.applyAsImmutable(a, b, BinaryOperations.MUL);
DoubleArraysMath.applyAsMutable(a, b, BinaryOperations.ADD);
DoubleArraysMath.applyAsMutable(a, b, (ai, bi) -> ai*ai + bi); // some custom operation

分离课程

DoubleArraysMutableMathDoubleArraysImmutableMath类中分隔可变和不可变的方法可以避免写入&#34; mutable / immutable&#34;每个方法名称的开头/结尾都有前缀/后缀。遵循这种模式,您将得到名为&#34; mutable / immutable&#34;的任何实用程序类。 (无论是否好,我都会作为一个悬而未决的问题离开。)

单一类别问题

如果我们想在单个类中使用这些方法(更好的维护),那么正确命名&#34;模式&#34 ;?我在我的代码示例中使用的模式&#34; asMutable / asImmutable&#34;或者通常&#34;可变/不可变的&#34;使用较长的方法名称可能不兼容。还有其他选择吗?

1 个答案:

答案 0 :(得分:1)

根据评论进行修改

你绝对应该分别实现可变和不可变的类。方法名称可以相似或不同,无论如何接口都是不同的。

单班

可以提及可变性策略作为该方法的附加参数,例如:

apply(a,b,Operation.ADD, ResultValue.NEW)
apply(a,b,Operation.ADD, ResultValue.FIRST_ARG)
apply(a,b,Operation.ADD, ResultValue.SECOND_ARG)

但是,在单个方法中使用多个策略会使该方法对客户端造成混淆并容易出错。

如果方法的签名是

double [] apply(double[] arg1, double[] arg2, BinaryOperation)

然后,可变性或不变性可以成为BinaryOperation本身的一部分:

public class FirstArgMutablePlusOperation {
    double[] apply(double[] arg1, double[] arg2) {
         //sample mutation
         arg1[0] = arg1[0] + arg2[0];
         // still return arg1 as a result
         return arg1;
    }
}

public class SecondArgMutablePlusOperation {
    double[] apply(double[] arg1, double[] arg2) {
         //sample mutation
         arg2[0] = arg1[0] + arg2[0];
         // still return arg2 as a result
         return arg2;
    }
}

public class ImmutablePlusOperation {
    double[] apply(double[] arg1, double[] arg2) {
         //sample mutation
         double[] result = new double[arg1.length];
         result[0] = arg1[0] + arg2[0];
         return result;
    }
}

然后用户可以使用正确的策略调用apply方法:

apply(arg1, arg2, new FirstArgMutablePlusOperation());
apply(arg1, arg2, new SecondArgMutablePlusOperation());
double[] result = apply(arg1, arg2, new ImmutablePlusOperation());

不可变/可变策略可以是BinaryOperation的一部分。 但是,我宁愿避免使用这个解决方案,因为它会引入if语句和庞大的实现:

public enum ResultStrategy 
{ RESULT, FIRST_ARG, SECOND_ARG };

public class PlusOperation extends BinaryOperation {
        private final ResultStrategy strategy;
        public PlusOperation(final ResultStrategy strategy) {
              this.strategy = strategy
        }
        double[] apply(double[] arg1, double[] arg2) {
             if(strategy == ResultStrategy.FIRST_ARG) {
                  //sample mutation
                  arg1[0] = arg1[0] + arg2[0];
                  // still return arg1 as a result
                  return arg1;
             } else if(strategy == ResultStrategy.SECOND_ARG) {
                  //sample mutation
                  arg2[0] = arg1[0] + arg2[0];
                  // still return arg2 as a result
                  return arg2;
             } else if(strategy == ResultStrategy.RESULT) {
                  double[] result = new double[arg1.length];
                  result[0] = arg1[0] + arg2[0];
                  return result;
             }
        }
    }

用法:

apply(arg1, arg2, new PlusOperation(ResultStrategy.FIRST_ARG));
apply(arg1, arg2, new PlusOperation(ResultStrategy.SECOND_ARG));
double[] result = apply(arg1, arg2, new PlusOperation(ResultStrategy.RESULT));

<强>更新

根据问题提供的示例代码

public enum ResultStrategy { FIRST_ARG, NEW_RESULT;} // SECOND_ARG = apply(b, a)

public class DoubleArraysMath {
    ...
    public static double[] apply(ResultStrategy rs, double[] a, double[] b, BinaryOperation o) {
        if (rs == ResultStrategy.FIRST_ARG) { return apply(a, a, b, o); }
        return apply(new double[a.length], a, b, o);
    }
}