domingo, 29 de julho de 2007

Orientação a objetos

Orientação a objetos é o paradigma de programação por «simulação», ou seja, em vez de o programador pensar em procedimentos ou funções, ele usa o conceito de objetos, similares aos reais, que interagem entre si.

Cada objeto tem características próprias, executa procedimentos próprios e interage de uma maneira própria. Essa técnica também é chamada «programação antropomórfica» ou «programação por personificação».

Veja que não é necessário uma linguagem ou sintaxe com suporte a orientação a objetos, apenas que o programador seja capaz de pensar orientadamente a objetos. Porém uma linguagem ou sintaxe com suporte próprio ajuda bastante.

Na abordagem tradicional procedimental o foco da programação está nos procedimentos imperativos. Na programação funcional o foco está nas funções, passagem de parâmetros e tratamento de retorno.

Já na orientação a objetos o foco está nos objetos simulados e na interação entre eles.

Por exemplo, no famoso jogo da cobrinha, a cobra seria um objeto com características – tamanho por exemplo – e procedimentos – virar à esquerda, por exemplo. Outros objetos seriam a maça e as paredes.

A própria cobra é composta de secções, que por si são objetos com características – posição – e procedimentos – mudar a posição.

O jogo surge da interação entre os objetos.

As características de um objeto são chamadas atributos e os procedimentos métodos. Algumas linguagens permitem atributos especiais que executam métodos de forma transparente. Esses atributos são chamados propriedades.

Atributos e métodos usados para interagir com outros objetos são chamados interface.

Então orientação a objetos consiste em elaborar objetos similares a coisas físicas, com características próprias e uma interface, de forma a que da interação entre os objetos surja o resultado desejado.

Sintaxe


Não… não é da sintaxe de criação, comandos class e similares que vou falar.

Quero falar de como a sintaxe de uma linguagem deve ser para incitar a orientação a objetos.

Segundo Smalltalk, para uma perfeita orientação a objetos as instruções de um programa devem ser mensagens envidas a objetos.

Para incentivar a orientação a objetos é interessante que o primeiro elemento de uma mensagem seja o objeto chamado.

Por exemplo, fatorial de 5 em Perl (procedimental):
fatorial 5


Em Smalltalk:
5 fatorial


Em Perl, procedimental, é informado um procedimento – fatorial – a ser executado e é passado a esse procedimento o parâmetro 5.

Em Smalltalk, orientada a objetos, é informado um objeto – 5 – ao qual é passada a mensagem, dizendo para ele executar um método internamente.

Observação: em Haskell, linguagem funcional, não imperativa, a sintaxe seria, no caso em questão apenas, idêntica à de Perl, mas a lógica é diferente: é informada uma função matemática que necessita de um parâmetro. Ou seja, é diferente você dizer «execute esse comando» de «o resultado dessa função é».

Sintaxe ou paradigma?


É preciso se perguntar: «estou orientado a objetos ou estou usando uma linguagem que facilita orientação a objetos para programar sequencialmente?»

Não é pela linguagem ser orientada a objetos que o programa será. Também não é pela linguagem não ser orientada que o programa não será.

Programa é a representação de um algoritmo em uma linguagem determinada; se o algoritmo for orientado a objetos o programa também será, mas se o algoritmo não for, não faz diferença se a linguagem em si é ou não.

Aliás, muitos programadores deixam de estruturar por usar uma linguagem orientada a objetos, resultando em programas sequenciais.

Gente, muito cuidado no planejamento. Não confiem na linguagem para fazer tudo pra vocês.


Bem, está aí mais um artigo conceitual.

[]'s
Cacilhas

sábado, 28 de julho de 2007

Smalltalk

VisualWorks Faz tempo que quero escrever algo sobre Smalltalk.

Smalltalk é a linguagem de programação orientada a objetos. O conceito de orientação a objetos foi criado pela equipe que desenvolveu Smalltalk, no MIT durante o final da década de 1960, ainda antes da criação de C. A primeira versão oficial foi Smalltalk-71.

