29 de outubro de 2010

Levantando os recursos existentes na CPU

Há um post aqui no blog onde mostrei como obter informações sobre a CPU em Delphi usando a instrução assembly CPUID. O foco lá era obter apenas o modelo da CPU, informação usada para fazer um licenciamento de software. Aqui eu vou mostrar como fazer um levantamento sobre os recursos implementados numa CPU dos dois principais fabricantes - Intel e AMD.

Em ambos os fabricantes, o levantamento proposto é executado pela função 1 da CPUID. Isto signfica que teremos que mover o valor 1 para o registrador EAX, que armazena o código da função a ser executada. Os valores que buscamos são armazenados pela instrução CPUID no registrador EDX.
var REGEDX : LongWord;
begin
asm
MOV EAX, 1
CPUID
MOV [REGEDX], EDX
end;
{ ... }

Então, após a execução do código acima, teremos na variável REGEDX o mapa de bits para as características presentes no processador. São 32 bits ao todo, cada um sinalizando se um determinado recurso está presente na CPU do seu computador. Portanto, para ter acesso a cada bit isoladamente, teremos que trabalhar com aritmética binária no Delphi - principalmente com o operador AND aplicado bit a bit.

A ideia é preparar outra variável com 32 bits mas apenas um dos bits estará ligado de cada vez. Ao aplicar o AND binário entre essa variável e o conteúdo de REGEDX nós obtemos a sinalização se o recurso representado nesse bit específico está presente ou não. A imagem abaixo ilustra a extração do recurso representado pelo primeiro bit:
Extração do primeiro bit

Repare que, na variável preparada, apenas o primeiro bit está ligado, isto é, possui valor 1. Comos os demais bits estão em zero, o AND binário com o REGEDX retornará um valor diferente de zero caso seu primeiro bit também esteja ligado.

Para ligar um bit de cada vez na variável, podemos montar um laço iniciando em 1 (liga o primeiro bit) e ir multiplicando-a por 2 para fazer o bit ir "avançando" :
var REGEDX, Mascara : LongWord;
Suportado : array[0..31] of byte;
i : integer;
begin
{ ... }
Mascara := 1;
for i := 0 to 31 do begin
if (REGEDX and Mascara) <> 0 then
Suportado[i] := 1 { Suportado }
else
Suportado[i] := 0; { Não suportado }
Mascara := Mascara * 2;
end;
{ ... }

No código acima, a variável preparada para auxiliar na extração dos bits chama-se Mascara. Ao final da execução desse trecho, teremos em cada posição do array Suportado um sinal indicando se o recurso existe ou não na CPU. Mas qual recurso ?

O significado de cada posição varia de acordo com o fabricante da CPU, sendo que até mesmo o conjunto de recursos incluídos em um e outro é diferente. Para facilitar a exibição das informações sobre os recursos podemos montar um array com 32 posições para texto e alimentar cada uma com um lembrete do significado do recurso. O quadro abaixo mostra os recursos disponíveis em processadores Intel:
if(StrComp(VendorID, 'GenuineIntel') = 0)
then begin
Recurso[0]:='FPU'; { Floating Point Unit }
Recurso[1]:='VME'; { Virtual Mode Extension }
Recurso[2]:='DE'; { Debugging Extension }
Recurso[3]:='PSE'; { Page Size Extension }
Recurso[4]:='TSC'; { Time Stamp Counter }
Recurso[5]:='MSR'; { Model Specific Registers }
Recurso[6]:='PAE'; { Physical Address Extension }
Recurso[7]:='MCE'; { Machine Check Extension }
Recurso[8]:='CX8'; { CMPXCHG8 Instruction}
Recurso[9]:='APIC'; { On-chip APIC Hardware }
Recurso[10]:=''; { Reserved }
Recurso[11]:='SEP'; { Fast system call }
Recurso[12]:='MTRR'; { Machine Type Range Registers }
Recurso[13]:='PGE'; { Global Paging Extension }
Recurso[14]:='MCA'; { Machine Check Architecture }
Recurso[15]:='CMOV'; { Conditional Move Instruction }
Recurso[16]:='PAT'; { Page Attribute Table }
Recurso[17]:='PSE-36'; { 36-bit Page Size Extension }
Recurso[18]:='PSN'; { 96-bit Processor Serial Number }
Recurso[19]:='CLFSH'; { CLFLUSH Instruction }
Recurso[20]:=''; { Reserved }
Recurso[21]:='DS'; { Debug Trace Store }
Recurso[22]:='ACPI'; { ACPI Support }
Recurso[23]:='MMX'; { MMX Technology }
Recurso[24]:='FXSR'; { FXSAVE FXRSTOR (Fast save and restore) }
Recurso[25]:='SSE'; { Streaming SIMD Extensions }
Recurso[26]:='SSE2'; { Streaming SIMD Extensions 2 }
Recurso[27]:='SS'; { Self-Snoop }
Recurso[28]:='HTT'; { Hyper-Threading Technology }
Recurso[29]:='TM'; { Thermal Monitor Supported }
Recurso[30]:=''; { Reserved }
Recurso[31]:='PBE'; { Pending Break Enable }
end;

