La mejor manera de estado de la devolución de la bandera y el mensaje de un método en Java

StackOverflow https://stackoverflow.com/questions/356248

  •  21-08-2019
  •  | 
  •  

Pregunta

Tengo un engañosamente simple escenario, y quiero una solución simple, pero no es obvio que es "más correcta" o "la mayoría de Java".

Digamos que tengo un pequeño autenticar(Cliente cliente) método en la clase.La autenticación puede fallar por un número de razones, y quiero devolver un booleano simple para el control de flujo, sino también devolver una Cadena de mensajes para el usuario.Estas son las posibilidades que puedo pensar:

  • Devolver un valor booleano, y pasar un StringBuilder para recoger el mensaje.Esto es lo más cercano a un C-estilo de la manera de hacerlo.
  • Lanzar una excepción en lugar de devolver false, e incluir el mensaje.No me gusta esto ya que el fracaso no es excepcional.
  • Crear una nueva clase llamada AuthenticationStatus con el operador booleano y la Cadena.Esto parece excesivo para un pequeño método.
  • El mensaje se almacene en una variable miembro.Esto introduciría una posible condición de carrera, y no me gusta que implica un estado que en realidad no existe.

Otras sugerencias?

Editar Pasada esta opción desactivada

  • Devolver un valor nulo para el éxito - Es esto peligroso?

Editar Solución:

Me fui para la mayoría de los OO solución y crearon una pequeña AuthenticationResult clase.Yo no haría esto en cualquier otro idioma, pero me gusta en Java.También me gustó la sugerencia de devolver un String[] ya que es como la nula rentabilidad, pero más seguro.Una de las ventajas de que el Resultado de la clase es que usted puede tener un mensaje de éxito con más detalles si es necesario.

¿Fue útil?

Solución

La devolución de un objeto pequeño tanto con la bandera booleana y la cadena en el interior es probablemente la forma más OO-como de hacerlo, aunque estoy de acuerdo que parece excesivo para un caso sencillo como esto.

Otra alternativa es volver siempre una cadena, y tienen nula (o una cadena vacía - a elegir qué) indican el éxito. Mientras los valores de retorno se explican claramente en las javadocs no debería haber ninguna confusión.

Otros consejos

Se puede usar excepciones ....

try {
    AuthenticateMethod();
} catch (AuthenticateError ae) {         
    // Display ae.getMessage() to user..
    System.out.println(ae.getMessage());
    //ae.printStackTrace();    
}

y luego, si se produce un error en su AuthenticateMethod se envía un nuevo AuthenticateError (se extiende Excepción)

Evitar la devolución de un "valor de centinela", especialmente null.Usted va a terminar con un código base donde los métodos no puede ser entendido por la persona que llama sin la lectura de la aplicación.En el caso de nulo, las personas que llaman pueden acabar con NullPointerExceptions si se olvidan (o no sabe) que su método puede devolver null.

La tupla sugerencia de Bas Leijdekkers es una buena que yo uso todo el tiempo si quiero devolver más de un valor a partir de un método.La que utilizamos es P2<A, B> a partir de la Funcional Java biblioteca.Este tipo de es un tipo de conjunto de la unión de otros dos tipos (que contiene un valor de cada tipo).

Lanzar Excepciones para el control de flujo es un poco de un código de olor, pero excepciones comprobadas son una manera de obtener más de un tipo de valor a partir de un método.Otros, limpiador de posibilidades aunque existen.

  1. Usted puede tener un Option<T> clase abstracta con dos subclases Some<T> y None<T>.Esto es un poco como un tipo de alternativa segura a null, y una buena manera de implementar funciones parciales (funciones cuyo valor de retorno no está definido para algunos argumentos).El Funcional Java la biblioteca dispone de un completo Option clase que implementa Iterable<T>, por lo que se puede hacer algo como esto:

    public Option<String> authenticate(String arg) {
       if (success(arg))
          return Option.some("Just an example");
       else
          return Option.none();
    }
    
    ...
    
    for(String s : authenticate(secret)) {
       privilegedMethod();
    }
    
  2. Alternativamente, puede utilizar un discontinuo de la unión de dos tipos, como Either<L, R> clase.Contiene un valor que es de tipo L o R.Esta clase implementa Iterable<T> para ambos L y R, por lo que se puede hacer algo como esto:

    public Either<Fail, String> authenticate(String arg) {
       if (success(arg))
          return Either.right("Just an example");
       else
          return Either.left(Fail.authenticationFailure());
    }
    
    ...
    
    Either<Fail, String> auth = authenticate(secret);
    for(String s : auth.rightProjection()) {
       privilegedMethod();
    }
    for(Fail f : auth.leftProjection()) {
       System.out.println("FAIL");
    }
    