[update 2008-04-19]Pequena correção: o conceito de orientação a objetos foi aprimorado em Smalltalk. A linguagem Simula já era orientada a objetos antes de Smalltalk.[/update]


Em Smalltalk tudo são objetos. Números são objetos, classes são objetos, métodos são objetos, blocos de código, strings, etc., tudo mesmo.

Outros conceitos que leigos acreditam ter sido criados na década de 1990 também proveem de Smalltalk, como bytecode e máquina virtual. É como Smalltalk trabalha.

Para ter Smalltalk instalado, eu uso Cincom VisualWorks.


Este artigo tem por objetivo exibir alguns exemplos.

Vamos então ao famoso «Olá Mundo!»:

Se você também instalou VisualWorks, inicie um novo workspace, digite e execute:
Transcript show: 'Hello World'.
Transcript cr.


Dica: é preciso selecionar o código para executá-lo.

O botão para execução é o raiozinho (Do it).


Os comandos são chamados mensagens e têm o formato:
objeto método[: parâmetros].

Onde os parâmetros são outros objetos passados ao método do objeto que recebe a mensagem.

O objeto Transcript é a janela principal do VisualWorks, que tem o método show (mostrar). Como parâmetro, estamos passando o objeto 'Hello World', uma string.

O método cr de Transcript insere uma mudança de linha.

Chamadas a diversos métodos de um mesmo objeto podem ser concatenadas com ;:
Transcript show: 'Hello World'; cr.


Na verdade não é obrigatório usar o ponto como terminador de mensagem. Ele é apenas um separador de mensagens.

Podemos «picar» a string:
Transcript show: ('Hello World' copyFrom: 2 to: 4).
Transcript cr.


Vai exibir ell: assim como Pascal e Lua, os índices em Smalltalk começam em 1.

Para exibir um número:
Transcript show: (((3 + 5) negated) printString).
Transcript cr.


Vamos agora criar um coleção:
| ord |
ord := SortedCollection new.
ord add: 'Forca de Expressao'.
ord add: 'Monte Gasppa'.
ord add: 'Walter Cruz - devlog'.
Transcript show: (ord at: 1).
Transcript cr.


Ou ainda:
| ord |
ord := SortedCollection new.
ord add: 'Forca de Expressao'.
ord add: 'Monte Gasppa'.
ord add: 'Walter Cruz - devlog'.
ord do: [ :each | Transcript show: each; cr ].


Para exibir todos os número de 1 a 10:
(1 to: 10) do: [ :index |
Transcript show: (index printString); cr
].


Vamos ficar por aqui por enquanto… quando eu estiver mais desenferrujado, escreverei mais alguma coisa.

Apropósito, mais informações podem ser obtidas aqui.

[]'s
Cacilhas

OpenID

OpenID Passei essa semana quebrando a cabeça no trabalho para desenvolver um protótipo de módulo relying party em Lua.

Relying party – também chamado consumer – é um dos nós que participam de uma autenticação OpenID.

O que é OpenID?


OpenID é um sistema livre descentralizado de autenticação e autorização centrado no usuário.

Ou seja, atualmente em cada sistema com autenticação, você precisa fazer um cadastro. Então você usuário é obrigado a manter uma redundância inconveniente de dados, que eventualmente precisam ser atualizados.

Para piorar os sistemas centralizam dados de todos os usuários, inclusive as senhas. Daí você usuário precisa ter uma senha para cada sistema, tendo de lembrar toda uma fauna de sEnH45 complicadas – ou de 123mudar.

Alguns arriscam sua identidade digital usando a mesma senha para tudo, o que não é aconselhável nem de longe.

OpenID surge em meio a essa realidade como uma solução para o problema.

Você usuário centraliza todos seus dados e sua senha em um único servidor de sua confiança, chamado server-agent ou OpenID provider.

