todas tipos propagacion programacion para numeros negativos manejo las excepciones ejemplos clase arbol java exception return-type control-flow

java - propagacion - tipos de excepciones en programacion



¿Cómo puedo evitar el uso de excepciones para el control de flujo? (11)

¿Cuán estricto es el requisito para la firma de ese método?

Parece que estás trabajando en un proyecto que aún está en progreso. Si los consumidores de su clase son otros desarrolladores, ¿puede convencerlos de que la firma del método que han solicitado es insuficiente? Quizás todavía no se hayan dado cuenta de que debe haber dos modos de falla únicos (la clave no existe y el objeto no se ha modificado).

Lo discutiría con su supervisor si esa es una opción.

Se me ha asignado un proyecto para desarrollar un conjunto de clases que actúen como interfaz para un sistema de almacenamiento. Un requisito es que la clase sea compatible con un método get con la siguiente firma:

public CustomObject get(String key, Date ifModifiedSince)

Básicamente, se supone que el método devuelve CustomObject asociado con la key si y solo si el objeto se ha modificado después de ifModifiedSince . Si el sistema de almacenamiento no contiene la key , el método debe devolver nulo.

Mi problema es este:

¿Cómo manejo el escenario donde la clave existe pero el objeto no ha sido modificado?

Esto es importante porque algunas aplicaciones que usan esta clase serán servicios web y aplicaciones web. Esas aplicaciones necesitarán saber si se devuelve un 404 (no encontrado), 304 (no modificado) o 200 (bien, aquí están los datos).

Las soluciones que estoy pesando son:

  1. Lanzar una excepción personalizada cuando el sistema de almacenamiento no contiene la key
  2. Lanza una excepción personalizada cuando ifModifiedSince falla.
  3. Agregue una propiedad de estado al CustomObject. Requerir que quien llama verifique la propiedad.

No estoy contento con ninguna de estas tres opciones. No me gustan las opciones 1 y 2 porque no me gusta usar excepciones para el control de flujo. Tampoco me gusta devolver un valor cuando mi intención es indicar que no hubo ningún valor .

No obstante, me inclino por la opción 3.

¿Hay alguna opción que no esté considerando? ¿Alguien tiene sentimientos fuertes sobre cualquiera de estas tres opciones?

Respuestas a esta pregunta, parafraseada:

  1. Proporcione un método contains y solicite que la persona que llama lo llame antes de llamar a get(key, ifModifiedSince) , get(key, ifModifiedSince) excepción si la clave no existe, devuelva null si el objeto no se ha modificado.
  2. Envuelva la respuesta y los datos (si los hay) en un objeto compuesto.
  3. Use una constante predefinida para indicar algún estado ( UNMODIFIED, KEY_DOES_NOT_EXIST ).
  4. La persona que llama implementa la interfaz para ser utilizada como devolución de llamada.
  5. El diseño apesta.

Por qué no puedo elegir la respuesta n. ° 1

Estoy de acuerdo en que esta es la solución ideal, pero fue una que ya dejé (a regañadientes) destituir. El problema con este enfoque es que en la mayoría de los casos en los que se utilizarán estas clases, el sistema de almacenamiento de fondo será un sistema remoto de terceros, como Amazon S3. Esto significa que un método contains requeriría un viaje de ida y vuelta al sistema de almacenamiento, que en la mayoría de los casos sería seguido por otro viaje de ida y vuelta. Debido a que esto costaría tiempo y dinero , no es una opción.

Si no fuera por esa limitación, este sería el mejor enfoque.

(Me doy cuenta de que no mencioné este importante elemento en la pregunta, pero estaba tratando de mantenerlo breve. Obviamente era relevante).

Conclusión:

Después de leer todas las respuestas, llegué a la conclusión de que un envoltorio es el mejor enfoque en este caso. Básicamente imitaré HTTP, con metadatos (encabezados) que incluyen un código de respuesta y cuerpo de contenido (mensaje).


Aún así regresaría nulo.

La intención de la propiedad es devolver el objeto que se modificó después de la fecha especificada. Si devolver nulo para ningún objeto está bien, entonces seguramente devolver nulo para un objeto no modificado también está bien.

Personalmente devolvería null para un objeto no modificado y lanzaría una excepción para un objeto no existente. Eso parece más natural.

Estás en lo cierto al no usar excepciones para control de flujo por cierto, así que si solo tienes esas 3 opciones, tu instinto es correcto.


Buscar un objeto que no existe me parece un caso excepcional. Junto con un método que permite a la persona que llama determinar si existe un objeto, creo que estaría bien lanzar la excepción cuando no lo haga.

public bool exists( String key ) { ... }

La persona que llama podría hacer:

if (exists(key)) { CustomObject modified = get(key,DateTime.Today.AddDays(-1)); if (modified != null) { ... } } or try { CustomObject modified = get(key,DateTime.Today.AddDays(-1)); } catch (NotFoundException) { ... }