Todas estas clases, P2, Option, y Either son útiles en una amplia variedad de situaciones.

Algunos más opciones:

  • devolver un valor enum separado para cada tipo de fallo. El objeto enum podría contener el mensaje
  • Vuelta un int y tener un método independiente que busca el mensaje apropiado de una matriz
  • crear una clase tupla utilidad genérica que puede contener dos valores. una clase de este tipo puede ser útil en muchos más lugares.

tupla ejemplo simple, la implementación real puede necesitar más:

class Tuple<L, R> {

    public final L left;
    public final R right;

    public Tuple( L left, R right) {
        this.left = left;
        this.right = right;
    }
}

Se puede devolver una colección de mensajes de error, vacío que indica que no hubo ningún problema. Este es un refinamiento de su tercera sugerencia.

Yo personalmente creo que la creación de una nueva clase llamada AuthenticationStatus con el booleano y la cadena es el más Java como camino. Y si bien parece un exceso (que bien puede ser) parece más limpio para mí y más fácil de entender.

El hecho de que la autenticación no es un lugar común no quiere decir que no es excepcional.

En mi opinión, los errores de autenticación son los cartel-hijo de casos de uso para las excepciones controladas. (Bueno ... tal vez el archivo no existencia es el caso de uso canónica, pero el fracaso de autenticación es una estrecha # 2.)

Yo uso la "pequeña clase" a mí mismo, por lo general con una clase interna. No me gusta usar argumentos para recolectar mensajes.

Además, si el método que podría fallar es "bajo nivel" - como procedente de un servidor de aplicación o la capa de base de datos, preferiría volver a una enumeración con el estado de retorno, y luego traducir eso en una cadena en el nivel de interfaz gráfica de usuario. No pasar alrededor de cadenas de usuarios a nivel bajo si alguna vez va a internacionalizar su código, porque entonces el servidor de aplicación sólo puede responder de un idioma a la vez, en lugar de tener diferentes clientes que trabajan en diferentes idiomas.

Es este el único método en el que tiene tal requisito? Si no, simplemente generar una clase de respuesta general, con una bandera isSuccessful y una cadena de mensaje, y el uso que en todas partes.

O usted podría tener el método devuelto nulo para mostrar el éxito (no es bonito, y no permite devolver un éxito y un mensaje).

Me lo más probable ir para algo como:


class SomeClass {
public int authenticate (Client client) {
//returns 0 if success otherwise one value per possible failure
}
public String getAuthenticationResultMessage (int authenticateResult) {}
//returns message associated to authenticateResult
}

Con este "diseño", que se puede pedir un mensaje sólo cuando falla la autenticación (que espero es el escenario que se produce 99,99% del tiempo;))

También puede ser de buenas prácticas para delegar resolución mensaje a otra clase. Pero depende de sus necesidades de aplicación (en su mayoría, no lo necesitan i18n?)

Esto parece como un lenguaje común en otros lenguajes de programación, pero no puedo averiguar cuál (C supongo que como he leído en la pregunta).

aquí y aquí

intentar devolver dos valores a partir de una sola función, puede ser engañosa. Pero, como se ha demostrado por los intentos de hacerlo, puede ser muy útil también.

