最佳实践:在Java.net.URL中捕获故障点

10

我是JVM和Scala以及Play 2.0的新手。

我正在将一个需要通过Authorize.net进行付款处理的遗留应用程序转换为Play。查看java.net.URL源代码,有很多潜在的失败点。在下面给出的接口中,您会在哪里实现try/catch块?我需要相应地调整方法签名,可能会返回Either [Error,Success]到调用客户端代码。

import java.net.{URL, URLEncoder}
import java.io.{BufferedReader, DataOutputStream, InputStreamReader}
import javax.net.ssl._

trait Authnet {
  private val prodUrl = "https://secure.authorize.net/gateway/transact.dll"
  private val testUrl = "https://test.authorize.net/gateway/transact.dll"

  protected def authNetProcess(params: Map[String,String]) = {
    val(conn, urlParams) = connect(params)
    val request = new DataOutputStream( conn.getOutputStream )
    request.write(urlParams.getBytes)
    request.flush()
    request.close()
    val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
    val results = response.readLine().split("\\|")
    response.close()
    results.toList
  }  

  private def connect(params: Map[String,String]) = {
    val urlParams = (config ++ params) map { case(k,v) =>
        URLEncoder.encode(k, "UTF-8") + "=" + URLEncoder.encode(v, "UTF-8")
    } mkString("&")

    lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
    val conn = url.openConnection
    conn.setDoOutput(true)
    conn.setUseCaches(false)
    (conn, urlParams)
  }

  private val config = Map(
    'x_login        -> "...",
    'x_tran_key     -> "...",
    ...
  )
}
2个回答

1

遵循基本原则:

只有在必须处理时才捕获异常。

“必须处理”没有明确的定义,但它意味着您应该抵制捕获异常的冲动,因为您可以仅抛出不同的异常。

“必须处理”主要由应用程序应如何工作或其他依赖项来定义。

如果应用程序需要向用户显示错误而不是通过异常中止,则必须这样做。

在这种情况下,捕获异常还添加了一些有意义的处理。

如果API需要抛出不同的异常,则必须这样做,但API的定义可能不正确。

我始终质疑用另一个异常替换异常的附加值。

将此应用于您的示例:

从authNetProcess()中的connect()捕获异常是否会增加价值?

不!无法在connect()内部处理该异常。因此,将该异常留给authNetProcess的调用者是可以的。在那里,您可以根据异常的类型提供不同的处理。


0

编辑
好的,如果连接/流程中的任何部分失败,则事务将失败,所以仅在打开连接时捕获错误是愚蠢的。我只是将整个事务包装在一个catching (operation) option块中,并将其留在那里;我对错误的具体原因不太关心(无论它是什么都被记录下来),因为它是短暂的,所以捕获它,让用户重试;如果错误仍然存在,请联系我们...

原文 好吧,鉴于赞成票和迄今缺乏评论,我唯一能得出的结论是...这里没有人知道他们在做什么!哈哈,开玩笑;-)

虽然我对JVM还很陌生,但是使用try/catch/finally处理繁琐,通过Scala类型推断的神奇,我已经将通用错误处理抽象为简洁的实现:
catching ( operation ) option
catching ( operation ) either

除非我收到其他反馈,否则我现在只是捕获连接创建(我相信在这种情况下,最有可能的错误条件)。以下是新的实现:

protected def authNetProcess(params: Map[String,String]) = {
    connect() match {
      case Some(conn) =>
        val request = new DataOutputStream(conn.getOutputStream)
        request.write(getUrlParams(params).getBytes)
        request.flush()
        request.close()
        val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
        val results = response.readLine().split("\\|")
        response.close()
        results.toList
      case None => List[String]()
    }
  }

  private def connect() = {
    lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
    catching ( url.openConnection ) option match {
      case Some(conn) =>
        conn.setDoOutput(true)
        conn.setUseCaches(false)
        //conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
        Some(conn)
      case None => None // connection failed
    }
  }

我想一个更严谨的方法可能是将所有可能出错的条件提取到 maybeWorked 选项操作中,然后将它们全部包装在 for 推导式中。这可能是适当/负责任的方式……但一天只有那么多小时,稍后再回来处理。

欢迎反馈意见!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接