Veja este link para saber como obter o nome do fabricante. A documentação sobre o uso do CPUID em processadores Intel pode ser acessada aqui.

O quadro abaixo mostra os recursos disponíveis em processadores AMD:
if(StrComp(VendorID, 'AuthenticAMD') = 0)
then begin
Recurso[0]:='FPU'; { Floating Point Unit }
Recurso[1]:='VME'; { Virtual Mode Extension }
Recurso[2]:='DE'; { Debugging Extension }
Recurso[3]:='PSE'; { Page Size Extension }
Recurso[4]:='TSC'; { Time Stamp Counter }
Recurso[5]:='MSR'; { Model Specific Registers }
Recurso[6]:='PAE'; { Physical Address Extesnion }
Recurso[7]:='MCE'; { Machine Check Extension }
Recurso[8]:='CX8'; { CMPXCHG8 Instruction }
Recurso[9]:='APIC'; { On-chip APIC Hardware }
Recurso[10]:=''; { Reserved }
Recurso[11]:='SEP'; { SYSENTER and SYSEXIT instructions }
Recurso[12]:='MTRR'; { Machine Type Range Registers }
Recurso[13]:='PGE'; { Global Paging Extension }
Recurso[14]:='MCA'; { Machine Check Architecture }
Recurso[15]:='CMOV'; { Conditional Move Instruction }
Recurso[16]:='PAT'; { Page Attribute Table }
Recurso[17]:='PSE-36'; { 36-bit Page Size Extension }
Recurso[18]:=''; { Reserved }
Recurso[19]:='CLFSH'; { CLFLUSH instruction support }
Recurso[20]:=''; { Reserved }
Recurso[21]:=''; { Reserved }
Recurso[22]:=''; { Reserved }
Recurso[23]:='MMX'; { MMX Technology }
Recurso[24]:='FXSR'; { FXSAVE FXRSTOR (Fast save and restore) }
Recurso[25]:='SSE'; { Streaming SIMD Extensions }
Recurso[26]:='SSE2'; { SSE2 instruction support }
Recurso[27]:=''; { Reserved }
Recurso[28]:='HTT'; { Hyper-Threading Technology }
Recurso[29]:=''; { Reserved }
Recurso[30]:=''; { Reserved }
Recurso[31]:=''; { Reserved }
end;

A documentação sobre o uso do CPUID em processadores AMD pode ser acessada aqui.

Ambos os arrays montados neste post - Suportado e Recurso - estão sincronizados. Então, para mostrar se um recurso está ou não presente basta percorrer os arrays usando o mesmo índice e mostrando lado a lado o nome do recurso e o flag indicativo de suporte a este recurso.

19 de outubro de 2010

Fazendo Download e Upload usando FTP com Delphi

O FTP é um protocolo bastante antigo, anterior ao advento da internet mas largamente usado nela para transferência de arquivos - os populares download e upload. Até publiquei um post em julho explicando o funcionamento teórico do FTP. Neste post eu pretendo mostrar algo mais prático, incluindo num programa em Delphi a capacidade de fazer transferência de arquivos usando este protocolo.

