La función de mi verificador de valores debe devolver tanto un valor booleano como un mensaje

14

Tengo una función de verificación de valor, algo muy parecido a una función de verificación de número de tarjeta de crédito, que se pasa en una cadena y necesita verificar que el valor tenga el formato correcto.

Si es el formato correcto, necesita devolver verdadero.

Si no es el formato correcto, debe devolver el valor falso y también indicarnos qué tiene de malo el valor.

La pregunta es, ¿cuál es la mejor manera de lograr esto?

Aquí hay algunas soluciones:

1. Utilice códigos de retorno de enteros / enumeración para indicar significados:

String[] returnCodeLookup = 
[
"Value contains wrong number of characters, should contain 10 characters",
"Value should end with 1", 
"Value should be a multiple of 3"
]

private int valueChecker(String value)
{
    /*check value*/
    return returnCode;
}

rc = checkValue(valueToBeChecked);
if rc == 0
{
    /*continue as normal*/
}
else
{
    print("Invalid value format: ") + returnCodeLookup[rc];
}

No me gusta esta solución, ya que requiere implementación en el lado del que llama.

2. Crea una clase de código de retorno

Class ReturnCode()
{
    private boolean success;
    private String message;

    public boolean getSuccess()
    {
        return this.success;
    }

    public String getMessage()
    {
        return this.message; 
    }
}

private ReturnCode valueChecker(String value)
{
    /*check value*/
    return returnCode;
}

rc = checkValue(valueToBeChecked);
if rc.getSuccess()
{
    /*continue as normal*/
}
else
{
    print("Invalid value format: ") + rc.getMessage();
}

Esta solución está ordenada, pero parece una exageración / reinvención de la rueda.

3. Utilizar excepciones.

private boolean valueChecker(String value)
{
    if int(value)%3 != 0 throw InvalidFormatException("Value should be a multiple of 3";
    /*etc*/
    return True;
}

try {
rc = checkValue(valueToBeChecked);
}

catch (InvalidFormatException e)
{
     print e.toString();
}

Estoy tentado a usar esta solución, pero me dicen que no debe usar excepciones para la lógica de negocios.

    
pregunta dwjohnston 23.02.2015 - 00:00

3 respuestas

14

Utilice un objeto de retorno más complejo que encapsule ambas preocupaciones. Ejemplo:

public interface IValidationResult {
  boolean isSuccess();
  String getMessage();
}

Esto tiene varias ventajas:

  1. Devuelve múltiples datos relacionados en un objeto.
  2. Espacio para la expansión si necesita agregar datos adicionales en el futuro.
  3. No confíe en el acoplamiento temporal: puede validar múltiples entradas y no obstruyen el mensaje como en la otra respuesta. Puede revisar los mensajes en cualquier orden, incluso en subprocesos.

En realidad he usado este diseño específico anteriormente, en aplicaciones donde una validación puede ser más que simplemente verdadera o falsa. Quizás sea necesario un mensaje detallado, o solo una parte de la entrada no es válida (por ejemplo, un formulario con diez elementos puede tener solo uno o dos campos no válidos). Usando este diseño, puede acomodar fácilmente esos requisitos.

    
respondido por el user22815 23.02.2015 - 03:36
2

Ninguna de las anteriores, usa una clase de ValueChecker

Primero una interfaz para darle flexibilidad:

public interface IValueChecker {
    public boolean checkValue(String value);
    public String getLastMessage();
}

Luego implemente tantos valuecheckers como necesite:

public class MyVeryEspecificValueChecker implements IValueChecker {
    private String lastMessage="";
    @Override
    public boolean checkValue(String value) {
        boolean valid=false;
        // perform check, updates "valid" and "lastMessage"
        return valid;
    }
    @Override
    public String getLastMessage() {
        return lastMessage;
    }
}

Código de cliente de muestra:

public class TestValueChecker {
    public static void main(String[] args) {
        String valueToCheck="213123-YUYAS-27163-10";
        IValueChecker vc = new MyVeryEspecificValueChecker();
        vc.checkValue(valueToCheck);
        System.out.println(vc.getLastMessage());
    }
}

Tiene la ventaja de que puedes tener muchos verificadores de valor diferentes.

    
respondido por el Tulains Córdova 23.02.2015 - 00:24
1

Mi respuesta extiende el enfoque de @ Snowman. Básicamente, cada validación, cada regla de negocio y cada lógica de negocio deberían ser capaces de dar alguna respuesta, al menos en aplicaciones web. Esta respuesta, a su vez, se muestra a una persona que llama. Esto me llevó a la siguiente interfaz (es php, pero la pregunta es de lenguaje independiente):

interface Action
{
    /**
     * @param Request $request
     * @throws RuntimeException
     * @return Response
     */
    public function act(Request $request);
}

La creación de un operador de switch que actúa como una expresión, no como una declaración, hace que el servicio de la aplicación se vea así:

class MyApplicationService implements Action
{
    private $dataStorage;

    public function __construct(UserDataStorage $dataStorage)
    {
        $this->dataStorage = $dataStorage;
    }

    public function act(Request $request)
    {
        return
            (new _SwitchTrue(
                new _Case(
                    new EmailIsInvalid(),
                    new EmailIsInvalidResponse()
                ),
                new _Case(
                    new PasswordIsInvalid(),
                    new PasswordIsInvalidResponse()
                ),
                new _Case(
                    new EmailAlreadyRegistered($this->dataStorage),
                    new EmailAlreadyRegisteredResponse()
                ),
                new _Default(
                    new class implements Action
                    {
                        public function act(Request $request)
                        {
                            // business logic goes here

                            return new UserRegisteredResponse();
                        }
                    }
                )
            ))
                ->act($request)
            ;
    }
}
    
respondido por el Zapadlo 30.11.2017 - 19:17

Lea otras preguntas en las etiquetas