12 de maio de 2020

Programação Orientada a ob... classes

A história da computação é algo muitas vezes cíclico, onde conceitos com quase 50 anos retornam, às vezes na mesma forma, as vezes em uma nova roupagem. Vamos dar um zoom num dos conceitos mais comuns da programação moderna, a programação orientada a objetos.

 A primeira coisa que eu gostaria de falar, é que programamos orientado a classes mas os sistemas não rodam orientado a objetos.

Cão-da-pradaria de costas virando dramáticamente e encarando a câmera.
O QUE?


O que fazemos na verdade é estruturação de códigos em classe, o que não é ruim mas no decorrer dos próximos parágrafos vou tentar explicar melhor. Isso inclusive constata a diferença entre como organizamos nosso código e como isso pode ser diferente da organização das estruturas do nosso código em execução.

Se você, que nem eu, começou a programar nos últimos 20 ou até 30 anos com certeza lidou com a programação orientada a objetos, provavelmente com linguagens como C++, Java, C#, Python, Ruby ou qualquer outra linguagem que dê suporte a classes ou até protótipos (no caso de Javascript). Estas linguagens estruturam fortemente o código utilizando classes e a partir dela instanciam estes obetos, porém o ciclo de vida dos objetos tende a ser muito curto e contido no escopo de outros métodos, o que tem benefícios se tratando de concorrência (os objetos vivem tão pouco e num escopo tão restrito que não compartilham nenhum estado), gestão de memória (como os objetos são menores e vivem num escopo restrito, fica fácil controlar seu início e fim) e também manutenção de código, pois a execução do código ainda fica linear em sua execução. Porém é necessário deixar claro que isso não é algo que foi decidido da noite para o dia, durante muito tempo essa abordagem não foi a prioritária para o desenvolvimento Java, que durante muito tempo estruturou de forma diferente suas aplicações com EJBs no framework Java Enterprise Edition (Java EE).

Esta estrutura de código funciona muito bem, porém como já fazemos uma separação mais clara entre procedimentos (ou funções) e estruturas de dados, poderíamos potencializar os benefícios acima espelhando a maneira como nosso programa executa com a maneira que estruturamos nosso código, isso abriu um grande espaço para linguagens funcionais que já lidam bem com programação concorrente, gerenciamento de memória e manutenabilidade, e assim vemos o crescimento de linguagens como Clojure, Elm, F# e até Haskell.

Tabela com duas colunas, uma explicando o que temos de padrões em OO e os FP (que é apenas funções)
Diferenças entre OOP e FP
Fonte: https://blog.cleancoder.com/uncle-bob/2014/11/24/FPvsOO.html

Você pode pensar no motivo de já não termos adotado linguagens funcionais logo de cara, já que a programação orientada a objetos na maneira como fazemos hoje tem uma impedância entre a estrutura de código e a estrutura interna do programa em si, mas como falei acima, isso nem sempre foi assim. No decorrer dos anos 70 uma linguagem muito famosa surgiu, o Smalltalk, sendo uma linguagem orientada a objetos, um dos seus maiores diferenciais era a maneira como ela gerenciava seus objetos. Ao iniciar um programa os objetos eram carregados por sua máquina virtual e começavam a trocar mensagens entre eles, o ciclo de vida desses objetos era mais longo e permitia inclusive tirar uma fotografia do momento atual da máquina virtual e carregá-la novamente no mesmo estado posteriormente. 


Exemplo de diagra de sequência com mensagens UML
Diagra de sequência com mensagens UML
Fonte: https://en.wikipedia.org/wiki/Sequence_diagram
Programadores experientes em Smalltalk e posteriormente em Java inclusive criaram uma forma de documentar toda essa estrutura em uma linguagem bem conhecida, o Unified Model Language, porém como vamos descobrir abaixo, este modelo de execução sofria de alguns problemas e o UML acabou ficando subutilizado, pelo fato de só utilizarmos classes e não orientação a objetos de uma maneira purista, ou já utilizarmos logo uma linguagem funcional.

