Showing posts with label component. Show all posts
Showing posts with label component. Show all posts

Wednesday, January 10, 2007

Domain Specific Languages e Estratificação por Estabilidade

2007 mal começou e o meme das DSLs já está provocando polêmica. Eric Evans, em entrevista na InfoQ, disse:

"More out on the cutting-edge are the efforts in the area of domain-specific languages (DSLs), which I have long believed could be the next big step for DDD. To date, we still don't have a tool that really gives us what we need. But people are experimenting more than ever in this area, and that makes me hopeful."
Philip Calçado citou o Evans e foi além, afirmando que "DSLs são iminentes mas as ferramentas simplesmente ainda não chegaram lá". Escrevendo em tom mais cético, Rodrigo Kumpera comentou que DSLs ainda parecem uma tecnologia de um exemplo só; da mesma maneira que toda palestra de AOP fala de logging, toda introdução à DSLs fala em configuração. Citando:

"Todos estão falando o tempo todo sobre como configuração é um problema a ser resolvido por linguagens de domínio. Até o Martin Fowler comete essa gafe em sua palestra na JAOO 2006! O problema é o mesmo que logging, eu diria, representa nenhum risco a complexidade de um projeto. Quantos realmente já tiveram problemas relacionados a dificuldade de colocar logging em uma aplicação? Configuração idem."
Eu acho que a analogia com AOP não procede. Tracing/logging é de fato um caso de uso (quase trivial, BTW) para AOP. Precisamos analisar configuração com mais cuidado. Tome por exemplo uma aplicação de eCommerce B2C tradicional (você pode imaginar que é, quem sabe, uma loja de, sei lá.., animais de estimação). Na primeira iteração do software, cada item à venda tem um preço de catálogo cadastrado. Essa decisão logo se mostra inflexível, pois uma variação sazonal nos preços é comum no varejo. O requisito é atendido com uma nova feature permitindo que se estabeleça um perentual de desconto/acréscimo por mês para cada produto. A interface com o usuário para esta feature se localiza numa tela entitulada "Configurações". Mais adiante percebe-se que a flexibilidade ainda está aquém do ideal, os clientes querem definir regras de preço mais complicadas, como:
se vendeu mais de 500 na semana passada, acréscimo de 10%.
Pode-se inserir estas regras (hard-coded) no meio do sistema ou decidir por manter a parametrização externa e usar uma DSL. Em qualquer caso, ainda podemos chamar isto de configuração?
Sabendo que código e dados são basicamente a mesma coisa, eu vejo a aplicação de DSLs como decisões a respeito de que tipo de informação faz parte do sistema, e que tipo de informação consiste em parametrização "externa". No fim das contas, é técnica para atender ao "Stable Dependencies Principle (S0P)", deve-se isolar as porções de um software com maior volatilidade e uma linguagem específica - talvez até editável por usuários finais - é uma boa alternativa para implementar os módulos menos estáveis.

Tuesday, August 15, 2006

Componentes e objetos

Muito já se escreveu sobre a distinção entre programação orientada a objetos (OO), desenvolvimento baseado em componentes (CBD) e service oriented architectures (SOA). Isso significa que este post vai indubitavelmente chover no molhado. Entretanto, não se pode dizer que o assunto está resolvido e acabado; eu só espero confundir menos do que esclareço.

Como bem lembrou Philip Calçado, não podemos nos esquecer de que estes conceitos todos foram concebidos em contextos diferentes por grupos distintos e sem maiores preocupações com uma coesão formal. OO por exemplo, tem origem na Noruega, mas foi conceptualizada de maneira mais completa no laboratório da Xerox em Palo Alto, sendo reificada numa sequência de protótipos da linguagem Smalltalk. O líder desse projeto foi o lendário Alan Kay, que também tem a distinção de ter cunhado o termo "programação orientada a objetos". Kay, que na época já tinha um background em biologia e matemática, imaginou um paradigma computacional centrado em entidades similares a células biológicas, que se comunicavam trocando mensagens químicas. Apesar da paternidade reconhecida, não há consenso sobre o que seria a definição de OO, então trabalharei com uma definição improvisada (não confie muito). Um objeto é caracterizado por:
  1. Comportamento. Ele é capaz de receber invocações* de outros objetos para efetuar uma computação e (a) responder com um outro objeto ou (b) alterar o seu estado. Para efetuar a computação, o objeto pode invocar outros objetos. Ele obtém acesso a estes objetos de três maneiras: criando - "instanciando" - novos objetos na hora, usando uma referência que é parte de seu estado ou recebendo-os no momento em que é invocado.
  2. Estado. Um objeto pode armazenar um conjunto de referências para outros objetos. Através dessas referências ele pode invocar comportamento dos outros objetos conforme descrito no ítem anterior.
  3. Identidade. Mesmo que o estado todo de um objeto se altere, ele ainda existe como a "mesma" entidade.
  4. Ciclo de vida. Um objeto é instanciado em algum momento, quando ele passa a existir (manter uma identidade). Ele também pode ser destruído em algum momento. As linguagens de programação que seguem o paradigma OO apresentam uma grande variedade de mecanismos para instanciar e destruir objetos (classes, protótipos, prefixos, gerenciamento manual de memória, coletor de lixo, ...).