O Delphi vem incluindo há bastante tempo em sua paleta de componentes o tratamento para um amplo conjunto de protocolos. Esses componentes são o produto de um projeto Open Source chamado Indy Internet Direct e estão disponíveis para várias plataformas de desenvolvimento - Delphi, C++, C#, etc. Eles encapsulam os detalhes de mais baixo nível do funcionamento de cada protocolo, simplificando bastante a sua utilização. Há componentes para considerar ambos os lados de uma comunicação, permitindo a criação tanto de aplicações servidoras em relação a um protocolo quanto aquelas que serão apenas Clients, isto é, consumidoras do serviço provido por um servidor.

No caso do FTP, vou me ater ao componente TIdFTP, que implementa o lado Client de uma comunicação para transferência de arquivos. O componente tem métodos para tratar os comandos inerentes a um Client FTP; portanto, a mesma instância pode tratar tanto o envio quanto o recebimento de arquivos, dentre outras possibilidades.

Qualquer que seja a operação desejada, o primeiro passo tem que ser a conexão com um servidor. O exemplo abaixo preenche as propriedades mais importantes do FTP:
IdFTP1.Disconnect();

IdFTP1.Host := 'ftp.abc71.com.br';
IdFTP1.Port := 21;
IdFTP1.Username := 'usuario_para_login';
IdFTP1.Password := 'senha';
IdFTP1.Passive := false; { usa modo ativo }
IdFTP1.RecvBufferSize := 8192;
try
{ Espera até 10 segundos pela conexão }
IdFTP1.Connect(true, 10000);
except
on E: Exception do
_Erro = E.Message;
end;
Os parâmetros Host e Port identificam o endereço do servidor FTP com o qual queremos conectar. O Username e a Password servem para fazer o login naquele servidor; são informações que você deve conhecer previamente - aqui, os dados fornecidos são apenas exemplos. Alguns servidores permitem que se conecte anonimamente; para isso é recomendado que se informe um endereço de email em Password. Caso você esteja tentando fazer a conexão a partir de um computador que só se conecta na rede através de um proxy, use a propriedade ProxySettings para complementar as configurações.

O valor de RecvBufferSize indica o tamanho do buffer interno para a recepção de dados; normalmente, ele não precisa ser alterado. Finalmente, a função Connect faz todo o trabalho para estabelecer a conexão, aguardando um tempo máximo especificado na própria função. O primeiro parâmetro passado a ela indica se o login deve ocorrer junto com a conexão. Se optar por não fazer o login neste momento, você terá que chamar manualmente a função Login.

Com a conexão estabelecida e o login feito com sucesso, enviar um arquivo (fazer o upload) é bastante simples. Basta chamar a função Put do TIdFTP:
IdFTP1.Put (AFileName, ADstFileName, false);
O primeiro parâmetro é o nome completo do arquivo que você quer mandar, incluindo o caminho. O segundo parâmetro é como o arquivo será nomeado no servidor, isto é, o seu arquivo pode ser enviado com um nome diferente. Para mantê-lo com o mesmo nome no servidor, simplesmente passe um texto vazio no lugar. Para mandar para uma pasta específica no servidor, informe o nome dela como parte do nome do arquivo. O componente FTP também possui métodos para navegar pela árvore de pastas, criar uma nova pasta e listar as pastas atualmente existentes, caso seja necessário. O último parâmetro passado ao Put sinaliza ao servidor o que fazer caso um arquivo com o mesmo nome já exista. Informar true fará com que o servidor inclua o conteúdo do seu arquivo no final do arquivo já existente.

Fazer o download de um arquivo também é simples. Basicamente, chame a função Get do TIdFTP:
IdFTP1.Get (AFileName, ADstFileName, true, false);
Aqui a situação é invertida em relação ao Put. O nome de arquivo passado no primeiro parâmetro identifica um arquivo no servidor, enquanto o segundo parâmetro é o nome com o qual queremos salvá-lo localmente. O terceiro parâmetro determina se o download sobreporá ou não um arquivo local que tenha o mesmo nome. Por fim, o último parâmetro indica se o download deve tentar prosseguir a partir do ponto onde uma tentativa anterior tenha sido interrompida.