Então você pode autenticar-se em sistemas que ofereçam suporte a OpenID – chamados relying parties ou consumers – sem que o sistema conheça sua senha, apenas fornecendo uma URL conhecida como identidade OpenID (identity). Ainda mais: quando for atualizar seus dados, só é preciso atualizar no agente servidor, pois não há redundância.

É um sistema descentralizado porque você não é obrigado a cadastrar seus dados no sistema onde deseja ser autenticado.

Protocolo


Há ferramentas prontas para Python, JSP, Ruby e PHP.

No entanto Lua é uma linguagem com uma comunidade muito pequena ainda para reagir tão rápido às novidades. Considerando-se ainda a filosofia da linguagem – SIMPLE: simple, light-weight and extensible, simples, leve e extensível –, é compreensível a necessidade de desenvolver os próprios módulos.

Se por um lado é inconveniente, por outro, se você realmente gosta de programar, Lua se torna uma linguagem muito divertida.

Em miúdos: se você trabalha com programação mas não gosta, faz isso só pra ganhar dinheiro, pare de ler por aqui e vai trabalhar. Espere alguém fazer um módulo por você para poder usar OpenID. =P


Continuando então o artigo – agora para programadores de verdade e curiosos –, o problema para desenvolver um módulo consumidor é entender o protocolo.

O protocolo OpenID negocia tunelado dentro do protocolo HTTP.

Resumidamente, a lógica é a seguinte:
  1. O cliente (navegador) acessa o consumidor;
  2. O consumidor envia um formulário ao cliente solicitando sua identidade OpenID;
  3. O cliente informa ao consumidor sua identidade;
  4. O consumidor normaliza a identidade – fica algo como http://user.example.com/;
  5. O consumidor acessa via HTTP a URL da identidade e pega o código HTML;
  6. O consumidor procura na URL marcadores link com atributos rel contendo openid.server, openid.delegate, openid2.provider e openid2.local_id – esses marcadores informam através do atributo href quem é o agente servidor e qual a identidade real do cliente;
  7. O consumidor acessa via HTTP o agente servidor em busca das chaves de comunicação – esse processo é chamado associação;
  8. Tendo sido feita a associação, o consumidor usa as chaves para redirecionar o cliente para a página de autenticação do agente servidor;
  9. O cliente se autentica no agente servidor informando sua senha, se já não estiver atenticado;
  10. O agente servidor pergunta ao cliente se ele autoriza o consumidor a ter acesso a seu perfil;
  11. Se o cliente permitir, o agente servidor redireciona o cliente para o consumidor, passando os dados solicitados.


Vamos então para o primeiro passo que precisamos implementar:

Formulário


O action do formulário deve apontar para o script que irá negociar com o agente servidor e precisa ter uma entrada texto para a identidade.

Esta entrada geralmente tem a identificação openid_login e seu formato CSS padrão pode ser encontrado aqui.

Normalização


O próximo passo já é executado no script.

Ele deve pegar a URL e normalizá-la.

Isto é feito assim:
  • =id não muda;
  • xri://=id vira =id;
  • xri://$dns*id.ex.com vira http://id.ex.com/;
  • xri://$ip*a.b.c.d vira http://a.b.c.d/;
  • http://id.ex.com/ e https://id.ex.com/ não muda;
  • id.ex.com vira http://id.ex.com/.


Na verdade estamos aqui neste artigo interessados apenas nas normalizações que geram URLs HTTP e HTTPS.

Associação


Na associação o consumidor acessa o agente servidor via HTTP.

O agente servidor é obtido de um desses marcadores tirados da consulta ao HTML da identidade:
  • <link rel="openid.server" href="http://example.com/server" />
  • <link rel="openid2.provider" href="http://example.com/server" />
  • <link rel="openid.server openid2.provider" href="http://example.com/server" />


Observação: para uma consulta HTTP em Lua você precisa da função socket.http.request() de LuaSocket.

Na associação envie ao agente servidor via GET os seguintes parâmetros:
  • openid.mode=associate
  • openid.assoc_type=HMAC-SHA1
  • openid.sesion_type=no-encryption


