无需抛出异常的多nil/无效值检查最佳实践方案咨询
优化Ruby API坐标获取方法的健壮性方案
原方法虽能正常运行,但存在异常未捕获、冗余检查过多、可读性差的问题,以下是符合Ruby开发惯例的优化方案:
优化后的基础版本
# @return [Array, nil] - 任何失败场景都不会抛出错误 def fetch_coords_from_api api_url = "some_api_url" params = { api_key: ENV["API_KEY"] } response = ApiClient.new(api_url, params).get return nil unless response json = JSON.parse(response.body) addresses = json.dig("result") return nil unless addresses.is_a?(Array) && !addresses.empty? address = addresses.find { |add| add["zip"] == zip } latitude = address&.dig("latitude") longitude = address&.dig("longitude") [latitude, longitude] if latitude && longitude rescue JSON::ParserError nil end
关键优化点
- 异常兜底:添加
rescue JSON::ParserError,处理响应非合法JSON的场景,严格遵守"不抛出错误"的要求 - 简化层级检查:用
Hash#dig替代手动哈希键存在性判断,减少冗余代码 - 合并冗余判断:将经纬度的有效性检查合并到返回语句中,避免多余的
return unless分支 - 保留合理提前返回:仅保留必要的前置检查,避免过多分支打断代码阅读流
进阶线性逻辑版本(Ruby 2.6+)
如果偏好更连贯的线性逻辑,可以用then链式调用重构,进一步减少局部变量和分支跳转:
# @return [Array, nil] - 任何失败场景都不会抛出错误 def fetch_coords_from_api api_url = "some_api_url" params = { api_key: ENV["API_KEY"] } ApiClient.new(api_url, params).get.then do |response| next nil unless response JSON.parse(response.body).dig("result") end.then do |addresses| next nil unless addresses.is_a?(Array) && !addresses.empty? addresses.find { |add| add["zip"] == zip } end.then do |address| latitude = address&.dig("latitude") longitude = address&.dig("longitude") [latitude, longitude] if latitude && longitude end rescue JSON::ParserError, NoMethodError nil end
这个版本通过then将每个逻辑阶段串联,代码逻辑更线性,可读性更强;额外捕获NoMethodError,防止JSON.parse返回非哈希类型时调用dig抛出异常。
内容的提问来源于stack exchange,提问作者nextstep
相关产品推荐
相关产品推荐