O modelo se modernizou para o século 21 quando foi adotado pelo Java Enterprise Edition no seu começo, onde estes objetos que ficavam carregados em memória, na forma de pools, eram chamados de Enterprise Java Beans e permitiam coisas como a distribuição entre diversos servidores (um EJB de uma máquina poderiam passar uma mensagens, em forma de invocação de método, para um EJB em outra máquina). 

O modelo orientado a objetos, apesar de muito robusto, era complexo e exigia configurações de máquina bem exigentes (trabalhei em lugares que tinham oito servidores de 32 núcleos e 64 GB de RAM para executar uma única aplicação Java) e isto começou a fazer a estrutura ficar cada vez menos interessante, mesmo o ciclo de vida dos objetos tendo um função de passiva-los (ou seja, eles eram serializados e salvos em um lugar mais econômico da JVM), sendo que depois perceberam que era melhor criar EJBs sem estado (ou seja, a primeira execução do EJB não mantinha nada armazenado que pudesse afetar sua segunda execução) e logo a máquina virtual do Java, por decisões arquiteturais e para facilitar a vida do coletor de lixo (responsável por liberar memória) começou a favorecer objetos que fossem instanciados rapidamente e morriam mais rapidamente ainda, permitindo a execução em máquinas com muito menos memória, favorecido pelo crescimento de frameworks mais simples de desenvolver como o Spring.
Ciclo de vida de um EJB
Fonte: https://examples.javacodegeeks.com/enterprise-java/ejb3/ejb-life-cycle-example/

Hoje em dia, os modelos mais comuns de orientação a objetos favorecem criar o código em forma de classes porém a execução de ocorre muito mais proceduralmente. Isso ajuda no gerenciamento de memória e tira da frente alguns problemas em relação a paralelismo de código, pois quando você tem vários objetos rodando em paralelo é necessário decidir qual é a prioridade e tempo de máquina que cada método de cada objeto deve ter e isto foi uma decisão que os desenvolvedores de linguagens e máquinas virtuais decidiram não priorizar.

Esta é a primeira parte do post e explica um pouco da história da programação orientada a objetos e sua evolução, porém como falei acima, as coisas ocorrem de maneira cíclica e o modelo criado pelo Smalltalk seria retomado mais recentemente de outra forma, que será explicada num próximo post.

10 de fevereiro de 2020

JoKenPo em Python

Fazer um jogo de JoKemPo em Python é simples, mas para complementar fiz alguns tratamentos diferentes, como a captura de KeyboardException para tratar a saída do programa.


19 de janeiro de 2020

Python que nem Javascript!

Disclaimer: Nunca faça isso na real!

Python tem uma natureza funcional muito boa (não tão boa quanto linguagens funcionais, é claro), o que de certo modo faz ele similar com Javascript, utilizando closures e afins. Inclusive permite construções similares a esta abaixo:

Python não define um meio de criar objetos dinâmicos como Javascript, devido a sua forte tipagem, por isso usei a estrutura de dicionário. O que acontece na verdade é que devolvemos uma coleção de funções que acessam os atributos do "construtor" através de closures.

Desde o ES6/ES2015 temos como declarar classes em Javascript utilizando keywords como class, constructor, etc, o que deixa bem mais limpo e agrupado, mas tudo isso ainda é syntax suggar para a estrutura de criação de objetos que existia anteriormente.

Update:


Consegui usar as chamadas de método normalmente, porém tive que definir uma classe apenas de quebra galho (a classe Object) apenas para poder usar setattr e para isto é necessário a classe definir __dict__:

10 de janeiro de 2020

Fazendo upload de arquivos para o Google Cloud Storage com Python

O processo é bem simples, porém é necessário antes configurar algumas coisas no Google Cloud e gerar as credenciais necessárias, para este processo pode seguir este tutorial. Lembre-se também de criar uma variável de ambiente com o nome GOOGLE_APPLICATION_CREDENTIALS apontando para o caminho do json, no Linux basta fazer:

export GOOGLE_APPLICATION_CREDENTIALS=/caminho/para/arquivo.json

Depois disso é possível executar o código abaixo (é claro, o bucket e o  arquivo indicado deve existir):


6 de janeiro de 2020

Pense sobre o seu trabalho - O programador pragmático

