我正在学习干净的代码,我实际上是在研究银行账户Kata。从桑德罗·曼科的github账户上看,我要做的工作如下:
Deposit and Withdrawal
Transfer
Account statement (date, amount, balance)
Statement printing
这是卡塔的规则:
One level of indentation per method
Don’t use the ELSE keyword
Wrap all primitives and Strings
First class collections
One dot per line
Don’t abbreviate
Keep all entities small (50 lines)
No classes with more than two instance variables
No getters/setters/properties
帐户类别:
package com;
public class Account {
private Operations operations;
public Account(Euro amountOfInitialOperation) {
DateOfOperation dateOfInitialOperation = new DateOfOperation();
Operation defaultOperation = new Operation(amountOfInitialOperation, dateOfInitialOperation);
operations = new Operations();
operations.create(defaultOperation);
}
public void depose(Euro amount) {
recordOperation(amount);
}
public void withdraw(Euro amount) {
Euro negativeAmount = amount.negative();
recordOperation(negativeAmount);
}
private void recordOperation(Euro amount) {
DateOfOperation dateOfOperation = new DateOfOperation();
Operation newOperation = new Operation(amount, dateOfOperation);
operations.create(newOperation);
}
public String print() {
return operations.formatBankOperations();
}
}
DateOfOperation类:
package com;
import java.util.Date;
public class DateOfOperation {
private Date date;
public DateOfOperation() {
date = new Date();
}
public String formatInFrench() {
return "Formated Date";
}
}
欧元级:
package com;
public class Euro {
private long value;
public Euro(long theValue) {
value = theValue;
}
public String moneyRepresentation() {
return value + " euros";
}
public Euro negative() {
return new Euro(-value);
}
@Override
public boolean equals(Object obj) {
Euro other = (Euro)obj;
return value == other.value;
}
}
操作班:
package com;
public class Operation {
private Euro amount;
private DateOfOperation date;
public Operation(Euro theAmount, DateOfOperation theDate) {
amount = theAmount;
date = theDate;
}
public String formatDetails() {
String stringDate = date.formatInFrench();
String moneyRepresentation = amount.moneyRepresentation();
StringBuffer formatedDate = new StringBuffer();
formatedDate
.append(stringDate)
.append(" - ")
.append(moneyRepresentation)
.append("\n");
return formatedDate.toString();
}
}
操作类:
package com;
import java.util.ArrayList;
import java.util.List;
public class Operations {
private List<Operation> operations;
public Operations() {
operations = new ArrayList<Operation>();
}
public void create(Operation operation) {
operations.add(operation);
}
public String formatBankOperations() {
StringBuffer details = new StringBuffer();
for(Operation operation : operations) {
details.append(operation.formatDetails());
}
return details.toString();
}
}
在帐户类上
在处理帐户类时,我在记录事务时遇到了一些问题。事实上,我想测试存款函数,我没有办法模拟DateOfOperation (不是注入,而是通过隐藏的方式创建)。
从技术角度来看,这个方法是私有的,它创建一个新的DateOfOperation来创建一个新的操作。但是,在内部创建这个日期似乎违反了一些坚实的原则。
从业务角度来看,我不希望人们提供一些DateOfOperation作为参数,因为他们可以在将日期作为参数传递时修改该日期。我的行动现在可能是假的。
因此,我不知道如何测试这个结果,我迷失了两种可能性:匹配绝对可靠,或者接受我完全隐藏了操作的日期创建。为了进一步打击我的头脑,Bob叔叔在Clean中建议在创建方法时使用最少的参数。如果我们有太多的参数,我们应该把它分割成多个类/函数(我认为我在这个例子中)
关于DateOfOperation类
DateOfOperation的存在只是为了与规则相匹配:
包装所有原语和字符串
这意味着我们必须包装原语(即使日期是一个类定义.同样适用于列表、字符串等)
这样,我就把我的约会对象(在Java上)完全隐藏在DateOfOperation构造函数中。
问题是我不能嘲笑我的约会,而我在单元测试中的期望也不可能是真的.
我正在寻找一些解释,或代码修改,可以应用于一个平静的对象上下文,这将帮助我纠正以前的问题,或理解这类东西的限制。
发布于 2017-01-25 09:32:38
这里的主要问题在于对业务上下文的理解:您希望操作日期作为外部参数(我现在告诉您,我将在下周二退出),还是总是“现在”?
如果它总是“现在”,就像现在一样在内部创建它。如果要测试"new ()“的结果以等于给定的预定义值,可以使用Powermockito在Date上模拟新操作符,或者注入一个可以模拟的日期工厂。
除此之外,您的命名还存在两个问题,使您很难理解代码:
https://codereview.stackexchange.com/questions/153486
复制相似问题