Quando terminar o uso do componente, é conveniente chamar o método Quit para encerrar a conexão e devolver os recursos usados pelo sistema operacional.

As operações Get e Put podem ser bastante demoradas, dependendo do tamanho do arquivo sendo transferido. Então, para evitar que a aplicação pareça travada, é possível responder a alguns eventos no TIdFTP para dar ao usuário um retorno sobre o andamento da operação. O evento OnStatus notifica o programa a respeito de mudanças no estado da conexão. Já os eventos OnWorkBegin, OnWork e OnWorkEnd tratam do progresso da transferência do arquivo, informando o tamanho esperado do trabalho, a evolução da quantidade de bytes transferida enquanto a operação está em andamento e, por fim, sinalizando a conclusão da transferência. Com isso, podemos, por exemplo, incluir uma barra de progresso na tela para acompanhar toda a operação.

13 de outubro de 2010

O futuro da computação: dispositivos sensíveis ao contexto

O exercício da futurologia é uma atividade que sempre fascina a humanidade. Não há quem não goste de especular sobre como as coisas serão no futuro. Embora haja previsões mirabolantes, espetaculares, que apresentam um futuro completamente diferente daquilo com que estamos acostumados hoje, outras são muito mais pragmáticas e se focam num futuro não tão distante. Parece ser esse o caso que emerge do forum para desenvolvedores da Intel quando eles falam em Computação sensível ao Contexto, isto é, aquela onde os computadores terão uma inteligência inerente que será capaz de distinguir a situação na qual estiverem sendo utilizados e reagirão de acordo com essa situação.

Como eles já estão pesquisando sobre esse assunto, já nem é mais previsão e sim a revelação de um projeto. A ideia é mesmo muito interessante e nem me pareceu que esteja tão distante, sendo mais uma questão de combinar tecnologias já existentes de uma forma funcional - mais ou menos como aconteceu com a convergência tecnológica, que visa integrar num único dispositivo funções antes implementadas em vários aparelhos distintos.

A matéria que está reproduzida abaixo sobre a computação sensível ao contexto é da IDG Now. O texto original pode ser acessado aqui.
A melhor maneira de prever o futuro é inventá-lo. Há anos este vem sendo o mantra da Intel. Que também há anos realiza, na cidade de São Francisco, o Intel Developer Forum (IDF), evento organizado com o objetivo de aproximar seus técnicos e executivos da comunidade de desenvolvedores e da imprensa internacional. No IDF a Intel revela sua visão do futuro da computação e como trabalha para estar bem posicionada quando este futuro chegar.

Este ano o IDF aconteceu em meados de setembro. E revelou a aposta da Intel em um futuro da computação sensível ao contexto, que deverá mudar radicalmente a forma como interagimos e nos relacionamos com os dispositivos e serviços de informação.

Segundo a Intel, os dispositivos "sensíveis ao contexto" conseguirão prever as necessidades dos usuários, aconselhá-los e guiá-los durante todo o dia de uma maneira mais parecida com um assistente pessoal do que um computador tradicional. Imagine o seu PC te aconselhando a sair de casa dez minutos mais cedo para o seu próximo compromisso devido ao engarrafamento no seu caminho para o trabalho. Ou em um controle remoto capaz de determinar instantaneamente quem o está segurando e carregar as preferências da TV inteligente para essa pessoa.

Isso tudo pode soar a ficção científica, mas já pode ser demonstrado, em boa parte, nos laboratórios da Intel. Com os dispositivos tendo cada vez mais sensores, poder de processamento, conectividade e capacidades inovadoras , os pesquisadores da empresa estão focados em oferecer novas experiências orientadas pelo contexto aos usuários, segundo demonstrou ao vivo, no IDF, o Vice-Presidente e CTO da Intel, Diretor da Intel Labs e Senior Fellow, Justin Rattner.

