Código conciso: claro e breve
Postado em 16. jun, 2011 por Guilherme Silveira em Agile, Inovação, Ruby
Há poucos anos, com a onda de novas linguagens, surgiram discussões defendendo código com a intenção de ser “conciso”.
Ser conciso é expressar muito, com poucas palavras; ser claro e sucinto; curto, mas com todas as informações necessárias; breve e claro. Note como todas as definições de concisão implicam em ser curto, mas também na clareza da informação. Dois fatores fundamentais para a busca do código de qualidade
Tomemos como exemplo o ato de salvar um usuário no único banco de dados acessado por uma aplicação:
user.saveInTheDatabase(database)
Ele é claro, e chega a ser até mesmo redundante uma vez que “tipifica” o nome do método ao repetir a palavra database. Já o código a seguir mantem a clareza relativa a responsabilidade citada, além de ser sucinto:
user.save
Em uma outra situação, o mesmo código acima pode ser implementado executando outras tarefas, como inserindo outros objetos relativos a um usuário:
def save
super
maquinas_a_instalar.each do |instancia|
cria_maquina_no_banco(instancia)
end
# ou qualquer outro tipo de efeito colateral
end
Agora o código anterior, continua sucinto mas já não é mais tão claro:
user.save
Ele não diz que faz o que realmente fará. A busca pelo código curto introduziu a possibilidade de engano daquele que vai ler, pior ainda, o nome do método e a maneira de implementá-lo levam ao erro: ele não é conciso, ele é somente breve.
Por isso alguns usos excessivos de técnicas avançadas, como AOP ou mesmo reflection, precisam de muito cuidado. Remotabilidade transparente, EJBs, JPA, ActiveResource e quaisquer outras bibliotecas que trabalham um serviço de maneira a ocultá-lo podem gerar problemas caso o usuário não tenha um certo conhecimento do efeito de suas chamadas. É o caso do excesso de invocações remotas ou de queries sqls, que os frameworks já citados podem trazer sem um conhecimento mais profundo..
Concisão não significa texto curto. Um dos grandes desafios de um autor é ser conciso, para não cansar seus leitores, mantendo a clareza de seu texto. Algumas linguagens ou até mesmo bibliotecas podem acelerar ou desacelerar o processo de falar algo com poucas palavras, o que não significa necessariamente o código mais fácil de entender e, consequentemente, de manter a longo prazo.
Escrever pouco – a métrica de linhas de código – traz o menor código, mas não necessariamente o mais claro ou melhor.
No exemplo a seguir, o cliente está sendo somente salvo ou algo mais está sendo feito e a “pseudo-concisão” está nos enganando?
cliente.save()
Guilherme Silveira (Google+)
12 Respostas para “Código conciso: claro e breve”
Trackbacks/Pingbacks
-
-
julho 18, 2012
[...] Na verdade isso pode ser ruim, pois bonito é muitas vezes diferente de um código com clareza e concisão, [...]