Quanto a criptografia, o ideal é usar DH-SHA1 (Diffie Hellman), mas, até que alguém faça um módulo de baixo nível para Lua de gerenciamento de chaves grandes, Lua é muito lenta para lidar com tais chaves e somos obrigados a trabalhar sem criptografia. =(

Feita esta consulta, o agente servidor deve retornar duas chaves no corpo:
  • assoc_handle – «maçaneta» (alguma tradução melhor?) de associação;
  • mac_key – chave de código de autenticação de mensagem.


Guarde essas informações!

Redirecionamento


Agora é preciso redirecionar o cliente para a página de login do agente servidor.

Faça isso contruindo uma URL apontando para o agente servidor e levando os seguintes parâmetros (via GET mesmo):
  • openid.ns – indica a versão de OpenID usada, para 2.0: http://specs.openid.net/auth/2.0
  • openid.mode=checkid_setup
  • openid.identity – a identidade do cliente
  • openid.claimed_id – novamente a identidade
  • openid.assoc_handle – a «maçaneta» de associação recebida
  • openid.return_to – a URL do script que irá tratar a resposta


Depois disso o cliente vai negociar diretamente com o agente servidor.

Recebendo de volta


No final o cliente será redirecionado de volta para o consumidor, mais especificamente para a URL informada por openid.return_to.

Esse script receberá parâmetros POST, sendo o principal openid.mode, que, se for id_res, o cliente está autenticado e autorizou o consumidor.

Outros parâmetros


Todos os parâmetros podem ser encontrados na especificação do protocolo.

TODO


Este artigo aborda o básico do básico da atenticação.

Com ele ainda não é possível recolher dados de SRE (informações de perfil), que deveriam ser passados nos subparâmetros de openid.sreg.

Mas para tanto é preciso usar criptografia – pelo que entendi, posso estar errado.

De qualquer forma, aqui está uma boa explicação do funcionamento do protocolo OpenID.

[]'s
Cacilhas

segunda-feira, 16 de julho de 2007

Pylons: conhecendo aplicando

Tomei a coragem de escrever um post sobre Pylons, mas ao contrário do que disse numa outra oportunidade, não vou fazer o exemplo do livro de receitas. Tomo por base para este post e outros, uma aplicação de gestão de férias de empregados. Algumas coisas me influenciaram a escolher esse tipo de sistema, mas o principal é a raridade de encontrar exemplo parecido.

Outra diferença importante será o fato de não expor o código completo nos posts. Gostaria de colocar somente os mais importantes. O código-fonte está disponível aqui.

Análise de Requisitos

Queremos que o empregado possa acessar a aplicação via navegador web para solicitar suas férias. Ele pode marcá-las para no mínimo 20 dias após o pedido. Ainda pode sugerir duas datas para que o seu chefe imediato possa escolher a mais adequada. Essas datas precisam ter uma distância de pelo menos 15 dias corridos.

O empregado tem a opção de informar se deseja vender um terço das férias ou toda ela para receber em troca o bônus pecuniário.

As férias podem ser parceladas na seguinte forma: duas parcelas de 15 dias ou uma de 10 mais outra de 20 dias. Caso venda parte de suas férias não haverá parcelamento.

O parcelamento também é uma sugestão do empregado. O seu gerente é quem toma a decisão final.

Uma solicitação só pode ser aceita caso não haja uma anterior pendente. O sistema deve avisar com antecedência de um mês para o gerente do empregado que uma solicitação está a um mês para alcançar a data do início do período de férias mais próximo que o usuário pediu. Quando esta data chegar o sistema avisará novamente quando aproximar-se a segunda sugestão.

O gerente quando for atender uma solicitação deve ter em conta quais empregados já possuem férias para serem gozadas nas datas sugeridas pelo empregado. O sistema deve mostrar isso.

Após haver a possibilidade de férias em uma das datas, o próximo passo será verificar a possibilidade de compra das férias. Caso haja e se for total, essa opção será marcada. O empregado receberá seu abono na folha de pagamento seguinte à primeira data de sugestão. Caso seja a terça parte, o sistema registrará a data de início e fim em 20 dias corridos.

Não havendo possibilidade de venda ou o gerente não querendo comprar, resta saber se haverá parcelamento ou não. Fica a critério do gerente usar as datas sugeridas para parcelar ou somente uma delas.

Ao fechar o pedido de solicitação do empregado, estas férias estarão em estado de espera de gozo. O empregado não poderá fazer uma nova solicitação até o proximo ano ou até que tenha gozado. Além do mais, a nova solicitação será para o período de seguinte.

O sistema ainda poderá informar ao empregado, ao logar-se no sistema, que estará a ponto de acumular três férias sem gozar. Caso ocorra essa acumulação, automaticamente o período de férias mais antigo será prescrevido.

O projeto

O projeto será construído usando o framework Pylons e por isso dei o nome para ele de Ferlons, uma junção de férias e Pylons. Os formulários serão simples porém escolherei um template visualmente agradável na web para animar as coisas.

Pré-requisitos

Saber um pouquinho de Python, possuir a versão 2.4 ou 2.5 da linguagem instalada na máquina e a biblioteca do SQLite (claro, você poder usar o MySQL ou o PostgreSQL). Os comandos abaixo instalam o Pylons e o SQLAlchemy.


easy_install Pylons SQLAlchemy


Caso não tenha o easy_install na sua máquina acesse a página de downloads do Pylons para explicações.

Acompanhem os próximos posts onde cuidarei de mostrar um pouco mais. Possivelmente o uso do AuthKit.

terça-feira, 3 de julho de 2007

Pylons

Esse texto é baseado em um e-mail que eu mandei para a lista PythonBrasil, porém mais completo que o e-mail.


Pylons é uma das opções que o desenvolvedor Python tem dentro dos frameworks para desenvolvimento web.

Um dos seus diferenciais é que ele é todo centrado em WSGI - Web Server Gateway Interface, que é uma PEP que descreve como os aplicativos devem se comunicar com o servidor web. Qual a vantagem disso? Uma modularização razoavelmente padronizada que é totalmente interessante.


Suporta SQLObject e SQLAlchemy (a maioria atualmente esteja dando preferência ao último). Embora o SQL Alchemy use o padrão de projeto DataMapper é possível transformá-lo em um ActiveRecord usando o Elixir. Isso com certeza irá agradar os usuários do rails.


Não só isso – a integração com JavaScript é feita à la Rails, incluindo os helpers com suporte a Prototype e Scriptaculous e o sistema de despacho do Pylons é baseado no do Ruby (Routes).


Usando os mecanismos do WSGI, a autenticação pode ser feita por um middleware, o AuthKit. Para algo ultra-simples, um cadastro que apenas um usuário vá usar, é possível gerar um formulário de login usando apenas as configurações do middleware. Simples e funcional.


Quais seriam as vantagens desses middlewares e do amplo suporte a WSGI? Um exemplo simples: você tem uma aplicação com o Pylons, e precisa adicionar um wiki a ela. É fácil desenvolver um, mas que tal usar o MoinMoin? Mas e a base de usuários, terei de duplicar? Bom, como o MoinMoin também implementa interfaces pra WSGI, você embute ele em um controlador e usa a própria autenticação do AuthKit. Interessante não?


Para modelos, o Pylons usa o Buffet, que é uma API de intercambiabilidade de motores de modelo. No cardápio, Myghty, Mako, Genshi e Kid e Cheetah (por enquanto).

Dos três principais frameworks pra web em Python (Django[2003-2004],TurboGears[início de 2005] e Pylons[fim de 2005]), o Pylons é o mais novo. Mas nem por isso deixa de surpreender: a movimentação para o TurboGears 2.0 é que ele seja implementado em cima do Pylons! Só por esse tipo de notícia já vale a pena colocar o Pylons na sua lista de coisas a testar!