Programar da esquerda para a direita
(graic.net)- Programar da esquerda para a direita significa que, assim que o código é digitado, o programa permanece em um estado válido, maximizando o suporte das ferramentas, como o autocompletar do editor
- As list comprehensions do Python atrapalham o autocompletar por causa de variáveis não declaradas e da ausência de inferência de tipos
- Rust e JavaScript permitem compor o programa naturalmente da esquerda para a direita, tornando mais intuitivos o uso de variáveis e a descoberta de métodos
- O estilo funcional em C e Python prejudica uma experiência de codificação eficiente por causa da baixa descobribilidade dos nomes de funções ou da estrutura
- Em lógicas mais complexas, o código desenvolvido da esquerda para a direita é mais fácil de ler e oferece melhor manutenção e extensibilidade
Programar da esquerda para a direita
O código precisa ser válido no momento em que é digitado
Limitações das list comprehensions em Python
- A sintaxe de list comprehension do Python
words_on_lines = [line.split() for line in text.splitlines()]exige acessar uma variável não declarada (line), o que faz com que o editor não consiga oferecer autocompletar nem inferência de tipos de forma adequada - Durante o processo de digitação parcial do código
- ao digitar algo como
words_on_lines = [line.sp, o editor não sabe o tipo delinee não consegue sugerir métodos - também fica mais difícil detectar erros em potencial, como um typo no nome da variável (
lime, por exemplo)
- ao digitar algo como
- Para receber sugestões corretas, é preciso escrever código incompleto, o que torna o processo pouco intuitivo e incômodo
Composição da esquerda para a direita em Rust
- No exemplo em Rust (
let words_on_lines = text.lines().map(|line| line.split_whitespace());),- no momento em que a variável (
line) aparece pela primeira vez junto com a declaração da função anônima, ela já é tratada como declarada, permitindo autocompletar e sugestão de métodos imediatamente - na prática, até o método
split_whitespacepôde ser encontrado facilmente graças às sugestões automáticas
- no momento em que a variável (
- Como o programa permanece sempre em um estado parcialmente válido, a IDE ou o editor consegue oferecer suporte à codificação em tempo real
Divulgação progressiva (Progressive Disclosure) e usabilidade de APIs
- Divulgação progressiva (Progressive Disclosure) é um princípio de design em que o usuário só encontra a complexidade na medida em que precisa dela, e isso também pode ser aplicado à programação
- Ex.: semelhante à UX de um processador de texto em que opções relacionadas só aparecem ao adicionar uma imagem
- A linguagem C oferece pouco desse suporte
- como nem todas as funções relacionadas a
FILE *filepodem ser exploradas viafile., é preciso decorar padrões de nomes de função (fread,fcloseetc.), e fica difícil descobrir funcionalidades - já em uma linguagem ideal, as sugestões de métodos via
file.permitiriam descobrir progressivamente os recursos relacionados com facilidade
- como nem todas as funções relacionadas a
Diferença na descobribilidade de funções e métodos
- Comparação entre os exemplos
map(len, text.split())em Python etext.split(" ").map(word => word.length)em JavaScript- em Python, como nomes de função como
len,lengthousizenão são previsíveis, é preciso tentar várias opções para descobrir qual realmente funciona - em JavaScript, basta digitar
.ldepois deword.para o editor sugerir métodos comolength, o que dá alta descobribilidade - até funções de ordem superior como
mapdeixam claros de imediato o valor retornado e o tipo de dado
- em Python, como nomes de função como
Quanto mais complexa a lógica, maior a vantagem da escrita estruturada
- Em lógicas mais complexas (código longo em Python com
filterelambdaaninhados),- é preciso verificar repetidamente o início e o fim do código, e surgem problemas de legibilidade reduzida e dificuldade de compreensão em condições e pareamento de parênteses
- Na versão equivalente em JavaScript, é possível ler e entender o código sequencialmente, de cima para baixo e da esquerda para a direita
Princípio central
O código precisa ser válido em cada momento da digitação
- Mesmo ao digitar apenas
text, o programa continua em um estado válido - Mesmo após escrever
text.split(" "), e depois continuar com.map(word => word.length), o estado intermediário do programa permanece sempre válido - Esse padrão de codificação aumenta a possibilidade de suporte em tempo real pelo editor e, em um ambiente REPL, também permite verificar os resultados imediatamente
Conclusão
- O design de APIs e linguagens deve dar suporte para que o código possa ser digitado naturalmente da esquerda para a direita, formando um programa válido em cada etapa intermediária
- Um bom design de API é a chave para melhorar essa experiência de codificação
1 comentários
Comentários do Hacker News
SELECT * FROM tablee simplesmente escreverFROM table. Talvez eu soe como um velho rabugento por reclamar disso, mas é só uma saudade pessoal minhaTABLE <table>functools.mapno Python){3} for {2} in {1}também é possível. Essas ferramentas oferecem um meio-termo entre "sintaxe boa de ler" e "sintaxe fácil de digitar". Mesmo recorrendo a tooling, eu tendo a priorizar uma sintaxe boa de ler. Não acho que exista motivo para insistir exclusivamente na estrutura "for-in"bake(divide(add(knead(mix(flour, water, sugar, butter)),eggs),12),450,12), usar pipe emmix(flour, water, sugar, butter) %>% knead() %>% add(eggs) %>% divide(12) %>% bake(temp=450, minutes=12)é muito mais fácil e agradável de verfrom some_library import child_moduleé muito intuitiva. Em JS, uma estrutura comoimport { asYetUnknownModule } from SomeLibraryparece bem menos intuitivalen(list(filter(lambda line: all([abs(x) >= 1 and abs(x) <= 3 for x in line]) and (all([x > 0 for x in line]) or all([x < 0 for x in line])), diffs))), seria muito melhor usar um array NumPy, já que assim não é preciso criar novas listas na memória e também fica bem melhor para tratar a linha inteira de uma vez. Por exemplo: Isso reflete muito melhor a ideia de "da esquerda para a direita"