Imaginem um dispositivo que usa inúmeros tipos de sensores para determinar o que você fará, seja dormir na sua cama ou correr com um amigo. Ao combinar as informações do sensor rígido como onde você está e as condições a sua volta, com as dos sensores flexíveis, como seu calendário, suas redes sociais e histórico de preferências, os dispositivos do futuro aprenderão constantemente sobre quem é você, como você vive, trabalha e se diverte. À medida que os seus dispositivos aprendem sobre a sua vida, eles podem começar a prever as suas necessidades.

Entre os exemplos demonstrados por Rattner no IDF estava o projeto de pesquisa chamado Socially Enabled Services (SENS). Tecnologia que dá aos dispositivos móveis (celulares, principalmente) a habilidade de compreender as suas atividades em tempo real e, caso você deseje, compartilhar essa informação "ao vivo e a cores" com os amigos e parentes da sua rede por meio de animações gráficas no dispositivo que estiver disponível, seja PC, smartphone ou TV. Clique aqui para ouvir a explicação, em inglês.

"Ao mesmo tempo em que estamos desenvolvendo todas essas novas maneiras para experimentar, reunir e compartilhar dados contextuais, a Intel está ainda mais focada em garantir a privacidade e a segurança à medida que bilhões de dispositivos se conectam e ficam mais inteligentes", declarou Rattner. "A nossa visão é habilitar os dispositivos a gerar e usar informações contextuais para uma melhor experiência do usuário, garantindo a segurança e a privacidade das informações pessoais de um indivíduo. Por trás desse novo nível de segurança, estão as próximas técnicas habilitadas por hardware da Intel que melhoram dramaticamente a habilidade de todos os dispositivos se defenderem contra possíveis ataques".

O que pouca gente sabe é que o início das pesquisas com computação sensível ao contexto datam de 1991, no Palo Alto Research Center (PARC), que completa 40 anos em 2010. Lembra das pesquisas com a computação ubíqua? Termo cunhado pelo saudoso e querido Mark Weiser, cientista chefe do Centro de Pesquisa Xerox PARC, no artigo "O Computador do Século 21" (The Computer for the 21st Century )? Para ele, a computação não seria exclusividade de um computador, uma simples caixa mesmo que de dimensões reduzidas e, sim, diversos dispositivos conectados entre si. E invisível aos olhos. O foco dos usuários ficaria voltado para a tarefa, e não para a ferramenta utilizada, utilizando-se de computação sem perceber ou necessitar de conhecimentos técnicos da máquina utilizada.

Pois estamos chegando lá…


8 de outubro de 2010

Descobrindo quais aplicações são iniciadas junto com o Windows

Você já teve a sensação de que há coisas demais sendo carregadas junto com o Sistema Operacional quando liga seu computador ? Ou, pior ainda, viu que há um programa sendo iniciado junto com o Windows e não conseguiu descobrir como fazer para impedir que ele seja carregado? Tive um problema assim recentemente, relacionado com o módulo de segurança do site de meu banco, um programa que se chama G-Buster Browser Defense (instalado automaticamente pelo site e colocado na pasta GbPlugin). Em algumas situações ele deixa o computador extremamente lento mas a forma com que ele é instalado não permite remoção fácil. Para saber mais sobre essa remoção especificamente, veja este endereço.

Ao pesquisar uma solução para o problema da lentidão, encontrei uma ferramenta muito boa para monitorar tudo que está sendo iniciado junto com o Windows. A ferramenta, que se chama AutoRuns, é parte da coleção de utilitários desenvolvidos pela Systinternals, tal como o Process Explorer sobre o qual já falei no blog.

Ao contrário de outras ferramentas que se propõem listar os programas iniciados com o Windows, o AutoRuns vai a fundo na sua busca. São incluídos locais como a lista de serviços do Windows, programas diretamente marcados para iniciar com o sistema, os programas registrados como auxiliares do shell (os chamados hooks), objetos auxiliares do navegador de internet, notificações do subsistema de logon e outros. Com isso, é possível fazer uma análise bastante profunda do que realmente é necessário ser iniciado com o Windows, resultando numa inicialização mais rápida do sistema. Obviamente, esse trabalho de limpeza deve ser feito com conhecimento de causa para evitar que o sistema passe a sofrer com mal funcionamentos e instabilidades. Recomenda-se até mesmo a criação de pontos de restauração para o caso de algo sair errado. A imagem abaixo é uma captura de tela da aplicação.
Captura de tela do AutoRuns

