language-agnostic - 可变/不可变方法的命名约定
问题描述
当您有两个通用名称方法执行相同的操作,而一个是不可变的而另一个是可变的时,命名约定是什么?
例子
考虑接受 2 个数字数组的单元格操作:不可变版本创建一个新数组来放入结果,而可变版本将结果存储在第一个数组参数中。
由于方法名称是通用的,例如apply
操作策略 (add, sub, mul, div) 由第三个参数指定,因此您不能使用诸如add
可变性 (a = a + 1) 和plus
不变性 (c = a +乙)。
代码(将被跳过)
以下细节可能是题外话,但为了说明我在谈论什么方法:
@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
单独的课程
在类中分离可变和不可变方法DoubleArraysMutableMath
可以避免DoubleArraysImmutableMath
在每个方法名称的开头/结尾写入“可变/不可变”前缀/后缀。遵循这种模式,您最终将得到任何名为“可变/不可变”的实用程序类(无论它是否好,我都会留下一个悬而未决的问题)。
单类问题
如果我们想在单个类中使用这些方法(更好的维护),正确的命名“模式”是什么?我在代码示例中使用的模式“asMutable/asImmutable”或通常的“可变/不可变”可能与较长的方法名称不兼容。还有其他选择吗?
解决方案
根据评论编辑
您绝对应该分别实现可变和不可变类。方法名称可以相似也可以不同,这并不重要,因为接口会有所不同。
单班
可变性策略可以作为方法的附加参数提及,例如:
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);
}
}
推荐阅读
- python - Creating a list of random numbers without duplicates in python
- logic - 时钟“数据触发器”(DFF)实现
- metadata - Not be able to console log Auth0 user_metadata. I created a custom rule I also see the data in postman.What am I doing wrong
- python - XGBoost feature_importances_ parameter returns nan
- javascript - 如何使用反向浮动和溢出呈现内联列表
- c# - Botframework:如何使用机器人处理长时间运行的任务?
- arrays - 更改初始数组值 Swift
- python - 'invalid literal for int() with base 10:' 使用 Django REST 检索记录时出错
- css - 与 sass 子选择器等效的 bs-css 子选择器是什么?
- c++ - QTableView:模型中的 endMoveRows 重置水平标题大小