Evitando Hadouken de Ifs

por Fabio A. Mazzarino

Hadouken de Ifs nasceu de um meme, ilustrado abaixo. Basicamente é um conjunto de ifs aninhados, normalmente um conjunto de validações, que, por conta de inexperiência ou inabilidade do desenvolvedor, acaba por formar uma estrutura difícil de compreender e consequentemente mais difícil de ser mantida, implicando em maiores custos de manutenção do código.

Hadouken de ifs

No caso do meme que ficou famoso o código está em PHP e demonstra um conjunto de ifs aninhados que validam um POST de um usuário. A cada sucesso é necessário passar para à próxima validação, e em caso de falha é necessária uma mensagem de erro específica.

A principal regra a qual o desenvolvedor não se atentou foi a de Falhar Primeiro. Essa técnica já foi abordada em outro post: Tratamento de Erro com C, e a principal consequência é exatamente o hadouken de ifs. Abaixo um trecho do código acima das cinco primeiras regras de validação:

std::string checkNewUser(std::map<std::string, std::string> post) {
    if (post.has_key("user_name"))
        if (post.has_key("user_password_new"))
            if (post["user_password_new"] == post["user_password_new"])
                if (post["user_password_new"].length() > 5)
                    if (post["user_name"].length() > 1 && post["user_name"] < 65)
                        return "";
                    else 
                        return "Username must be between 2 and 64 characters";
                else 
                    return "Password must be at least 6 characters";
            else 
                return "Passwords does not match";
        else 
            return "Empty Password";
    else 
        return "Empty Username";
}
                    

No código do meme são 10 regras, mas não é necessário reproduzir todas para ilustrar a solução.

Como Evitar o Hadouken de Ifs?

A solução segue a regra do Falhar Primeiro: uma função deve falhar o mais rapidamente possível para evitar processamento desnecessário e para tornar a manutenção do código facilitada. Seguindo essa regra o código ficaria desta forma:

std::string checkNewUser(std::map<std::string, std::string> post) {
    if (!post.has_key("user_name"))
        return "Empty Username";
    if (!post.has_key("user_password_new"))
        return "Empty Password";
    if (post["user_password_new"] != post["user_password_new"])
        return "Passwords does not match";
    if (post["user_password_new"].length() < 6)
        return "Password must be at least 6 characters";
    if (post["user_name"].length() < 2 && post["user_name"].length > 64)
        return "Username must be between 2 and 64 characters";                        
    return "";
}

Note como o código ficou mais compacto, mais fácil de entender, e principalmente mais fácil de associar qual ação para cada validação. É um código mais maduro e que custa menos para ser mantido.

Profissionalmente

Times que não tomam ações contra Hadouken de Ifs tem dificuldades em dar manutenção no código. O código fica mais difícil de entender, aumentando o tempo de reposta em caso de melhorias ou correções. Também tem problemas em treinar novos desenvolvedores, aumentando o tempo de treinamento de novos programadores ingressando no time.

Até os anos 90 uma das métricas da qualidade de código era a quantidade de linhas. Atualmente a quantidade de linhas perdeu essa importância, esse indicador é mais utilizado para definir a complexidade e custo da manutenção, e auxiliando na definição do tamanho da equipe necessária para manter o sistema.

Um código de boa qualidade utiliza linhas em branco e comentáros para aumentar a visibilidade e facilitar sua compreensão. Mas investe na quantidade correta de código, balanceando visibilidade e quantidade de linhas.