Quando se executa o programa, ele imediatamente varre as entradas relevantes do registry, produzindo uma listagem na ordem exata com que essas entradas são processadas durante a carga do Windows. De início, todas as entradas são exibidas numa guia geral mas há também guias organizadas por tipo de inicialização, o que facilita o trabalho de localizar entradas específicas. Por exemplo, há uma guia exclusiva para os Serviços de inicialização automática e outra para os hooks registrados para o Windows Explorer. Em qualquer das guias, os itens levantados vêm acompanhados por uma caixa de seleção. Ao desmarcar essa caixa, o item em questão é temporariamente desabilitado e não será carregado nos próximos boots, até que ela seja marcada de novo. Se preferir, pode remover a entrada em definitivo. Em ambos os casos, os privilégios de manutenção do registry se aplicam, isto é, você só poderá fazer a alteração se o seu usuário tiver a permissão apropriada.

Para evitar que muitas entradas apareçam na listagem, há opção - marcada por padrão - de esconder aquelas que são criadas e controladas pelo próprio Windows. Estas são, em tese, mais arriscadas de se remover ou de se suspender. A ferramenta tem ainda recurso para permitir encontrar as entradas que contenham um texto qualquer, informado pelo usuário.

Os itens são levantados inicialmente para o usuário atual do Windows mas a aplicação permite fazer o levantamento das entradas para qualquer outro usuário que já tenha se logado no computador. Basta selecionar o usuário desejado através da opção de menu User para que o levantamento das entradas específicas desse usuário seja feito, permitindo ao administrador fazer um monitoramento e a limpeza que for conveniente.

Ainda no sentido de auxiliar os administradores, o AutoRuns é distribuído também com uma versão console para ser executada na linha de comando. Isso facilita a automatização de tarefas através da inclusão de comandos da aplicação em arquivos batches. Mais informações sobre quais comandos estão disponíveis por esse meio podem ser encontrados no site da ferramenta.

4 de outubro de 2010

Um novo paradigma: Programação Orientada a Aspectos

As ferramentas de modelagem de sistemas disponíveis para os Arquitetos de Software evoluem em paralelo com as técnicas de programação - quando um conceito é introduzido numa ferramenta, linguagens de programação rapidamente o incorporam também. Nos tempos em que o DFD (Diagrama de Fluxo de Dados) reinava, a programação de computadores era majoritariamente procedural. Isto é, os programas eram construídos com instruções sequenciais que emulavam o fluxo de dados definido pelo Diagrama, utilizando linguagens como o COBOL, Clipper ou Pascal. Hoje, as linguagems de programação comerciais mais usadas são calcadas no conceito de classes - Java, .Net, Delphi, etc. - e os sistemas são modelados frequentemente usando Diagramas de Classes e outras ferramentas que constituem a UML (Unified Modeling Language).

Essa forma de trabalho, no entanto, obriga o projetista a estabelecer relações entre certas classes que possuem pouco ou nada em comum, resultando em modelagens por vezes confusas, complicadas de se dar manutenção. Para ilustrar essa questão, imagine que você está modelando um sistema com operações que serão tratadas como transações no banco de dados.

Neste sistema, haverá operações para movimentação de estoque (com saída de quantidade de um depósito e a respectiva entrada no depósito destino), para registrar contabilizações (envolvendo uma ou mais contas contábeis para débito e crédito) e para efetuar pagamentos a fornecedores. Distingue-se neste cenário a necessidade de modelagem de diversas classes de objetos: item de estoque, conta contábil, movimento de estoque, contabilização, fornecedor, entre outros. Há ainda claramente uma entidade que deve controlar as transações no banco de dados para garantir que as alterações comandadas numa operação sejam tratadas como um bloco único. Embora nada tenham em comum, tanto movimentos de estoque quanto pagamentos a fornecedores devem ser contabilizados. Um diagrama de classes que ilustre essas relações ficará confuso por misturar conceitos de movimentação de itens e de pagamentos. A situação tende a piorar se surgirem outras operações que precisem ser contabilizadas. E do ponto de vista da programação, modificações na classe de contabilização afetarão todas as outras classes, exigindo que estas também sejam revisadas.

