Vamos falar sobre Idempotência

Yan Justino
Yan Justino

--

Esta é uma reflexão sobre o conceito de idempotência e sua aplicação em uma API REST. Nessa breve reflexão nos questionamos sé é realista uma implementação na qual todos os métodos são, de fato, idempotentes.

Idempotência é uma propriedade matemática e computacional que garante que operações tenham o seu resultado seguramente inalterado, mesmo que sejam executadas várias vezes, depois da primeira aplicação.

Em operações binárias, por exemplo, 1 e 0 são números naturais idempotentes: 1 x 1 sempre será 1, assim como 0 x 0 será sempre 0; por sua vez, 2 x 2 não tem como resultado 2.

Na computação, especificamente falando de REST, os verbos GET, PUT e DELETE são tidos como métodos idempotentes, dadas suas características e propósitos ao atuar sobre um mesmo conjunto de recursos diante de uma mesmas entrada. Já o verbo POST não, uma vez que cada aplicação representa um novo recurso.

O conceito descrito dessa forma representa uma espécie de “Estado da arte”. No entanto, alguns aspectos operacionais despertam o seguinte questionamento: é realista uma implementação na qual todos os métodos são, de fato, idempotentes? Vejamos alguns casos.

Código 1. pseudocódigo representando uma operação HTTP PUT (fonte própria)

Tomemos por exemplo o Código 1, o qual ilustra uma representação de um requisição HTTP PUT. Nesse trecho de código temos o seguinte fluxo: o recurso é recuperado de um repositório, seu estado alterado e, por fim, persistido.

Olhando mais atentamente, percebemos que ao alterar o estado da entidade, a data e o horário da última atualização é modificado (LastUpdate). Isso significa que nessa implementação, mesmo diante de uma mesma entrada, tenho como efeito colateral um novo estado do recurso todas as vezes que o método é executado. Continuemos…

Código 2. pseudocódigo representando uma operação HTTP GET (fonte própria)

Vejamos uma operação de leitura HTTP GET que executa uma ação chamada GetNextId(), como ilustra o Código 2. Também nesse caso, temos um comportamento aparentemente não Idempotente: nesse trecho de código temos como resultado sempre um novo valor a cada nova chamada.

Com base nesses exemplos, percebe-se que o simples uso dos verbos GET, PUT ou DELETE não é uma garantia de se obter idempotência. Por exemplo, repensando o Código 1, poderíamos lhe dar uma maior capacidade idempotente através do uso de um identificador único a cada solicitação, como ilustra o Código 3.

Código 3. pseudocódigo representando uma operação HTTP PUT idempotente (fonte própria)

Contudo, o uso de um identificador exclusivo para definir um recurso idempotente exige que o estado de sessão seja gravado de forma confiável pelo serviço e preservado em caso de falhas de hardware do servidor. Isso pode prejudicar a escalabilidade do serviço, e pode ser ainda mais complicado se implementações de serviços redundantes estiverem operando em diferentes locais que sofrem falhas de rede [2].

Diante disso, pressuponha-se que operações idempotentes não são tão comuns como se imagina ou se espera, uma vez que logs e manipulações internas de estado são recorrentes e podem facilmente serem implementadas sem capacidades idempotentes. Além disso, garantir um estado de sessão para se obter idempotência exige um esforço não trivial.

Por tanto, o que realmente deve ser ponderado é qual o objetivo de qualidade se deseja alcançar e quais resultados concretos são esperados de uma implantação idempotente. Acima disso, quais benefícios podem ser alcançados.

Obrigado por ler esse artigo. Sinta-se a vontade para deixar sua opinião nos comentários. Se você deseja ampliar sua visão sobre o tema, recomendo a leitura do debate O que é ser idempotente em REST? O debate continua, disponibilizado pelo portal do InfoQ.

Referências

[1] O que é ser idempotente em REST? O debate continua

[2] Idempotent Capability

--

--

Yan Justino
Yan Justino

MSc. Software Engineering — MCP | MCSA | MCSD | OCA