Uma abordagem para lidar com o fluxo de seus dados

Victor Igor
9 min readAug 20, 2018

--

Vou te mostrar como a teoria das categorias pode dar uma nova perspectiva de como modelar o fluxo de dados do seu software.

Vamos falar sobre:

  • Paradigmas de programação
  • A história da teoria das categorias
  • Programação funcional
  • Como a teoria das categorias pode ajudar a construir um bom software
  • Por que composição?
  • Controle do fluxo
  • Como lidar com efeitos colaterais
  • Conceitos na prática

Para exemplos, irei usar códigos em Javascript e PureScript.

Introdução

Nós precisamos conversar sobre paradigmas de programação antes.

O que é paradigma de programação para você?

Um paradigma de programação é como uma abordagem para programar um computador que é baseado em um conjunto coerente de princípios ou uma teoria matemática. Na prática, cada paradigma vem com seu próprio modo de pensar e há problemas para os quais é a melhor abordagem.

Por exemplo:

  • Em programação funcional, a teoria é chamada de Lambda calculus.
  • Em POO, existem vários tipos diferentes de teoria, mas é essencialmente teorias organizacionais de como estruturar informações e atualizar informações.
  • Multi-agent concurrent programming a teoria é chamada de pi calculus.

Razões para você estudar outras linguagens de programação

  • Novas maneiras de resolver problemas.
  • Novos conceitos para aplicar em seus projetos.
  • Ferramenta certa para o trabalho certo.
  • Novas oportunidades.
  • Se manter atualizado.

The Pragmatic Programmer

Você acha que precisa apenas estudar a linguagem em que trabalha? Então precisa repensar se quiser ser um ótimo programador. Se você aprendeu e usou apenas um estilo de linguagem de programação (oop, funcional, compilado, alto nível, baixo nível, etc) é provável que o seu pensamento em torno de programação é muito estruturado em torno dessa linguagem.

Leia um pouco mais sobre isso: If you’re only going to learn one programming language, you should learn…

A Teoria das Categorias não é um novo paradigma, mas uma nova perspectiva sobre modelagem de fluxo de dados que pode contribuir muito para o desenvolvimento de softwares, em especial no que diz respeito a composição.

Uma pequena história sobre a teoria das categorias

O nascimento dessa teoria tem sido muito mais matemático do que computacional, e é muito difícil dizer exatamente quando foi a primeira vez que isso apareceu.

Em 1995 foi publicado um artigo chamado “Teoria Geral das Equivalências Naturais”, onde os conceitos de categoria foi introduzido como o de functor. Os autores precisaram definir um conceito para functor e aqui chegaram a algumas conclusões de conceitos básicos a categoria. Esses conceitos foram introduzidos muito mais na topologia algébrica, e com certeza! Todo mundo sabe o que é isso! Não, eu não sei, mas vamos continuar com a nossa saga.

Assim, outros avanços importantes foram publicados, mas houve um artigo que introduziu a ideia de usar a categoria para criar teorias mais gerais e aplicar em campos específicos, sim! Agora não temos apenas uma linguagem bonita, porque a categoria abstrata de estudo que encapsula os resultados algébricos homológicos também pode ser aplicada para obter resultados em outras áreas da matemática e, em seguida, vários teoremas e teorias podem ser vistos por um ângulo categórico. Mais tarde, teve uso suficiente em física teórica, a partir daí tornou-se bastante importante.

Veja a timeline da teoria das categorias e matemática relacionada para você ter uma noção do tempo.

Ciência da Computação e a teoria

A teoria das categorias é um campo que afeta cada vez mais a consciência de muitos cientistas da computação, especialmente aqueles com interesse em linguagens de programação e especificações formais, mas o maior contribuinte para receber a Teoria das Categorias é Haskell e seu sistema de tipos, que estendeu o sistema do tipo Hindley-Milner com a noção de type classes.

Programação Funcional e a Teoria

Esse paper explica muito mais os conceitos da teoria aplicado na programação funcional, mas explicarei um pouco. Se você não conhece esse paradigma, recomendo que você leia este artigo Functional Programming should be your #1 priority for 2015.

