SOA se
tornou um acrônimo bem conhecido e de certa forma
questionável. Se uma pessoa pedir a duas outras que
definam o que é SOA, provavelmente receberá duas
respostas diferentes, possivelmente conflitantes. Alguns
descrevem a SOA como uma infra-estrutura de TI para
habilitação comercial; outros vêem a SOA como algo que
aumenta a eficiência da TI. De muitas formas, a SOA é um
pouco como o poema de John Godfrey sobre o homem cego e
o elefante: cada homem descreve o elefante de uma forma
um pouco diferente, pois cada um deles é influenciado
por suas próprias experiências (por exemplo, o homem que
toca a tromba acredita que se trata de uma cobra, ao
passo que o que toca o marfim acredita que seja uma
lança). O elefante do Sr. Saxe é muito mais fácil de
descrever, pois ele existe como uma entidade física: a
SOA, no entanto, é muito mais difícil de descrever,
visto que as filosofias de design não estão disponíveis
como manifestação física.
A SOA é
uma abordagem de arquitetura para a criação de sistemas
criados a partir de serviços autônomos. Com a SOA, a
integração é uma previsão, e não algo em que não se
pensa: a solução final provavelmente será composta de
serviços desenvolvidos em diferentes linguagens de
programação, hospedadas em plataformas diferentes, com
uma variedade de modelos de segurança e de processos
comerciais. Apesar de esse conceito parecer
incrivelmente complexo, ele não é novo: alguns podem
argumentar que a SOA evoluiu das experiências associadas
ao projeto e ao desenvolvimento de sistemas distribuídos
com base em tecnologias disponíveis anteriormente.
Muitos dos conceitos associados à SOA, como serviços,
descoberta e ligação tardia, foram associados ao CORBA e
ao DCOM. Da mesma forma, muitos princípios de design de
serviço têm muito em comum com técnicas OOA/PPD
anteriores, baseadas em encapsulamento, abstração e
interfaces claramente definidas.
O
acrônimo SOA levanta uma questão óbvia: o que exatamente
é um serviço? Simplesmente, serviço é um programa com
que se pode interagir por meio de trocas de mensagens
bem-definidas. Os serviços devem ser projetados para
disponibilidade e estabilidade. Os serviços são criados
para durar, enquanto as configurações e agregações de
serviço são criadas para mudar. A agilidade muitas vezes
é promovida como uma das maiores vantagens da SOA: uma
organização com processos comerciais implementados em
uma infra-estrutura menos rígida é muito mais aberta a
mudanças que uma organização limitada por aplicativos
monolíticos subjacentes que levam semanas para
implementar uma pequena alteração. Os sistemas menos
rígidos resultam em processos comerciais menos rígidos,
visto que os processos comerciais não são mais
restringidos por limitações da infra-estrutura
subjacente. Os serviços e suas interfaces associadas
devem permanecer estáveis, permitindo que sejam
reconfigurados ou reagregados para atender às sempre
novas necessidades das empresas. Os serviços
permanecem estáveis, contando com interfaces baseadas em
padrões e em mensagens bem-definidas: em outras
palavras, esquemas SOAP e XML para definição de
mensagens. Os serviços projetados para a execução de
funções granulares simples com conhecimento limitado de
como as mensagens são passadas a eles ou deles
recuperadas provavelmente serão muito mais reutilizados
dentro de uma infra-estrutura maior de SOA. Como já
afirmado, relembramos que os princípios básicos de
design OO relacionados ao encapsulamento e ao design da
interface nos atenderão também quando projetarmos e
criarmos Serviços da Web reutilizáveis. Podemos estender
esses princípios OO ao mundo de serviços da Web,
entendendo melhor as "quatro filosofias" da Orientação
de serviço citadas com freqüência:
Filosofia 1: os
limites são explícitos
Os
serviços interagem por intermédio de passagem explícita
de mensagens por limites bem-definidos. Cruzar limites
de serviços pode ser caro, dependendo de fatores
geográficos, de confiança ou de execução. Um limite
representa a fronteira entre a interface pública de um
serviço e sua implementação interna, privada. O limite
de um serviço é publicado por meio do WSDL e pode
incluir declarações que ditam as expectativas de
determinado serviço. O cruzamento de limites é
considerado uma tarefa cara por diversos motivos, entre
os quais:
|
• |
O local físico
do serviço almejado pode ser um fator
desconhecido. |
|
• |
Os modelos de
segurança e de confiança provavelmente mudarão a
cada cruzamento de limites. |
|
• |
O empacotamento
e a conversão de dados entre as representações
pública e privada de um serviço podem exigir
recursos adicionais; alguns deles podem ser
externos ao próprio serviço. |
|
• |
Ainda que os
serviços sejam criados para durar, as
configurações de serviço são criadas para mudar.
Esse fato implica que um serviço confiável possa
sofrer repentinas quedas de desempenho em função
de reconfigurações de rede ou de migração para
outro local físico. |
|
• |
Os consumidores
de serviço geralmente não sabem como os
processos internos privados foram implementados.
O consumidor de determinado serviço tem controle
limitado sobre o desempenho do serviço que está
sendo utilizado. |
O
padrão Integração orientada a serviços nos diz que
"invocações de serviço estão sujeitas à latência da
rede, à falha da rede e a falhas do sistema distribuído,
mas uma implementação local não. Uma quantidade
significativa de detecção de erros e lógica de correção
pode ser escrita para antecipar os impactos do uso de
interfaces de objetos remotos". Apesar de devermos
considerar que cruzar limites seja um processo caro,
também devemos ter cuidado ao implantar métodos locais
projetados para minimizar esses cruzamentos de limites.
Um sistema que implementa métodos e objetos locais
monolíticos pode ganhar desempenho, mas duplicar a
funcionalidade de um serviço previamente definido (essa
técnica foi chamada de "recorte e colagem" em OOP e
compartilha os mesmos riscos em relação à versão do
serviço).
Há
vários princípios a serem lembrados em relação à
primeira Filosofia da SO:
|
• |
Conheça seus
limites. Os serviços oferecem um contrato para
definir as interfaces públicas que eles
apresentam. Toda a interação com o serviço
ocorre por meio da interface pública. A
interface consiste em processos públicos e em
representações de dados públicas. O processo
público é o ponto de entrada para o serviço, ao
passo que a representação de dados pública
simboliza as mensagens usadas pelo processo. Se
usamos o WSDL para representar um contrato
simples, <message> representa os dados públicos
e <portType> representa os processos públicos |
|
• |
Os serviços
devem ser fáceis de usar. Ao projetar um
serviço, os desenvolvedores devem facilitar para
outros desenvolvedores o seu uso. A interface
(contrato) do serviço também deve ser projetada
para permitir a evolução do serviço sem romper
contratos com antigos consumidores. (Esse tópico
será analisado mais detalhadamente em futuros
artigos desta série.) |
|
• |
Evite interfaces
RPC. A passagem explícita de mensagens deve ser
favorecida em relação a um modelo como o RPC.
Essa abordagem separa o consumidor da parte
interna da implementação do serviço, permitindo
que os desenvolvedores de serviço evoluam seus
serviços ao mesmo tempo que minimizam o impacto
sobre consumidores do serviço (encapsulamento
pelo uso de mensagens públicas em vez de métodos
disponíveis publicamente). |
|
• |
Mantenha
reduzida a área da superfície de serviço. Quanto
mais interfaces públicas um serviço expõe, mais
difícil utilizá-lo e fazer sua manutenção.
Forneça algumas interfaces públicas
bem-definidas para o seu serviço. Essas
interfaces devem ser relativamente simples,
projetadas para aceitar uma mensagem de entrada
bem-definida e para responder com uma mensagem
de saída igualmente bem-definida. Depois que
essas interfaces são projetadas, elas devem
permanecer estáticas. Essas interfaces cumprem o
"constante" requisito de design a que os
serviços devem oferecer suporte, servindo de
face pública para a implementação interna,
privada, do serviço. |
|
• |
Os detalhes da
implementação interna (privada) não devem
ultrapassar o limite de um serviço. Se os
detalhes da implementação ultrapassarem o limite
do serviço, provavelmente ocorrerá uma maior
união entre o serviço e os consumidores desse
serviço. Os consumidores do serviço não devem
ser informados da parte interna da implementação
de um serviço, pois isso restringe as opções de
versão e atualização do serviço. A seção
Antipadrões deste artigo fornece um exemplo
detalhado dessa questão. |
Filosofia 2: os
serviços são autônomos
Os
serviços são entidades implantadas independentemente,
com versões e gerenciadas. Os desenvolvedores devem
evitar fazer suposições em relação ao espaço entre os
limites de serviço, visto que esse espaço tem muito mais
probabilidade de mudar do que os limites propriamente
ditos. Por exemplo, os limites do serviço devem ser
estáticos para minimizar o impacto da versão para o
consumidor. Ainda que os limites de um serviço sejam bem
estáveis, as opções de implantação desse serviço em
relação à diretiva, ao local físico ou à topologia da
rede provavelmente mudarão.
Os
serviços são tratados dinamicamente por meio de URIs,
permitindo que seus locais subjacentes e topologias de
implantação mudem ou evoluam com o tempo, com pouco
impacto em relação ao próprio serviço (isso também é
válido em relação aos canais de comunicação de um
serviço). Ainda que essas alterações possam ter pouco
impacto sobre o serviço, elas podem ter um impacto
devastador sobre aplicativos que o utilizem. E se um
serviço que você estava usando hoje passar para uma rede
na Nova Zelândia amanhã? A alteração no tempo de
resposta pode ter impactos esperados ou inesperados
sobre os consumidores do serviço. Os designers de
serviço devem adotar uma visão pessimista sobre o uso de
seus serviços: os serviços falharão e seus
comportamentos associados (níveis de serviço) estarão
sujeitos a mudança. Níveis apropriados de tratamento de
exceções e de lógica de compensação deverão ser
associados a qualquer invocação de serviço. Além disso,
consumidores de serviço podem precisar modificar suas
diretrizes para declarar tempos de resposta mínimos de
serviços a serem utilizados. Por exemplo, os
consumidores de um serviço podem exigir níveis variados
de serviço em relação à segurança, ao desempenho, às
transações e a muitos outros fatores. Uma diretriz
configurável permite que um único serviço ofereça
suporte a vários SLAs em relação à invocação de serviço
(diretrizes adicionais podem se concentrar em versão,
localização e outras questões). A comunicação das
expectativas de desempenho no nível de serviço preserva
a autonomia, visto que os serviços não precisam estar
familiarizados com as implementações internas um do
outro.
Os
consumidores de serviço não são os únicos que devem
adotar visões pessimistas do desempenho: os provedores
de serviço devem ser da mesma forma pessimistas ao
antecipar como seus serviços serão utilizados. Deve-se
esperar que os consumidores de serviço falhem, algumas
vezes sem notificar o próprio serviço. Os provedores de
serviço também não podem confiar que os consumidores
"farão a coisa certa". Por exemplo, os consumidores
podem tentar se comunicar usando mensagens
mal-elaboradas/mal-intencionadas ou tentar violar outras
diretrizes necessárias para uma interação de serviço
bem-sucedida. Os funcionários internos do serviço devem
tentar compensar esse uso inapropriado,
independentemente da intenção do usuário.
Apesar
de os serviços serem projetados para serem autônomos,
nenhum serviço é uma ilha. Uma solução baseada na SOA é
fractal, consistindo em vários serviços configurados
para uma solução específica. Pensando de forma autônoma,
logo se percebe que não há autoridade dirigindo em um
ambiente orientado a serviços: o conceito de "condutor"
de orquestra é falho (implicando mais ainda que o
conceito de "reduções de preços" nos serviços é falha,
mas esse tópico será tratado em outro artigo). As chaves
para executar serviços autônomos são isolamento e
separação. Os serviços são projetados e implantados
independentemente um do outro e só podem se comunicar
usando mensagens e diretrizes controladas por contrato.
Como
ocorre com outros princípios de design de serviço,
podemos aprender com nossas experiências passadas com o
design OO. O trabalho de Peter Herzum e de Oliver Sims
sobre fábricas de componentes comerciais apresenta
idéias interessantes sobre a natureza dos componentes
autônomos. Apesar de grande parte de seu trabalho ser
mais apropriada a soluções baseadas em componentes menos
detalhados, os princípios básicos de design ainda se
aplicam ao design de serviço.
Feitas
essas considerações, veja aqui alguns princípios de
design simples que o ajudarão a garantir a
compatibilidade com o segundo princípio da SO:
|
• |
Os serviços
devem ser implantados e ter a versão atualizada,
independentemente do sistema em que sejam
implantados e utilizados. |
|
• |
Os contratos
devem ser projetados pressupondo-se que, uma vez
publicados, não possam ser modificados. Essa
abordagem força os desenvolvedores a criarem
flexibilidade em seus designs de esquema. |
|
• |
Proteja os
serviços contra falhas, adotando uma visão
pessimista. Da perspectiva do consumidor,
planeje níveis pouco confiáveis de
disponibilidade e de desempenho do serviço. Da
perspectiva do fornecedor, espere que seu
serviço seja usado de forma errada
(deliberadamente ou não) e espere que os
consumidores do serviço falhem, talvez sem
notificar o serviço. |
Filosofia 3: os
serviços compartilham esquema e contrato, não a classe
Como
já afirmado, a interação com o serviço deve se basear
somente nas diretrizes, no esquema e nos comportamentos
baseados no contrato de um serviço. O contrato de um
serviço geralmente é definido usando-se o WSDL, e
contratos para agregações de serviços podem ser
definidos usando-se o BPEL (que, por sua vez, usa o WSDL
para cada serviço agregado).
A
maioria dos desenvolvedores define classes para
representar as várias entidades dentro de determinado
espaço problemático (por exemplo, Cliente, Pedido e
Produto). As classes combinam comportamento e dados
(mensagens) em uma única linguagem de programação ou
construção específica à plataforma. Os serviços dividem
esse modelo para maximizar a flexibilidade e a
interoperabilidade. Os serviços que se comunicam usando
mensagens baseadas no esquema XML não reconhecem as
linguagens e as plataformas de programação, garantindo
níveis mais amplos de interoperabilidade. O esquema
define a estrutura e o conteúdo das mensagens, ao passo
que o contrato de serviço define o comportamento do
próprio serviço.
Resumindo, o contrato de um serviço consiste nos
seguintes elementos:
|
• |
Formatos de
troca de mensagens definidos com o Esquema XML. |
|
• |
Padrões de troca
de mensagens (MEPs) definidos com o WSDL. |
|
• |
Recursos e
requisitos definidos com a especificação
WS-Policy. |
|
• |
O BPEL pode ser
usado como contrato no nível de processo
comercial para agregar vários serviços. |
Os
consumidores de serviço contarão com um contrato de
serviço para invocar um serviço e interagir com ele.
Havendo essa confiança, o contrato de um serviço deve
permanecer estável com o passar do tempo. Os contratos
devem ser projetados da forma mais explícita possível,
ao mesmo tempo tirando proveito da natureza extensível
do esquema XML (xsd:any) e do modelo de processamento
SOAP (cabeçalhos opcionais).
O
maior desafio da Terceira filosofia é sua permanência.
Depois que um contrato de serviço é publicado, é
extremamente difícil modificá-lo e ao mesmo tempo
minimizar o impacto sobre antigos consumidores do
serviço. A linha entre as representações de dados
interna e externa é fundamental para a implantação e a
reutilização bem-sucedida de determinado serviço. Os
dados públicos (dados passados entre serviços) devem se
basear em padrões organizacionais ou verticais,
garantindo ampla aceitação entre diferentes serviços. Os
dados privados (dados dentro de um serviço) são
encapsulados em um serviço. De alguma maneira, os
serviços são como representações menores de uma
organização que conduz transações de e-business. Assim
como uma organização deve mapear uma Ordem de compra
externo em seu formato interno de OC, um serviço também
deve mapear uma representação de dados sob contrato em
seu formato interno. Mais uma vez, nossas experiências
com encapsulamento de dados OO podem ser reutilizadas
para ilustrar um conceito semelhante: a representação
interna dos dados de um serviço só pode ser manipulada
por meio do contrato do serviço.
Feitas
essas considerações, veja aqui alguns princípios de
design simples que o ajudarão a garantir a
compatibilidade com o terceiro princípio da SO:
|
• |
Garanta que o
contrato de um serviço permaneça estável para
minimizar o impacto sobre os consumidores do
serviço. O contrato nesse sentido se refere à
representação de dados pública (dados), ao
padrão de troca de mensagens (WSDL) e a recursos
e níveis de serviço configuráveis (diretriz). |
|
• |
Os contratos
devem ser o mais explícitos possível para
minimizar a má interpretação. Além disso, os
contratos devem acomodar a futura versão do
serviço por meio da extensibilidade da sintaxe
XML e do modelo de processamento SOAP. |
|
• |
Evite manchar a
linha entre as representações de dados pública e
privada. O formato interno dos dados de um
serviço deve ficar oculto para os consumidores e
o esquema de dados público deve ser imutável
(preferencialmente com base em um padrão
organizacional, de facto ou de indústria). |
|
• |
Serviços de
versão quando há alterações no contrato de
serviço são inevitáveis. Essa abordagem minimiza
a ruptura de implementações do antigo
consumidor. |
Filosofia 4: a
compatibilidade com o serviço se baseia na diretriz
Ainda
que seja muitas vezes considerada a filosofia de design
menos compreendida, talvez seja uma das mais eficazes em
termos de implementação de serviços da Web flexíveis.
Não é possível comunicar alguns requisitos para
interação de serviço somente no WSDL. As expressões de
diretriz podem ser usadas para separar a compatibilidade
estrutural (o que é comunicado) da compatibilidade
semântica (como ou para quem uma mensagem é comunicada).
Os
requisitos operacionais para provedores de serviço podem
ser manifestados na forma de expressões de diretriz
legíveis em máquina. As expressões de diretriz oferecem
um conjunto configurável de semânticas interoperáveis
que regem o comportamento e as expectativas de
determinado serviço. A especificação WS-Policy define
uma estrutura de diretriz legível em máquina capaz de
expressar diretrizes no nível de serviço, permitindo que
elas sejam descobertas ou impostas em tempo de execução.
Por exemplo, um serviço de segurança do governo pode
exigir uma diretriz que imponha determinado nível de
serviço (fotos de passaporte que satisfaçam critérios
estabelecidos devem ser consultadas em um sistema de
identificação de terroristas, por exemplo). As
informações de diretriz associadas a esse serviço podem
ser usadas com vários outros cenários ou serviços
relacionados à condução de uma verificação de
antecedentes. A especificação WS-Policy pode ser usada
para impor esses requisitos sem exigir uma única linha
de código adicional. Esse cenário ilustra como uma
estrutura de diretriz fornece informações adicionais
sobre os requisitos de um serviço ao mesmo tempo
fornecendo um modelo de programação declarativa para
definição e execução do serviço.
Uma
declaração de diretriz identifica um comportamento que é
requisito (ou capacidade) de um assunto da diretriz. (No
cenário anterior, a declaração é a verificação de
antecedentes no sistema de identificação de
terroristas.) As declarações possuem semântica
específica ao domínio e serão posteriormente definidas
em especificações separadas, do próprio domínio, em
várias indústrias verticais (estabelecendo o conceito de
"estrutura" da WS-Policy).
Apesar
de os serviços controlados por diretriz continuarem
evoluindo, os desenvolvedores devem assegurar que suas
declarações de diretriz sejam o mais explícitas possível
em relação às expectativas do serviço e às
compatibilidades semânticas do serviço.
Padrões e
antipadrões da SOA
Agora
que você já tem conhecimento dos conceitos da SOA
(incluindo as filosofias de design da SO), chegou a hora
de aplicar o que aprendeu. O restante deste artigo
apresenta dois antipadrões e três padrões. Esses
antipadrões e padrões foram projetados de acordo com os
conceitos analisados anteriormente.
Por que padrões e
antipadrões?
As
pessoas tendem a pensar e se comunicar em padrões.
Christopher Alexander, autor de vários livros sobre
linguagens de padrões, definiu padrões como "uma
abstração de uma forma concreta que continua se
repetindo em contextos específicos, não-arbitrários". Os
padrões e as linguagens de padrões são meios de
descrever melhores práticas, designs testados e capturar
experiências passadas de forma que os outros aprendam
com essas experiências. Os padrões são uma abordagem
testada para entender rapidamente as diretrizes de
design e os vários contextos em que devem ser aplicadas.
Os antipadrões são, como se pode esperar, o oposto dos
padrões. Enquanto os padrões oferecem orientação testada
e melhores práticas, os antipadrões ilustram falhas
comuns de design e servem como método de aprendizado com
os erros dos outros. O restante deste artigo contém uma
revisão informal de dois antipadrões e de três padrões,
todos projetados para servir como guia para o
desenvolvimento de serviços da Web mais eficazes.
Os
antipadrões e padrões deste artigo seguem o formato
listado a seguir.
|
• |
Contexto:
uma breve explicação introdutória do padrão ou
do antipadrão. O contexto é fornecido de modo
que os leitores possam reconhecer possíveis
oportunidades para aplicar um modelo ou
reconhecer as características de um antipadrão
antes que ele seja totalmente instanciado. |
|
• |
Problema:
uma declaração simples, projetada para
estruturar os objetivos associados ao padrão ou
antipadrão. |
|
• |
Forças:
considerações adicionais que devem ser levadas
em conta na aplicação de determinado padrão ou
no reconhecimento de um antipadrão. |
|
• |
Solução:
uma descrição da resolução de determinado
antipadrão ou as etapas necessárias à aplicação
do padrão associado. |
|
• |
Sintomas e
conseqüências:
no caso dos antipadrões, os fatores que fazem um
antipadrão existir. No caso dos padrões, os
sintomas e as conseqüências podem voltar-se para
outros fatores ou questões a serem consideradas
antes da aplicação do padrão associado. |
Os
antipadrões incluem uma recomendação adicional sobre
como suas falhas de design associadas podem ser
aprimoradas.
Fonte:http://www.microsoft.com/brasil/msdn/Tecnologias/arquitetura/SOADesign_US.mspx
Tópicos Relacionados: