Realizamos una auditoria de errores

Un contrato utilizado con frecuencia para funciones que devuelven un valor de error de un tipo de interfaz es que la persona que llama no debe saber de antemano nada sobre el estado de otros valores devueltos por esta llamada sin verificar primero el error.


En la mayoría de los casos, los valores de error devueltos por las funciones deben ser opacos para la persona que llama. Es decir, una prueba en la que el error es nulo muestra si la llamada fue exitosa o fallida, y eso es todo lo que necesita hacer.



foto de aqui


Un pequeño número de casos, generalmente asociados con interacciones con el mundo exterior, como la actividad de la red, requieren que la persona que llama examine la naturaleza del error para decidir si repetir la operación.


Un requisito común para los autores de paquetes es devolver errores de tipo público conocidos para que la persona que llama pueda usar la afirmación de tipo y examinarlos en detalle. Creo que esta práctica conduce a una serie de resultados indeseables:


  • Los tipos abiertos de errores aumentan el "área de contacto" con la API del paquete.
  • Las nuevas implementaciones solo deberían devolver los tipos especificados en la declaración de la interfaz, incluso si no se ajustan bien.
  • El tipo de error, después de ser agregado al código, no se puede cambiar o desaprobar sin romper la compatibilidad, haciendo que la API sea frágil.

Confirme el comportamiento esperado, no el tipo de error


No afirme que el valor de error es de un tipo específico, sino más bien afirme que el valor implementa un comportamiento específico.


Esta oración es consistente con la naturaleza de las interfaces implícitas Go, y no es un [subtipo] de la naturaleza de los lenguajes basados ​​en herencia. Considere este ejemplo:


func isTimeout(err error) bool { type timeout interface { Timeout() bool } te, ok := err.(timeout) return ok && te.Timeout() } 

La persona que llama puede usar isTimeout () para determinar si el error se agotó al implementar la interfaz de tiempo de espera, y luego confirmar si el error se agotó, todo sin saber nada sobre el tipo o la fuente valores de error


Este método hace posible envolver errores, como regla, con bibliotecas que agregan explicaciones a la ruta de error; siempre que los tipos de error envueltos también implementen las interfaces de error que envuelven.


Esto puede parecer un problema insoluble, pero en la práctica hay bastantes métodos de interfaz generalmente aceptados, por lo que Timeout () bool y Temporary () bool cubrirán una amplia gama de casos de uso.


En conclusión


Confirme el comportamiento esperado, no el tipo de error


Para autores de paquetes


Si su paquete genera errores de naturaleza temporal, asegúrese de devolver los tipos de error que implementan los métodos de interfaz adecuados. Si ajusta los valores de error de salida, asegúrese de que sus contenedores soporten las interfaces con las que se implementa el valor de error original.


Para usuarios de paquetes


Si necesita verificar un error, use las interfaces para confirmar el comportamiento esperado, no el tipo de error. No pregunte a los autores de paquetes sobre los tipos de error abiertos; pídales que alineen sus tipos con interfaces comunes especificando los métodos Timeout () o Temporary (), según corresponda.


Sobre el autor


El autor de este artículo, Dave Cheney , es autor de muchos paquetes populares para Go, por ejemplo, https://github.com/pkg/errors y https://github.com/davecheney/httpstat .


Del traductor


Aunque el artículo original data de finales de 2014, me parece que no ha perdido su relevancia. El enfoque descrito se encuentra en algunos paquetes, mientras que el resto usa el enfoque habitual para errores.


¡Las modificaciones al texto para aumentar la claridad del material son bienvenidas!

Source: https://habr.com/ru/post/440818/


All Articles