sábado, 30 de junho de 2012

Validação do CNS (Cartão Nacional de Saúde)


Durante a semana que passou tive que implementar um código para validar o número do CNS (Cartão Nacional de Saúde), que passará a ser obrigatório a todos os brasileiros. O próprio site do SUS apresenta um exemplo em Java (e em outras linguagens).

Utilizei o código de exemplo, mas na minha opinião ele está tão mal feito que isso passou a manhã inteira me atormentando. Fiquei tentando me convencer de que "você tem um prazo para cumprir, o importante é funcionar", mas não consegui. Logo depois do almoço tive que refazê-lo. O relevante é que se você analisar o código para verificar "o que ele deve fazer", ao invés do "como fazer", perceberá que é algo extremamente simples. Passei de 93 linhas para as 15 abaixo.

Código bem-feito:

O projeto que contém este código, os testes e outras benesses está disponível em https://github.com/insula/opes

Para quem tiver curiosidade em saber como é o código original no site do SUS, segue abaixo. Mas cuidado! Pode causar náuseas e vômitos. Se tiver estômago forte, pode seguir adiante...

Código "normal":

6 comentários:

  1. Só uma palavra: regex
    Ótima refatoração!

    ResponderExcluir
  2. Cara estou precisando de um código que faça o reverso, ou seja que gere os números. Poderia me sugerir alguma coisa?

    ResponderExcluir
    Respostas
    1. Você está querendo gerar códigos de Cartão Nacional de Saúde válidos? Porque???

      Excluir
    2. O código do exemplo somente valida, mas se quiser gerar os números basta eliminar o último dígito e fazer a somaPonderada % 11 ser igual a 0.

      Excluir
  3. Parabéns por disponibiliza e refatorar o código. Muito bom seu trabalho.

    ResponderExcluir
  4. Baseado no seu exemplo, e fiz uma versão um pouco mais compacta para js:

    validarCNS: function (numero) {
    const vetNumero = numero.split('')
    if (numero.match(/[1-2]\d{10}00[0-1]/) || numero.match(/[7-9]\d{14}/))
    return vetNumero.reduce((soma, valor, indice) =>
    soma + parseInt(valor) * (15 - indice), 0) % 11 === 0
    return false

    ps.: eu não sei como habilitar texto como codigo aqui :v

    ResponderExcluir