【发布时间】:2021-10-20 13:43:02
【问题描述】:
在实践中尝试在 Java 中实现 Hexagonal/Ports-and-Adapters 架构时,我在集成异常处理方面遇到了问题。
说有一个 RentBookPort 二级端口接口之类的
public interface RentBookPort {
void rentBook(String isbn);
}
所以这个接口清楚地指定了端口合约,以通过给定的 isbn 租一本书。但是,如果我特别希望将不存在的书作为 EntityNotFoundException 或违反业务规则作为 InvalidInputException 抛出(即该书已被其他人租用)怎么办? 这是(对我而言)一个强有力的合同声明,该端口的每个辅助适配器都应该遵守,可能是真正的 db impl 或 mock impl。如何强制/领导端口接口的实现者这样做?
此外,如果我更改返回值或输入参数的合同,我会自动将编译问题作为警告信号。领先的开发人员是否有类似的技术/方式/技巧/模式来实现预期抛出的异常?
我搜索并找到最好的建议是 Joshua Bloch 的 Effective Java 中的第 56 项(“为所有公开的 API 元素编写 doc cmets”)和第 74 项(“记录每个方法引发的所有异常”)。比如:
public interface RentBookPort {
/**
* Rent a book for a given ISBN.
*
* @param isbn
*
* @throws EntityNotFoundException if no book for given ISBN can be found
* @throws InvalidInputException if the book is already rented by someone else
*/
void rentBook(String isbn);
}
但这真的是我能做的最好的吗,利用 javadoc 并编写独立于适配器的端口接口验收测试以确保符合正确的异常抛出?
【问题讨论】:
-
当你说你想抛出
InvalidInputException一个“不可处理的 ISBN 号”时,你的意思是String不是一个格式良好的 ISBN 吗?换句话说,它是否可以通过仅查看字符串本身而无需其他上下文来验证? -
@TimMoore:谢谢,好点子,isbn 只能通过查看字符串本身才有效,为此设计 InvalidInputException 是一个糟糕的选择/示例。在 DDD 术语中,最好引入一个值类型 ISBN,它将封装 ISBN 的概念,而不是使其成为适配器 impl 指定的东西。如果这本书已被其他人租用,我将示例更改为使用第二个例外,以使我的示例更清晰。
标签: java exception domain-driven-design clean-architecture hexagonal-architecture