Enquanto que objetos são entidades fundamentais de um modelo computacional, componentes são apenas uma alternativa para atender a certos requisitos encontrados em algumas aplicações. Essa afirmação pode parecer polêmica, por isso apelo para uma autoridade maior, Ralph "GoF" Johnson, que expôs bem essa consideração num post recente em seu blog:
It is important to realize the "components" are not technology, they are a customer requirement. Customers want to add on to their software system by adding a new component, and adding this component must not require that they change their existing system. It is like adding new speakers to a stereo system.
Ou seja, componentes são nada mais que uma unidade de extensão e/ou substituição dinâmica de um sistema de software. O adjetivo "dinâmico" é uma daquelas palavras que são jogadas por aí em contextos tão diversos a ponto de perder o seu significado, mas a noção aqui é bem simples: estamos considerando alterações realizadas em ambiente de produção, feitas por operadores do sistema. A partir dessa caracterização, podemos dezfazer uma série de confusões:
  • Uma aplicação pode usar componentes sem ser baseada em componentes. Isto é, é possível definir alguns poucos pontos de substituição e/ou extensão mantendo o resto do software completamente estático. Dentre os muitos exemplos estão a maioria dos programas de desktop; um exemplar típico é o Photoshop e seus plugins. É claro que também encontramos diversos casos no extremo oposto - aplicações totalmente baseadas em componentes - veja por exemplo os últimos servidores de aplicações e IDEs.
  • Um sistema pode ser modular mas não baseado em componentes, na acepção que estamos considerando. Basta que seja composto de partes pouco acopladas.
  • Não faz muito sentido projetar um sistema baseado em componentes fortemente acoplados. O motivo é simples: componentes fortemente acoplados exigem que um desenvolvedor independendente se preocupe com grandes porções do sistema, o que prejudica o atendimento ao requisito de reconfigurabilidade. Mesmo no caso de aplicações que limitam seu uso de componentes a extensões localizadas, é uma boa prática estabelecer uma interface reduzida entre o núcleo do sistema e os componentes.
  • A definição sugerida exige apenas que um sistema possa ser reconfigurado em ambiente de produção, não é necessário que ele tenha a capacidade de sofrer alterações enquanto está executando. Não obstante, existem algumas aplicações onde isto é um requisito real e soluções tecnológicas sofisticadas são necessárias.
  • O professor Johnson deixa bem claro que tecnologias como COM ou EJB não são necessárias para um sistema que use componentes. A rigor, para antender ao requisito delineado é suficiente um suporte tecnológico mínimo. Podemos imaginar até um sistema onde a escolha de componentes é feita através da substituição de arquivos objeto (em java seria um .class) no diretório de instalação.
  • Apesar do ponto anterior, é frequente que um sistema com componentes se beneficie de uma infra-estrutura básica para auxiliar na solução de problemas comuns como: controle do ciclo de vida, gerenciamento de dependências, suporte à modos de comunicação entre componentes, parametrização local (propriedades), etc.
Como já demorei muito mais do que imaginava para escrever este post - incluíndo um tempo desperdiçado reescrevendo uma boa porção do texto quando eu fiz besteira e perdi o draft - vou deixar para uma entrada futura a discussão sobre sistemas distribuídos e serviços.

Uma última observação: o leitor atento notará que a palavra reuso não aparece nesse post; isso não foi um acidente.

* Estou evitando a terminologia baseada em "mensagens" que é padrão em Smalltalk para evitar mais confusão.