ASSINE NOSSO RSS
Fernando
16. jun, 2011
“No exemplo a seguir, o cliente está sendo salvo em um banco ou algo mais está sendo feito e a “pseudo-concisão” está nos enganando?”
Isso realmente importa? Não deveríamos estar programando para a abstração? Deveriamos ter métodos saveInDatabase, saveInTextFile,saveInCloud?
Reinaldo
16. jun, 2011
Esse assunto é bastante interessante !
No caso desse exemplo específico, ainda temos a “desculpa” de que é um requisito de infraestrutura que estamos atendendo(instâncias do banco, em outros casos replicação, etc…), e geralmente usamos apenas argumentos de negócio para determinar se o método é conciso ou não.
Mas existem N casos onde colocamos código de negócio em AOP ou outros recursos (before_filter, triggers do hibernate) o que confunde bastante o ato de persistir algo, eu sinceramente nunca achei uma maneira legal de deixar isso claro.
Alterar o nome do método toda vez que um novo recurso é utilizado, geralmente fica no esquecimento.
Documentar com testes, geralmente “mockamos” essa parte de AOP pra não atrapalhar a “unidade do teste” e ai fica “sem especificação”, e testes de integração por sua natureza de escopo maior, não testamos todo o código que já é testado unitariamente.
Sinceramente espero uma resposta bacana aqui nos comentários
Paulo Silveira
16. jun, 2011
@FernandoAnonimo Creio que o que Guilherme quis dizer nao foi em relacao ao saveBanco, saveCloud, saveNoTXT. Isto é, nao “como” ele faz, e sim “o que” ele faz, que é a discussao interface X implementacao. Seu nome de metodo+documentacao deve deixar claro o que o metodo faz, mas nao como ele faz. Efeitos colaterais, na minha opiniao, fazem sim parte de “”o que” ele faz, e deveriam ser claros para o programador. Obviamente ha uma linha tenue aqui.
@Reinaldo, tambem concordo com voce nessa parte do AOP, onde alguns chegam ate a colocar logica de negocios… e fica um codigo praticamente invisivel e de dificil tracking, como uma trigger pode ser no caso de tambem conter negocio.
Guilherme Silveira
16. jun, 2011
Oi @Fernando, você está certo sim. E está de acordo com o que quis dizer. Atualizei a frase para não ficar ambígua. O cliente está sendo salvo, como o método diz, ou muito mais do que isso está acontecendo? (não o como, mas o quê).
Rogério Yokomizo
16. jun, 2011
Se existe código dentro do método que faz algo além de sua intenção, então acho que existe um problema na definição da intenção desse método, não?
“O cliente está sendo salvo, como o método diz, ou muito mais do que isso está acontecendo?”
O que é salvar?
Acho que essa confusão existe pois “salvar” está presente em diversos níveis de abstração. Se estamos em um nível muito alto de abstração, então acho que o salvar vai fazer mesmo mais do que persistir os dados.
Bruno Tavares
16. jun, 2011
Muito bom, só que a questão citada continua em aberto. Seria bacana uma sugestão do autor. Deveria ser alterado o nome do método? Talvez complementar o significado com documentação? Abs
Marcio Lucca
17. jun, 2011
Acho que para conseguir ser realmente conciso é preciso se livrar dos efeitos colaterais. Aí entra o paradigma funcional que vem ganhando mais notoriedade ultimamente.
Guilherme Silveira
17. jun, 2011
@Bruno com certeza mudar o nome. Uma prática que costumo fazer com o pessoal é dar um nome bem infantil para um método novo que estou criando (desde fazOQueTemQueSerFeito até chocolate) e depois quando tenho o código funcionando passo a entender o que ele realmente faz e não o que eu esperava que ele faria. Ai renomeio para algo que faça sentido.
No caso que salva o usuário e ao mesmo tempo salva algumas máquinas novas, o nome do método poderia ser algo mais explicito como um simples (e bobo): “gravaComMaquinas”. Esse é um dos motivos para termos cuidado com cascade update.
Já o ultimo exemplo, onde questiono o que aquele método faz, o nome novo depende justamente do que ele faz. O ponto importante é sempre deixar claro o que ele faz (lembrando o que o Fernando disse, sem precisar deixar explícito “como” ele faz).
Abraço!
Guilherme Silveira
17. jun, 2011
@Marcio acho que no funcional ainda podemos executar mais do que estamos falando, mesmo sem efeito colateral. Por exemplo, quando uma função retorna uma estrutura onde duas entradas são novas mas seu nome não deixa isso claro.
Isso no exemplo de concisão relativo a valores, claro. Acho que ainda existe a questão da concisão em relação a invocações: encadeamentos longos e funções (ou métodos) grandes também dificultam a compreensão, independente de famílida de linguagem de programação. Não citei esse exemplo aqui, mas é o tradicional a.b.c.d em orientação a objetos ou d(c)(b)(a) em funcional.
Abraço
Márcio
17. jun, 2011
Num código de negócio, ocultar aspectos e explicitar a regra de negócio, observando o que diz o Reinaldo sobre não ser desejável implementar negócio via AOP.
Aspectos, em geral, são recorrentes dentro de uma arquitetura e, portanto, fáceis de serem inferidos.
Concordo plenamente que o código conciso deve dizer O QUE faz e vou além dizendo que ele deve, quando necessário, buscar dizer também PORQUE o faz e, em não raras vezes, REAFIRMAR porque o faz – quem nunca se deparou com uma regra de negócio estranhíssima? Está aí um bom uso de comentários.
Roberto Nogueira
18. jun, 2011
Clareza do código só pode ser atingido com confiança no que está se fazendo.
Os problemas vão além da arquitetura, pois quando a regra de negócio é complicada ou mal feita o código tende a seguir o mesmo caminho. Então o programador tem que fazer o trabalho que o cliente não fez: Separation of Concerns. Onde um problema complicado é quebrado em problemas menores que são mais fáceis de entender.
Por isso acredito esse artigo vem muito de encontro ao conceito Confident Code. Onde um programador não deve ficar a maior parte do tempo escrevendo código defensivo poluído de ” ifs”, enfim se garantindo de qualquer problema que possa aparecer por não ter confiança no cenário que está trabalhando.
Continua valendo aquela velha frase ‘dividir para conquistar’.