我有一个界面:
public interface FileRepository {
String insert(File file) throws IOException;
// other methods ...
}
我的实现插入(文件文件)
使用本地(以避免并发问题)java.security。MessageDigester
抛出检查异常java.security。从其工厂方法中的NoSuch算法异常
。
public FileRepositoryImpl(String digestAlgo) throws NoSuchAlgorithmException {
this.digestAlgo = digestAlgo;
MessageDigest.getInstance(digestAlgo);
}
@Override
public String insert(File file) throws IOException {
// initialize message digest
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance(digestAlgo);
} catch (NoSuchAlgorithmException e) {
LOGGER.fatal(MD_INIT_ERROR, e);
return null;
}
// other code ....
}
// other methods (may contain local MessageDigest)
我的实践:由于< code > nosuchalgorithm exception 总是一个致命的错误(这使得模块完全不可用),我尝试在我的构造函数中初始化一个< code>MessageDigest来测试参数< code>digestAlgo,因此异常可以由构造函数抛出,而不是(早于)从< code>insert(File)抛出。另一个原因是接口定义不允许抛出< code > NoSuchAlgorithmException 。
我的问题:在我的实现中,代码
} catch (NoSuchAlgorithmException e) {
LOGGER.fatal(MD_INIT_ERROR, e);
return null;
}
因此我认为应该有更好的解决方案,这样可以避免(逻辑上和实际上)无法访问的代码。
欢迎任何解决方案/建议,谢谢。
编辑:
在运行代码时,这不是一个真正的问题。但是在测试中,由于代码是不可达的,加上一些“资源的尝试捕捉”,质量分析工具(sonar,pmd)会认为代码“单元测试的分支覆盖不足”,这是分析报告中的一个主要问题,这就是为什么我想避免这段代码。
另一个问题,测试MessageDigest. getInstance(digestAlgo)是一个好的做法吗?
在我的构造函数中?还是最好让插入(文件)
全权负责NoSuch算法异常
?
这节课进行得太多了。如果像它的名字所暗示的那样,它是一个文件存储库,那么它的重点应该放在存储文件上,但是在获取MessageDigest实例方面显然有很多不相关的活动——这个类应该负责创建一种对MessageDigest的隧道化(通过静态方法)依赖吗?依赖注入有许多选项,所有这些选项都使您能够将对象配置到专用于此目的的框架(Spring、Guice、PicoContainer等)。
我认为你认识到了这里的问题,所以这是一个很好的开始。作为一条规则,你应该努力不抛出异常,通常对象构造函数是我最不喜欢这样做的地方。如果您利用一个框架来帮助您配置对象,那么您在这里所面临的尴尬将会完全消失。此外,不是一次而是两次返回null,这会让你在方法调用的另一端检查null,你真的想这样做吗?如果你对此有所考虑,我打赌你会想找到另一种方式(你确实有其他选择)。
此外,您会发现,使用专门的对象创建工厂(这就是那些依赖注入框架)来配置对象将有助于将组件更松散地耦合在一起,这将促进测试组件与真实依赖分离的可能性——使用模拟进行测试。如果你能在做任何其他事情之前改变你为你所希望的代码编写单元测试的思路,你应该会看到更好的设计几乎在不知不觉中开始出现。谷歌的书是一个很好的开始资源。最美好的祝福!
编辑:我看错了——看起来你只返回一次null,但那仍然是一次太多了。:-/
我想我应该将构造函数更改为使用MessageDigest而不是算法名称,并让调用者处理异常。但这里还有另一个问题。将消化器作为实例成员意味着类不是线程安全的。