我最近阅读了很多关于 TDD 和干净代码的内容,所以我开始研究一个简单的项目来使用它们,我遇到了一些我真的不确定最好的方法是什么。
我有一个将 JavaFile
对象作为参数的类,期望这个File
对象必须是一个目录并且必须以某个前缀开头。我的第一次通过涉及File
在调用构造函数之前对对象进行检查,即检查它是否是一个目录并检查名称是否有效。但我不喜欢调用者指定什么使它有效,特别是有效前缀是什么,我认为这个逻辑应该放在类本身中。
我可以在构造函数中进行此检查并在它无效时抛出异常,但鉴于问题的性质,如果我正在迭代一个File
s 列表,那么完全可以预期其中一些不会是“有效的” ' (即它们将是文件而不是目录)所以抛出一个Exception
真的有保证吗?
public MyObject(File directory) {
if (!directory.isDirectory()) {
throw new IllegalArgumentException("Must be a directory");
}
if (!directory.getName().startsWith("Prefix")) {
throw new IllegalArgumentException("Must start with Prefix");
}
....
}
我考虑过可能添加一个工厂方法来创建对象,如果File
无效则返回 null 。
public static MyObject createMyObject(File directory) {
if (!directory.isDirectory() || !directory.getName().startsWith("Prefix")) {
return null;
}
return new MyObject(directory);
}
或者,我考虑在调用构造函数之前为调用者验证文件的类添加一个静态方法。
public static boolean isValid(File directory) {
return directory.isDirectory() && directory.getName().startsWith("Prefix");
}
if (MyObject.isValid(directory)) {
MyObject object = new MyObject(directory);
}
那么就干净的代码和所有 OOP 原则(例如单一职责、耦合等)而言,这将是首选的方式?
更新:
阅读了一些已经发布的答案后,我开始考虑另一种可能性,这种可能性仅适用于我目前的情况,而不是像我的问题所涉及的那样普遍适用。
作为我的调用代码的一部分,我有一个来自文件系统的路径,并且我列出了该目录中的所有文件,然后我将每个文件传递给 MyObject 构造函数,无论它是否有效。我可以将 a 传递FileFilter
给listFiles
确保 listFiles 仅返回有效目录的方法。FileFilter
可以在 MyObject 中声明:
public static FileFilter getFilter() {
return new FileFilter() {
public boolean accept(File path) {
return path.isDirectory() && path.getName().startsWith("Prefix");
}
};
}
如果我的构造函数抛出异常,那么这确实是一种异常情况,因为期望它只传递有效目录。这样做意味着我可以消除对构造函数/工厂检查异常的需要,因为任何异常都表明某处存在错误,而不是预期的行为。但它仍然留下了是否将其放入构造函数或工厂方法的问题。