A mudança de paradigma trazida pela teoria da relatividade de Einstein trouxe a percepção de que não há uma perspectiva única a partir da qual se possa ver o mundo. Há infinitamente muitos frameworks e perspectivas diferentes, e o poder real está em poder traduzir entre eles. É nesse contexto histórico que a teoria das categorias começou.

Como a teoria de categorias pode ajudar a construir software?

Essa deve ter sido sua primeira pergunta quando leu a descrição deste post. A composição de funções é minha parte favorita da programação funcional, e quando comecei a estudar Haskell e PureScript, eu encontrei muitas pessoas falando sobre Abstrações e Functors. Foi nesse momento que comecei a me perguntar “por que essas pessoas estavam falando sobre isso? O que é isso?”. Eu encontrei muitos artigos e livros falando sobre essa teoria, mas muitos ainda não sabem como isso pode ajudar a construir um software, e é normal acharem que isso não faz sentido.

Teoria das Categorias é sobre Composição

Sim, composição! Porque para definir uma categoria, você precisa especificar qual composição está nessa categoria. É como a operação de multiplicação em um grupo (para definir um grupo, não é suficiente apenas dizer que você tem um conjunto e é possível multiplicar elementos do conjunto), você tem que realmente dizer o que entende por “multiplicar” como parte da definição do grupo.

Por que compor ?

A essência do desenvolvimento de software é a composição e as coisas que são compostas são boas porque permitem abstrações. Para entender o motivo de precisarmos aprender sobre composição, leia a série do Eric Elliot chamada Composing Software.

Controle de fluxo

Há muitas maneiras de controlar o fluxo de seus dados, em linguagens procedurais, a computação envolve código operando em dados, em OOP, um objeto encapsula tanto código quanto dados e linguagens funcionais puras, dados não têm existência independente. RxJs é um ótimo exemplo para demonstração de como eu posso usar para trafegar dados entre funções e obter resultados no final do pipe. Na minha opinião, é uma ótima maneira de resolver um problema porque você tem um fluxo de controle definido, sem estado e, na maioria das vezes, é um código menor.

data flowing through functions

Categoria

A Teoria das Categorias é uma teoria das funções e a única operação básica é a composição. O conceito de categoria incorpora algumas propriedades abstratas da composição.

  • Uma coleção de objetos
  • Uma coleção de morfismo
  • Para cada triplo de objetos X, Y, Z, um mapa (chamado composição)

Existem muitos tipos de categoria, mas você deve aprender sobre a categoria de conjuntos, porque é a categoria cujos objetos são conjuntos. As setas ou morfismos entre os conjuntos A e B são as funções de A a B, e a composição dos morfismos é a composição das funções.

Muitas coisas podem ser compostas

Você deve estar pensando que isso não tem nada a ver com programação e que os conceitos de matemática não podem nos ajudar. Vamos ver alguns tópicos que temos em programação e não temos em matemática e que podemos usar a composição para nos ajudar.

  • Assignments
  • Loops
  • Erros e Callback
  • Side Effects

Assignments

Você se lembra quando eu falei sobre ‘functor’? Vamos ver como isso pode nos ajudar.

Um functor é um mapeamento entre categorias. Dadas duas categorias, A e B, um functor F mapeia objetos em A para objetos em B e para ser um functor, você deve assegurar que satisfaz as duas leis de functor:

  • Identity Law => F(idA) = idF(A)
  • Composition Law => F(g ∘ f) = F(g) ∘ F(f)

Vamos criar nosso próprio functor para usar qualquer tipo de dados e mapeá-lo.

Basicamente, podemos encadear longas sequências de cálculo para resolver problemas. Eu usei o PureScript neste exemplo, mas não é útil apenas para linguagens tipadas. Segue a mesma implementação em JavaScript:

Em PureScript, temos operadores para compor nossas funções:

Neste artigo, você pode aprender mais sobre functors e categorias em JavaScript.

Loops

Looping em programação funcional não é feito com instruções de controle como for e while, é feito com chamadas explícitas para funções como map, filter e reduce ou recursão. Se o código de loop mutar variáveis fora do loop, essa função de loop interno estaria manipulando variáveis fora de seu escopo e, portanto, seria impura. Isso não é o que queremos, porque as funções impuras não são fáceis de compor. Map, filter e reduce/fold provavelmente resolve a maioria dos seus problemas relacionado a loops.

Erros e Callbacks

