【发布时间】:2022-11-19 00:29:06
【问题描述】:
假设我有一个 UserController 的 Web 应用程序。客户端发送即将由控制器处理的 HTTP POST 请求。然而,首先必须将提供的 json 解析为 UserDTO。出于这个原因,存在一个UserDTOConverter 和一个方法toDTO(json): User。
鉴于我重视函数式编程实践的引用透明性和纯函数的好处,问题是。处理可能无法解析的 json 的最佳方法是什么?第一个选项是抛出异常并在全局错误处理程序中处理它。无效的 json 意味着出现了严重的错误(例如黑客)并且这个错误是不可恢复的,因此异常是正确的(即使假设 FP)。第二种选择是返回 Maybe<User> 而不是 User。然后在控制器中我们可以根据返回类型返回 HTTP 成功响应或失败响应。最终,这两种方法都会导致相同的失败/成功响应,但哪一种更可取呢?
另一个例子。假设我有一个 Web 应用程序需要从远程存储库 UserRepository 检索一些数据。来自 UserController 的存储库称为 getUser(userId): User。同样,在提供的 id 下处理可能不存在的用户错误的最佳方法是什么?我可以再次返回Maybe<User>,而不是返回User。然后在控制器中可以通过例如返回“204 No Content”来处理此结果。或者我可以抛出异常。代码保持引用透明,因为我再次让异常一直冒泡到全局错误处理程序(没有 try catch 块)。
而在第一个示例中,我更倾向于抛出异常,而在后一个示例中,我更愿意返回 Maybe。异常会导致更清晰的代码,因为代码库不会被无处不在的Eithers、Maybes、空集合等弄得乱七八糟。但是,返回这些类型的数据结构可确保调用的明确性,并且 imo 可以更好地发现错误。
函数式编程中有异常的地方吗?使用异常而不是返回Maybes 或Eithers 的最大陷阱是什么?在基于 FP 的应用程序中抛出异常有意义吗?如果是这样,是否有经验法则?
【问题讨论】:
-
Maybe/Either是编码短路概念的两种类型。根据用法,这也可能意味着总是在您的程序中捕获异常。不同之处在于,命令式异常是一种独特的语言构造,专门设计用于对预期异常进行编码,而Maybe/Either是一流值的可区分联合类型。前者是引用不透明的,后者是透明的,后者更普遍 bc 短路并不一定意味着异常,但也意味着非确定性或结果缺失。
标签: exception error-handling functional-programming