leanmind logo leanmind text logo

Blog

BDD

Behaviour-driven Development es una técnica para tomar mejores requisitos de producto.

Los intocables de la programacion

Por Luis Rodriguez

Como LeanMinders siempre estamos aprendiendo cómo hacer mejor las cosas, de esta manera podemos aportar el máximo valor a nuestros colaboradores.
Muchas veces ese aprendizaje es por medio de la práctica deliberada de katas, pero otras veces aprendemos de la mano de nuestros clientes.

Uno de los principios más importantes en la programación es el principio de mínima sorpresa, o también llamado Principle Of Least Astonishment, o simplemente principio POLA.
La idea central de este principio, es que todo tiene que ser obvio, de lo contrario, nos podemos llevar una desagradable sorpresa. La razón de este principio, radica en que el cerebro humano sólo puede centrarse en una sola cosa a la vez.

Hace unas semanas estábamos trabajando en un código legado, intentando solucionar una incidencia y de pronto, nos encontramos con un código parecido al siguiente:

namespace Client.Project.User.SignUp
{
    public class SignUpService
    {
        private readonly IUserRepository userRepository;
    
        public SignUpService(IUserRepository userRepository)
        {
            this.userRepository = userRepository;
        }
    
        public string SignUp(UserSignUpArgs args)
        {
            if (userRepository.Exist(args.Email))
                return "user doesn't exist";
    
            var user = new Model.User(email: args.Email, password: args.Password);
    
            userRepository.Save(user);
    
            args.UserCreated = true;
    
            return string.Empty;
        }
    }
    
    public class UserSignUpArgs
    {
        public string Email { get; }
        public string Password { get; }
        public bool UserCreated { get; set; }
    
        public UserSignUpArgs(string email, string password)
        {
            Email = email;
            Password = password;
        }
    }
    
    public interface IUserRepository
    {
        bool Exist(string email);
        void Save(Model.User user);
    }
}

Como podemos observar, tiene como colaborador un repositorio, para interactuar con el sistema de persistencia y el propio servicio que realiza la operación de registrar un nuevo usuario.
En principio todo parece normal. Básicamente registra un usuario.

 public string SignUp(UserSignUpArgs args)
 {
     if (userRepository.Exist(args.Email))
         return "user doesn't exist";
    
     var user = new Model.User(email: args.Email, password: args.Password);
    
     userRepository.Save(user);
    
     args.UserCreated = true;
    
     return string.Empty;
 }

Si observamos con detenimiento, podemos ver que el parámetro de entrada UserSignUpArgs, también hace las funciones de parámetro de salida, cuando actualiza la propiedad UserCreated a true.

Podemos afirmar que está rompiendo el principio de mínima sorpresa, porque no esperamos que un parámetro de entrada, sirva también como parámetro de salida. En realidad los parámetros de entrada deberían ser inmutables, para evitar este tipo de situaciones, como pasa en lenguajes tan populares como kolin o typescript entre otros.
Rompiendo este principio, hacemos que el código sea más complicado de mantener y de entender, reduciendo su calidad.

Si seguimos analizando este código, podemos darnos cuenta de que se están mezclando niveles de abstracción distintos en el mismo método, como es el uso de repositorio y la cadena de caracteres como resultado de la operación.
Una frase (cadena de caracteres) indica que debería de estar en un componente relacionado con la interfaz de usuario, más que con la lógica propia del negocio.

Una primera alternativa a este código, podría ser el siguiente:

public void SignUp(UserSignUpArgs args)
{
    if (userRepository.Exist(args.Email))
        throw new ArgumentException();
    
    var user = new Model.User(email: args.Email, password: args.Password);
    
    userRepository.Save(user);
}

Dejando el uso de excepciones sólo para casos excepcionales, podemos hacer uso de la mónada either, que nos facilita cuando ha ido bien o mal la operación a realizar.

public Either<Error, UserSignedUpSuccess> SignUp(UserSignUpArgs args)
{
    if (userRepository.Exist(args.Email))
        return Either<Error, UserSignedUpSuccess>.Error(new Error(Errors.UserAlreadyexist))
    
    var user = new Model.User(email: args.Email, password: args.Password);
    
    userRepository.Save(user);
    Either<Error, UserSignedUpSuccess>.Success(new UserSignedUpSuccess())
}

Conclusión:
Es mejor mantener inmutables los parámetros a los métodos/funciones, de esta manera, no tendremos sorpresas desagradables y nuestro código será más sostenible.

Happy coding!!!

Referencias:
Principle Of Least Astonishment
The Art of Unix Programming, chapter 11 “Applying the Rule of Least Surprise”
Diseño Ágil con TDD edición 2020, página 66
Código Sostenible, página 61

Publicado el 13/11/2024 por
Luis image

Luis Rodriguez

¿Quieres más? te invitamos a suscribirte a nuestro boletín para avisarte cada vez que recopilemos contenido de calidad que compartir.

Si disfrutas leyendo nuestro blog, ¿imaginas lo divertido que sería trabajar con nosotros? ¿te gustaría?

Impulsamos el crecimiento profesional de tu equipo de developers