Os dias não são fáceis, você acorda cedo e se desloca para o seu trabalho, então você faz algumas coisas e chega o fim do dia, você faz o caminho inverso para sua casa. No fim do mês você é pago por isso, o que é bom, e se for da área de TI, é "mais bom" do que 90% do restante do Brasil.

Agora voltemos ao "faz algumas coisas" do paragrafo acima, que coisas são essas? Onde você aprendeu elas? Como lida com elas? Todas essas coisas são a sua profissão, mas o que é profissão? Será que é apenas o seu trabalho? Aquilo que você é pago para fazer? Vamos buscar a definição de profissão:

pro·fis·são
(latim professio-onisdeclaraçãomanifestaçãoprofissãoempregoestadoensino)

substantivo feminino
1. Declaração pública.

2. Solenidade na qual alguém se liga por votos a uma ordem religiosa.

3. Ofícioempregoocupaçãomister.

"profissões", in Dicionário Priberam da Língua Portuguesa [em linha], 2008-2020, https://dicionario.priberam.org/profiss%C3%B5es [consultado em 05-01-2020].

Como podemos ver acima, profissão vem do latim professio e significa declaração, manifestação, então a sua profissão é a sua declaração para o mundo, seu ofício. Isso deixou as coisas um pouco mais profundas do que apenas "aquilo que faço para ganhar dinheiro". Inclusive não há na definição acima (pelo menos na etimologia da palavra) algo que ligue profissão a dinheiro, logo podemos ser profissionais sem ser remunerados (e também podemos ser amadores remunerados!).

Assumindo essa nova visão mais profunda sobre a sua profissão, você gasta um pouco do seu tempo diário pensando no que você está declarando para o mundo através do seu trabalho? Você pensa em como fazer algo com qualidade, que agregue valor real para o mundo? Fazendo essa reflexão para a nossa área, a programação, fica claro que não faz parte da nossa rotina trazer essa reflexão para o nosso dia a dia (e isso está longe de ser ensinado em nossas escolas, mas isso é assunto para outro momento).

As nossas responsabilidades como programadores são cada vez maiores, pois em um mundo onde a automação toma cada vez mais espaço, passamos de pessoas que criavam e geravam simples sistemas de cadastro e, quando muito, folhas de pagamento, para mantenedores de sistemas que movimentam milhões por semana, sistemas hospitalares (não só a ficha do paciente, mas também todo o suporte a vida de algumas UTIs) e a programação no mundo real através de robôs, carros autonômos, aviões e muito mais. Então precisamos fazer bem tudo isso, fazer nosso trabalho com qualidade, precisamos pensar sobre o que estamos fazendo, não apenas fazer. É necessário gastar um tempo pensando antes de qualquer decisão, se aquilo é a melhor forma de fazer, se irá ajudar as pessoas que prometemos ajudar e principalmente, se não irá prejudicar as pessoas que prometemos ajudar, tudo isso converge para um aspecto muito importante, a qualidade das nossas criações.

A qualidade de tudo o que fazemos está altamente correlacionada em como dominamos os meios pelo quais nos expressamos, da mesma forma que um marceneiro que usa com maestria suas ferramentas e cria coisas incríveis, um desenvolvedor que domina o computador com maestria também cria coisas incríveis, afinal a ferramenta para o artesão é como uma extensão para a sua mão e quando você quer fazer algo com a sua mão você não precisa pensar em quanto deve rotacionar seu pulso, a pressão que deve colocar nos dedos, etc., você só pensa no que deve ser feito e faz.

Parece ser muita responsabilidade e, pra falar a verdade, é. É necessário um esforço em forma de treino e prática a mais na sua rotina para que você domine essas ferramentas, seu computador, o servidor onde você roda suas aplicações, porém tudo isso vem com a sensação de que você está realmente no controle do que acontece, no controle da qualidade e principalmente no controle da sua carreira, que é parte essêncial da sua vida. E é claro, quando você tiver um domínio alto de todas as suas ferramentas e sua carreira, tudo isso para de ser uma barreira e permite você focar na sua parte criativa, participar de outras decisões (como de negócios) e também, quem sabe, se divertir mais com o seu trabalho.

Essas são algumas reflexões que tirei do inicio da segunda ediçao do livro O Programador Pragmático, que já comentei em outro post.