Compartilhar via


Programação funcional versus programação imperativa (LINQ to XML)

Este artigo compara e contrasta programação funcional com programação imperativa (procedural) mais tradicional.

Programação funcional versus programação imperativa

O paradigma de programação funcional foi criado explicitamente para dar suporte a uma abordagem funcional pura para a solução de problemas. Programação funcional é uma forma de programação declarativa. Por outro lado, a maioria das linguagens mais conhecidas, incluindo linguagens OOP (programação orientada a objeto), como C#, Visual Basic, C++ e Java, foram criadas para dar suporte principalmente à programação imperativa (de procedimento).

Com uma abordagem imperativa, um desenvolvedor grava o código que especifica as etapas que o computador deve executar para alcançar o objetivo. Isso é às vezes chamado de programação algorítmica. Em contraste, uma abordagem funcional envolve compor o problema como um conjunto de funções a serem executadas. Você define cuidadosamente entrada a cada função, e o que cada função retorna. A tabela a seguir descreve algumas das diferenças gerais entre essas duas abordagens.

Característica Abordagem imperativa Abordagem funcional
Foco do programador Como executar tarefas (algoritmos) e como controlar alterações no estado. Quais informações são desejadas e quais transformações são necessárias.
Alterações de estado Importante. Inexistente.
Ordem de execução Importante. Baixa importância.
Controle de fluxo primário Loops, condicionais, e chamadas de função (método). Chamadas de função, incluindo a recursão.
Unidade principal de manipulação Instâncias de estruturas ou classes. Funções como objetos de primeira classe e coleções de dados.

Embora a maioria das linguagens sejam criadas para oferecer suporte a um paradigma específico de programação, várias linguagens gerais são flexíveis o suficiente para suportar múltiplos paradigmas. Por exemplo, a maioria das linguagens que contêm ponteiros de função podem ser usadas para oferecer suporte credível à programação funcional. Além disso, a C# e o Visual Basic incluem extensões de linguagem explícitas para dar suporte à programação funcional, incluindo expressões lambda e inferência de tipos. A tecnologia LINQ é um formulário de programação declarativa, funcional.

Programação funcional usando XSLT

Muitos desenvolvedores XSLT estão familiarizados com a abordagem funcional pura. A maneira mais eficaz de desenvolver uma folha de estilos XSLT é tratar cada modelo como uma transformação isolada que possa ser composta. A ordem de execução é completamente minimizada. A XSLT não permite efeitos colaterais (exceto que mecanismos de escape para executar o código procedural podem gerar efeitos colaterais que resultam em impureza funcional). No entanto, embora a XSLT seja uma ferramenta eficaz, algumas de suas características não são ideais. Por exemplo, expressar construções de programação em XML torna o código relativamente detalhado, e portanto difícil manter. Além disso, a forte dependência na recursão para o controle de fluxo pode resultar em um código de difícil leitura. Para obter mais informações sobre XSLT, consulte Transformações XSLT.

No entanto, XSLT provou o valor de usar uma abordagem funcional pura para transformar XML de uma forma para outra. Programação funcional pura com LINQ to XML é semelhante de várias maneiras ao XSLT. No entanto, os constructos de programação introduzidos por LINQ to XML, C# e Visual Basic permitem que você grave transformações funcionais puras que são mais legíveis e sustentáveis do que XSLT.

Vantagens de funções puras

O principal motivo para implementar transformações funcionais como funções puras é que as funções puras são componíveis: isto é, autocontidas e sem estado. Essas características trazem um número de benefícios, incluindo o seguinte:

  • Legibilidade e sustentabilidade aumentadas. Isso ocorre porque cada função é criada para realizar uma tarefa específica com base em seus argumentos. A função não depende de qualquer estado externo.
  • Desenvolvimento iterativo mais fácil. Porque o código é mais fácil refatorar, alterações no design são geralmente mais fácil de implementar. Por exemplo, suponha que você escreve uma transformação complicada e depois percebe que algum código está repetido várias vezes dentro da transformação. Se você refatorar por meio de um método puro, poderá chamar seu método puro à vontade, sem se preocupar com efeitos colaterais.
  • Teste e depuração mais fácil. Como as funções puras podem ser testadas mais facilmente em isolamento, você pode escrever código de teste que chama a função pura com valores típicos, casos de borda válidos e casos de borda inválidos.

Pelos motivos descritos acima, a programação funcional é adequada ao estilo de arquitetura de microsserviços.

Transição para desenvolvedores em OOP

Em programação orientada a objeto tradicional (OOP), a maioria dos desenvolvedores estão acostumados a programação estilo obrigatório/procedural. Para passar a desenvolver em um estilo puramente funcional, eles precisam fazer uma transição em seu pensamento e na sua abordagem ao desenvolvimento.

Para resolver problemas, desenvolvedores de OOP projetam hierarquias de classes, focam no encapsulamento adequado e pensam em termos de contratos de classe. O comportamento e o estado dos tipos de objeto são primordiais, e os recursos de linguagem, como classes, interfaces, herança e polimorfismo, são fornecidos para abordar essas preocupações.

Por outro lado, a programação funcional aborda problemas computacionais como um exercício de avaliação de transformações funcionais puras de coleções de dados. Programação funcional evita o estado e dados mutáveis, e em vez disso enfatiza a aplicação de funções.

Felizmente, C# e Visual Basic não requerem uma imersão total em programação funcional, pois dão suporte a abordagens de programação imperativa e funcional. Um desenvolvedor pode escolher qual abordagem é a mais adequado para um cenário específico. De fato, os programas combinam geralmente as duas abordagens.

Confira também