Foto de um livro antigo de Latin & Inglês

Gramática e Programação

Eu sempre detestei aprender línguas. Só me esforço para aprender o básico de um idioma quando realmente não há outra forma de sobreviver sem ele. Foi assim que acabei aprendendo o suficiente de inglês e português.

Lembro que, na escola, eu odiava as aulas de português. A única parte que eu realmente curtia era Literatura. Todo o resto era um verdadeiro martírio.

Mas o destino, com seu senso de humor peculiar, colocou meus dois professores de português como vizinhos de muro. Em anos pares, eu tinha aula com uma professora; em anos ímpares, com um professor.

Como eu sempre ficava de recuperação nessa matéria, minha mãe acabava pagando aulas particulares — com o professor do outro ano. O resultado? Eu tinha o dobro de aulas de português com os dois vizinhos ao longo do ano inteiro.

Por conta disso, acabei aprendendo algumas coisas “úteis completamente inúteis”. Por exemplo, sei que toda paroxítona terminada em ditongo crescente era acentuada, mas que, com a nova reforma ortográfica, isso deixou de ser verdade. Se antes “idéia” tinha acento, agora não tem mais.

Outra coisa que aprendi, à base de muita dor e sofrimento, foi análise sintática. Toda aquela parte que disseca as sentenças e mostra como elas são compostas: os sujeitos e predicados, os verbos com suas “transitividades”, os objetos, e por aí vai. Tudo isso foi entendido, ainda que sem compreender o mais importante: por que, afinal, eu estava aprendendo isso?

Nessa época, eu já sabia programar e até tinha começado a trabalhar profissionalmente com programação (sim, comecei bem antes da lei permitir). Mesmo assim, eu não conseguia “conectar os pontos” e enxergar as relações entre a gramática e a programação.

Programação

Programar é comunicar. E, para comunicar, precisamos de uma linguagem comum entre todos os envolvidos no processo.

Ao longo dos anos, a computação desenvolveu uma infinidade de linguagens de programação, cada uma com suas próprias características e propósitos. Essas linguagens facilitam a comunicação entre programadores e computadores, além de permitir que os programadores se entendam entre si.

Por exemplo, qualquer programador que conheça Python e um computador com um interpretador Python será capaz de entender e executar códigos escritos nessa linguagem.

Assim como os idiomas e linguagens naturais, as linguagens de programação possuem gramática. Elas se preocupam com sintaxe, semântica, pragmática, entre outros aspectos que fazem parte do estudo das línguas. Além disso, também possuem um léxico e vocabulário próprios que, se não estão estritamente sob o guarda-chuva da gramática, fazem parte do domínio linguístico.

Python, assim como muitas outras linguagens de programação, é uma linguagem imperativa. Isso significa que você escreve comandos para instruir “como” as coisas devem acontecer. Nesse paradigma, o foco está em ações e etapas específicas.

Por outro lado, linguagens que seguem outros paradigmas — como funcional, declarativo, lógico ou de marcação — não se preocupam tanto com o “como”, mas sim com o “o quê” deve ser feito.

Aqui é possível traçar um paralelo interessante entre o paradigma imperativo na programação e o modo verbal imperativo na língua portuguesa: ambos lidam com comandos e ordens. No português, a conjugação dos verbos no imperativo é usada para instruir ou demandar ações — exatamente o que fazemos ao escrever código em uma linguagem de programação imperativa.

Tá, e daí?

Se programar é comunicar e usamos linguagens para transmitir algo, será que os conhecimentos de gramática de uma linguagem natural (português, inglês, alemão, etc.) podem ajudar a melhorar o nosso código?

Eu acredito que sim. E, a seguir, vou listar algumas práticas que adoto ao desenvolver meus projetos.

Vale lembrar: estou falando de projetos de software escritos em linguagens de programação imperativas, não de uma obra literária. As sugestões que vou apresentar podem melhorar o seu código, mas provavelmente seriam péssimas escolhas para seu conto, romance ou artigo acadêmico.

Sentenças simples

Escrever sentenças simples facilita a compreensão. A estrutura mais básica de uma sentença segue o padrão:

Sujeito — Verbo — Complemento

O sujeito pode assumir várias formas, mas geralmente é representado por um substantivo (nome/noun). Em linguagens orientadas a objeto, o sujeito é (quase) sempre um objeto. Assim, uma sentença simples em código poderia ser algo como:

objeto.verbo(complemento)  # ou...
objeto.verboComplemento()

Parece óbvio, não? Sim, é básico, mas dito dessa forma, fica claro que os métodos de um objeto devem necessariamente ser verbos, e que os parâmetros passados ao método funcionam como complementos — nos moldes da análise sintática da transitividade dos verbos:

  • Verbo Transitivo: Requer um complemento (objeto direto ou indireto) para completar seu sentido.

Exemplo: “Ela comprou um livro.” (complemento: “um livro”).

  • Verbo Intransitivo: Não precisa de complemento, pois possui sentido completo por si só.

Exemplo: “Ela dormiu.”

Se o verbo usado no nome do método for transitivo, é importante lembrar que ele exige um complemento para que a ação faça sentido. Essa escolha ajuda a tornar o código mais intuitivo e compreensível.

Single Responsibility

Observe que a sentença usada como exemplo contém apenas um verbo. Mantendo essa estrutura, também garantimos que cada método realiza apenas uma ação:

1 verbo → 1 ação → 1 responsabilidade

Trabalhar dessa forma nos ajuda a garantir que nossos métodos respeitem o Princípio da Responsabilidade Única (Single Responsibility Principle – SRP), que estabelece que cada método ou função deve ter apenas uma responsabilidade clara e bem definida.

Interfaces REST HTTP

Interfaces são um meio de disponibilizar o acesso a componentes do seu sistema. Existem diversos tipos de interfaces que podemos utilizar, e uma delas são as APIs REST, que usam o protocolo HTTP.

O protocolo HTTP trabalha de forma stateless: um cliente faz uma requisição (request) para um recurso/documento/objeto em um servidor, e o servidor retorna uma resposta (response) para o cliente. O formato de uma requisição HTTP é aproximadamente assim:

METHOD /url
Header1: ...
HeaderN: ...

<payload>

Alguns dos METHODs disponíveis são: GETPOSTPUTPATCHDELETE, etc. Perceba que todos os métodos são verbos, ou seja, indicam ações requisitando algo do servidor. Seguindo nossa lógica gramatical, podemos inferir que a /url é o complemento (geralmente representado por um substantivo).

Como mencionado anteriormente, é importante manter as sentenças simples, ou seja, com apenas um verbo por requisição. Uma boa interface deveria seguir este padrão:

GET /users/1
POST /users
DELETE /users/c0ffe

No entanto, é comum encontrar requisições que apresentam dois verbos na mesma sentença:

POST /contracts/1/remove
GET /documents/2/cancel

Percebe como isso soa estranho? Casos como esse geralmente aparecem quando a ação envolve processos mais complexos. Por exemplo, cancelar um contrato pode exigir várias etapas, e um simples DELETE /contracts/1 pode não ser suficiente. Quando isso acontece, uma boa prática é transformar o segundo verbo em um substantivo, tratando o processo como um objeto.

Por exemplo, ao invés de usar algo como:

POST /contracts/1/cancel  # verbo + verbo

Eu prefiro reestruturar assim:

POST /contracts/1/cancellation  # verbo + substantivo

Essa abordagem não só torna a requisição mais natural, como também reflete melhor a lógica gramatical e mantém a consistência da interface.


Comentários

O espaço abaixo é todo seu…