Recursos que permeiam várias classes de um sistema, vinculando mesmo aquelas que implementam regras conceitualmente distantes, são chamados de cross-cutting. Outros exemplos de recursos assim: criação de logs de operações, auditoria em alteração de dados, níveis de permissão de acesso a dados, autorização para executar operações, tratamento de exceções, etc. Melhorar a solução para esse tipo de recurso é a proposta da Programação Orientada a Aspectos (POA), onde o código que implementa os recursos cross-cutting são retirados das classes de negócio e inseridos em módulos próprios - os Aspectos. O código das regras de negócio fica mais limpo e alterações no funcionamento dos recursos cross-cutting passam a ser centralizadas no Aspecto.

A POA depende ainda de um mecanismo que permita vincular a execução dos códigos do Aspecto à execução das regras de negócio. A solução proposta pela POA é centrado no modelo de pontos de ligação (Join Points). Tal modelo é definido por 3 características: o momento em que o código poderá ser executado - chamado de join point -, uma forma de especificar esses momentos e uma forma de especificar o código que deve ser executado em cada momento.

Um ponto de ligação pode ser encarado como um evento que ocorre no código da regra de negócio - marcado pela execução de um determinado método ou pela alteração no valor de uma propriedade, por exemplo. Criar pontos de ligação significa, portanto, indicar quais desses eventos devem ser monitorados pelo Aspecto, usando para isso estruturas chamadas de pointcuts. Os pointcuts se valem de uma sintaxe especial para possibilitar a indicação de quais métodos e propriedades dispararão a execução do código relativo a um ponto de ligação. Ao código que será executado pelo Aspecto quando um ponto de ligação é encontrado dá-se o nome de Advice.

Assim como as Classes, Aspectos também podem conter variáveis internas (membros) e ter heranças para especializar seu comportamento, adequando-o a uma função mais específica. Voltando ao exemplo das operações dado no início deste post, uma solução usando Aspectos seria criar um Aspecto base para tratar transações com o banco de dados. Isso implica a criação de um ponto de ligação para apontar o início da função que realiza a operação, momento em que o advice desse ponto de ligação deve tomar providências para garantir a existência de uma transação no banco de dados. Outro ponto, ao final da operação, deve encerrar a transação. Para cuidar das transações que precisem ser contabilizadas faríamos uma herança desse Aspecto e introduziríamos o código necessário num dos pontos de ligação já estabelecidos. Nesta herança, indicaríamos como pointcuts apenas as classes expressando regras passíveis de serem contabilizadas.

A experiência mais bem sucedida para popularização da POA por enquanto é uma extensão da linguagem Java criada pelo Centro de Pesquisas da Xerox que tem o nome de AspectJ. Trata-se de um projeto open source disponível na Fundação Eclipse. Há ainda algumas bibliotecas voltadas para C#, disponíveis na forma de frameworks. O Delphi Prism - IDE para programação na plataforma .NET usando a linguagem Delphi - incorporou uma implementação para uso de POA em sua versão 2010 usando para isso recursos do próprio .NET. Veja aqui um exemplo de uso com a sintaxe do Delphi.

Tudo o que foi apresentado aqui não poderia ser resolvido apenas com uso de classes? Sim, poderia. Poderíamos até mesmo implementar tudo em uma solução exclusivamente procedural, se desejássemos. O ponto aqui é que as ferramentas até então existentes podem ser melhoradas para resolverem de forma mais eficiente determinados problemas. Uma nova filosofia está sendo amadurecida no campo da análise de sistemas e da programação e, mais cedo ou mais tarde, as linguagens também terão que evoluir para acompanhá-la consistentemente.