2012-06-01 10 views
10

Nuevo en la JVM, trabajando con Scala and Play 2.0de mejores prácticas: la captura de puntos de fallo en java.net.URL

estoy convirtiendo una aplicación heredada a jugar, uno que requiere el procesamiento de pagos a través de Authorize.net . Mirando a través de la fuente java.net.URL, hay numerosos posibles puntos de falla. Dada la interfaz que he escrito a continuación, ¿dónde implementarías los bloques try/catch? Voy a tener que adaptar las firmas de los métodos en consecuencia, probablemente, de devolver un bien [Error, Éxito] para llamar a código de cliente

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  -> "...", 
    ... 
) 
} 

Respuesta

0

EDITAR
Bueno, si alguna parte del proceso de conexión/corriente de falla, la transacción es una manguera, tan tonto que solo captura el error al abrir la conexión. Estoy envolviendo toda la transacción en un bloque catching (operation) option, y dejándolo así; No me preocupa demasiado la causa exacta del error (lo que sea que se haya registrado) ya que es transitorio, así que tómalo, haz que el usuario intente de nuevo; Si el error persiste, póngase en contacto con nosotros ...

ORIGINAL OK, bueno, teniendo en cuenta los votos arriba y la falta de comentario a la fecha, la única conclusión que puedo sacar es ... nadie por aquí sabe lo que' re haciendo! je, je, bromeando ;-)

Aunque soy nuevo en la JVM, prueba/captura/finalmente la hinchazón se está haciendo vieja rápidamente; a través de las maravillas de Scala inferencia de tipos, he abstraído en el manejo de las implementaciones concisas error general:
catching (operation) option
catching (operation) either

A menos que reciba retroalimentación de lo contrario, por ahora estoy copping a cabo por sólo la captura de creación de la conexión (creo , en este caso, la condición de error más probable). Aquí está la nueva aplicación:

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 
    } 
    } 

supongo que un enfoque más riguroso sería para extraer todas las posibles condiciones de error en las operaciones de opción maybeWorked, y luego envolver a todos ellos en una de comprensión. Ese es probablemente el enfoque adecuado/responsable ... pero solo tantas horas en un día, volveremos a visitarlo más tarde

comentarios apreciados!

1

Se adhieren a la regla del pulgar:

solo con captura una excepción si debe manejarlo.

No hay una definición clara para "debe manejar" pero significa que debe resistir la tentación de atrapar una excepción porque puede arrojar una excepción diferente.

El "debe manejar" se define principalmente por cómo debería funcionar su aplicación u otras dependencias.

Si la aplicación requiere mostrar un error al usuario en lugar de abortar con una excepción, entonces es obligatorio.

En ese caso, capturar el excpetion también agrega un procesamiento significativo.

Si una API requiere arrojar una excepción diferente, entonces es imprescindible, pero la definición de la API posiblemente no es válida.

Siempre estoy cuestionando el valor agregado de reemplazar una excepción con solo otra excepción.

Aplicando esto a tu ejemplo:

se sumaría eso algún valor para capturar una excepción de connect() en authNetProcess()?

No! No hay forma de manejar esa excepción dentro de connect(). Entonces está bien dejar esa excepción a la persona que llama de authNetProcess. Allí podría proporcionar un manejo diferente según el tipo de excepción.