Existem algumas maneiras em que os erros geralmente são tratados em muitas linguagens de programação, mas basicamente usamos estruturas de fluxo de controle como if/else e exceções como try/catch. Mas qual é o problema? Estes tendem a ser difíceis de prever, difíceis de manter e compor.
Basicamente, vamos usar uma estrutura de dados monádica para encapsular o fluxo de controle de maneira declarativa. Vou mostrar exemplos em JavaScript para você saber que não é restrito em linguagens fortemente tipadas.

  • Maybe — impõe uma verificação nula com ramificação de código composta usando o Maybe. Uma estrutura que ajuda a lidar com valores que podem ou não estar presentes.

Linha 2, usei ‘fromNullable’ do Maybe, usei como uma caixa para verificar se tem valor. Estou usando o Folktale, e isso nos ajuda a compor e manter um encadeamento dos dados.

  • Either — Uma estrutura que modela o resultado de funções que podem falhar e essa estrutura representa a disjunção lógica entre a e b. Essa implementação específica é baseada no valor correto (b), e essas projeções terão o valor correto em relação ao valor da esquerda.

No Folktale, temos o Result que é semelhante.

  • Future — Uma estrutura de dados para representar o resultado de uma computação assíncrona.

Agora você pode usar todos esses conceitos:

Como lidar com efeitos colaterais ?

Haskell é uma linguagem puramente funcional e todas as funções dela são puras, pra comportamentos com side-effects ela usa monads para resolver esse tipo de problema. Vamos usar um IO, então tudo que você tem de ação de IO, elas te retornam uma IO computation(dentro de uma caixa), então uma função que ler um Integer no teclado, em vez de retornar um Integer, ela retorna uma IO computation que reproduz um Integer quando for executada, e como retorna um IO, você não pode usar esse resultado diretamente em uma soma por exemplo. E pra acessar você vai ter que ‘desembrulhar’ dessa monad. É assim que Haskell isola os efeitos colaterais, a monad IO atua como uma abstração do estado do mundo real. Em Purescript temos Eff para lidar com esses tipos de efeitos colaterais, e na sua própria documentação nos diz alguns cenários de onde podemos usar.

Efeitos nativos:

  • Console IO
  • Random number generation
  • Exceptions
  • Reading/writing mutable state

E no browser:

  • DOM manipulation
  • XMLHttpRequest / AJAX calls
  • Interacting with a websocket
  • Writing/reading to/from local storage

Em JavaScript temos uma lib chamada ramda-fantasy que além de implementar algumas das abstrações anteriores, temos esse tal de IO.

https://drboolean.gitbooks.io/mostly-adequate-guide-old/content/ch8.html

Criando nosso pequeno IO:

https://stackoverflow.com/questions/44109374/pure-functions-when-working-with-dom-manipulation

Agora você pode experimentar usar todos esses conceitos. Eu tenho uma apresentação de quando falei sobre isso: Everything is composable. Esses conceitos podem ser usados em backend ou frontend, mas como programação funcional é sobre programação compondo funções, precisamos apenas de uma linguagem com funções como valores de primeira classe.

Bonus 🌟

Estou implementando um gerador de Ansible Playbook para automatizar a instalação de seus aplicativos e dotfiles. Você pode ver alguns desses conceitos sendo usados na prática:

Packblade.

Você é front-end e usa react? Tem react-dream, para se divertir usando esses e muitos outros conceitos em react.

Conclusão

Existem outros conceitos na teoria das categorias que talvez possam nos ajudar, até porque é um assunto vasto. A ideia foi mostrar para vocês um pouco dessa teoria e como pode nos ajudar com abstração e composição. Eu usei alguns exemplos em PureScript, na qual é uma linguagem fortemente tipada que foi escrita e inspirada em Haskell que compila para JavaScript. Talvez optar por uma linguagem puramente funcional para praticar alguns desses conceitos seja uma ótima diversão, aliás, aprendizado em teoria das categorias é um investimento a longo prazo.

Para onde devo ir ?

  1. Eric Elliot tem muitos artigos sobre composição.
  2. Category theory for programmers.
  3. Make the Leap from Javascript to PureScript
  4. Oh Composable World!
  5. Everything is composable
  6. How useful is category theory to programmers?
  7. Monads in JavaScript

--

--