El problema con las excepciones es que están destinadas a indicar un escenario de "falla rápida" (es decir, si no se procesa, una excepción detendrá una aplicación) debido a un comportamiento excepcional y anormal .

No creo que "el escenario donde existe la clave pero el objeto no se haya modificado" sea excepcional, ciertamente no anormal.

Por lo tanto, no utilizaría la excepción, sino que documentaría la acción que la persona que llama debe hacer para interpretar correctamente el resultado (propiedad u objeto especial).


La interfaz (prevista) con respecto a los requisitos está seriamente rota. Intentas hacer cosas no relacionadas dentro de un método. Este es el camino al infierno del software.


Parece que realmente desea devolver dos elementos: el código de respuesta y el objeto encontrado. Puede considerar crear un envoltorio liviano que contenga ambos y devolverlos juntos.

public class Pair<K,V>{ public K first; public V second; }

Luego puede crear un nuevo par que contenga su código de respuesta y los datos. Como efecto secundario al uso de genéricos, puedes reutilizar este envoltorio para el par que realmente necesites.

Además, si los datos no han expirado, aún puede devolverlos, pero proporcióneles un código 303 para informarles que no ha cambiado. La serie 4xx se emparejaría con null .


Puede crear un CustomObject final especial como un "marcador" para indicar sin cambios:

static public final CustomObject UNCHANGED=new CustomObject();

y prueba una coincidencia con "==" en lugar de .equals ().

También podría funcionar para devolver null en sin cambios y lanzar una excepción en no existe? Si tuviera que elegir uno de los 3, elegiría 1 porque ese parece el caso más excepcional.


Puede seguir el patrón de la biblioteca .Net y tener un campo público de solo lectura estático en el objeto personalizado llamado CustomObject.Empty que es de tipo CustomObject (como string.Empty y Guid.Empty). Puede devolver esto si el objeto no se modifica (el consumidor de la función deberá compararlo).
Editar: Acabo de descubrir que estás trabajando en Java, pero el principio aún se aplica

Esto le da la opción de lo siguiente

  • Devuelve nulo si la clave no existe.

  • Devuelve CustomObject.Empty si la clave existe pero el objeto no se ha modificado.

El inconveniente es que el consumidor debería saber la diferencia entre un valor de retorno nulo y un valor de retorno CustomObject.Empty.

Tal vez la propiedad se llamaría CustomObject.NotModified como Empty realmente está pensada para tipos de valor ya que no pueden ser nulos. También NotModified transmitiría el significado del campo más fácilmente al consumidor.


Si es aceptable, puede devolver un CustomObject amplificado (un contenedor), que contenía valores que representaban el objeto y su estado de modificación, si lo hubiera, etc.


Proporcione una devolución de llamada como el argumento donde la clase de devolución de llamada podría ser impulsada por eventos o por el sistema.

Usted tiene la interfaz de su clase para definir los diversos errores que pueden ocurrir, pasando el CustomObject como el parámetro para el evento, si es necesario.

public interface Callback { public void keyDoesNotExist(); public void notModified(CustomObject c); public void isNewlyModified(CustomObject c); . . . }

De esta forma, permite que el implementador de la interfaz Callback defina qué hacer cuando ocurre el evento, y puede elegir a través de la interfaz, si esas condiciones requieren el paso del objeto recuperado. Por último, reduce la complejidad de la lógica en un retorno. Tu método hace eso una vez. Los implementadores de la API no requieren hacerlo en absoluto, ya que está hecho para ellos.


Con el requisito dado, no puedes hacer esto.

Si diseñó el contrato , agregue una condición y haga que la persona que llama invoque

exists(key): bool

La implementación del servicio se ve así:

if (exists(key)) { CustomObject o = get(key, ifModifiedSince); if (o == null) { setResponseCode(302); } else { setResponseCode(200); push(o); } } else { setResponseCode(400); }

El cliente permanece sin cambios y nunca nota que ha validado por adelantado.

Si no diseñó el contrato Probablemente haya una buena razón para eso o, probablemente, solo sea la falla del diseñador (o arquitecto). Pero como no puedes cambiarlo, tampoco tienes que preocuparte.

Entonces debe cumplir con las especificaciones y proceder de esta manera:

CustomObject o = get(key, ifModifiedSince); if (o != null) { setResponseCode(200); push(o); } else { setResponseCode(404); // either not found or not modified. }

Ok, no estás enviando 302 en este caso, pero probablemente esa es la forma en que fue diseñado.

Quiero decir, por razones de seguridad, el servidor no debería devolver más información que eso [la sonda es get (clave, fecha) solo devuelve nulo u objeto]

Entonces no te preocupes por eso Hable con su gerente y hágale saber esta decisión. Comenta el código con esta decisión también. Y si tiene el arquitecto en mano, confirme los motivos de esta extraña restricción.

Lo más probable es que no haya visto venir esto y puedan modificar el contrato después de su sugerencia.

A veces, si queremos proceder correctamente, podemos proceder mal y poner en peligro la seguridad de nuestra aplicación.

Comunícate con tu equipo.