Sin duda, la creación y la pequeña clase con los resultados debe ser la forma correcta de proceder en caso de que es un flujo común en la aplicación tal como fue anunciado antes.

He aquí una cita de volver dos valores de una función:

  

Como una cuestión de estilo de programación, esta idea no es   apelando en un lenguaje de programación orientado a objetos.   Volviendo objetos para representar los resultados del cálculo   es la modismo para devolver varios valores. Algunos   sugerir que usted no debería tener que declarar clases   para los valores no relacionados, pero tampoco debe no relacionada   valores devueltos desde un único método.

Lo he encontrado en una de estas solicitudes para Java para permitir de retorno múltiple valores

vistazo a la sección de "evaluación" de fecha: 2005-05-06 09:40:08

La autenticación exitosa debería ser el caso "normal", por lo que un error de autenticación es el caso excepcional.

¿Cuáles son las diferentes cadenas de estado para el usuario de todas formas. Puedo ver sólo dos, éxito o fracaso. Cualquier información adicional es un problema de seguridad potencial. Otra ventaja de la solución con excepciones es que no se puede llamar de manera incorrecta y el caso de fracaso es más evidente. Sin excepciones, se escribe:

if (authenticate()) {
  // normal behaviour...
}
else {
  // error case...
}

Puede accidentalmente llamar al método ignorando el valor de retorno. El código "comportamiento normal" se ejecuta a continuación, sin autenticación exitosa:

authenticate();
// normal behaviour...

Si utiliza excepciones, eso no puede suceder. Si decide no utilizar excepciones, al menos el nombre del método de manera que es evidente que devuelve un estado, e. g:.

if (isAuthenticated()) {
//...
}

Hay un montón de buenas respuestas aquí, así que tendrán que sea breve.

Creo que el fracaso de un usuario para autenticar puede ser considerado un caso válido para una excepción comprobada. Si su estilo de programación a favor de manejo de excepciones entonces no habría ninguna razón para no hacerlo. También elimina el "Cómo devolver múltiples valores de un método, mi método hace una cosa que autentica a un usuario"

Si va a devolver múltiples valores a continuación, pasan 10 minutos creando una PairTuple genérico (también puede ser más que un par TripleTuple, no voy a repetir el ejemplo que aparece más arriba) y devolver los valores de esa manera. Odio tener pequeños objetos de estilo dto para devolver varios valores múltiples que sólo el desorden del lugar.

¿Qué hay de devolver una cadena. Vacío o nulo para el éxito. Mensaje de error en caso de fallo. Más simple que eso funcionaría. Sin embargo no estoy seguro si se lee bien.

devolver el objeto. Se le permite poner una funcionalidad adicional en la clase si lo necesita. objetos de corta vida en Java son rápidos para crear y recoger.

Yo elegiría la opción Excepción en primer lugar.

Pero, en segundo lugar, yo preferiría la técnica de estilo C:

public boolean authenticate(Client client, final StringBuilder sb) {
    if (sb == null)
        throw new IllegalArgumentException();
    if (isOK()) {
        sb.append("info message");
        return true;
    } else {
        sb.append("error message");
        return false;
    }
}

Esto no es tan extraño y se hace en muchos lugares en el marco.

En lugar de crear un objeto especial para el tipo de retorno, por lo general sólo devolver una matriz donde se almacena toda la información devuelta. La ventaja es que se puede ampliar esta gama con nuevos elementos sin crear nuevos tipos y desorden. El inconveniente que tiene que saber exactamente lo que deben presentar los elementos cuando matriz se volvió del método particular para analizar correctamente. Por lo general, estoy de acuerdo en cierta estructura, como primer elemento es siempre el éxito indicación de Boole, el segundo es String con la descripción, el resto es opcional. Ejemplo:

public static void main(String[] args)
{
    Object[] result = methodReturningStatus();
    if(!(Boolean)result[0])
        System.out.println("Method return: "+ result[1]);
}

static Object[] methodReturningStatus()
{
    Object[] result = new Object[2];

    result[0] = false;
    result[1] = "Error happened";

    return result;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top