Como você mantém SOA DRY?

5

Em nossa organização, mudamos para uma "arquitetura mais orientada a serviços". Para dar um exemplo, vamos supor que precisamos recuperar um objeto "Quote". Esta cotação tem um remetente, um consignatário, números de telefone, contatos, endereços de e-mail e outras informações de localização. Em outras palavras, um objeto Quote é composto de muitos outros objetos.

Assim, parece que faria sentido criar um "Serviço de recuperação de cotações". Em nossa situação, conseguimos isso criando uma solução .NET e escrevendo o serviço. A API de serviço é semelhante a isso (em pseudo-código):

Function GetQuote(String ID) Returns Quote

Então, até aí tudo bem. Agora, quando esse serviço é consumido, para manter as coisas "desacopladas", estamos criando essencialmente uma duplicata do objeto Quote e do mapeamento da versão QuoteService do Quote para a versão do Quote do consumidor. Em muitos casos, essas classes terão exatamente as mesmas propriedades.

Portanto, se o serviço de cotação for consumido por cinco outros aplicativos, teremos seis definições do que é uma "cotação". Um para cada consumidor e outro para o serviço. Isso parece errado. Eu pensei que o código deveria ser seco, mas parece que o nosso método de SOA está nos forçando a criar toneladas de definições de classe duplicadas. O que estamos fazendo errado ou a duplicação de código é apenas um "mal necessário" da SOA?

    
por TaylorOtwell 17.11.2011 / 20:09
fonte

5 respostas

6

JGWiessman está correto em dizer que a falta de DRYness em proxies gerados automaticamente não é custosa, porque você não mantém o código gerado pelo cliente. Altere-o no servidor, atualize suas referências nos clientes, trabalho feito.

No entanto, existe uma alternativa, se o cliente e o servidor forem .NET. Você pode colocar todos os seus objetos em uma montagem separada, referenciada pelo cliente e pelo servidor. Se você gerar automaticamente o cliente código, é simplesmente uma interface, usando os mesmos objetos que o servidor usa .

Faça isso apenas se os objetos que você está compartilhando forem objetos de dados estúpidos e não inclua nenhum código do lado do servidor, caso contrário, você estará expondo esse código ao seu cliente.

Se o cliente e o servidor estiverem usando a mesma versão do .NET, você pode dar um passo além e include a interface apenas por configuração . Mas você precisa ter cuidado aqui. A interface no lado do servidor requer o atributo ServiceContract e, portanto, faz referência ao assembly ServiceModel, portanto, se as versões forem diferentes, você poderá ter problemas.

    
por 17.11.2011 / 21:12
fonte
1

Você não deve codificar manualmente a definição duplicada no consumidor. Em vez disso, use uma ferramenta como o Visual Studios para importar uma referência ao serviço da Web que uma classe de proxy gerada por máquina. Há código repetido, mas é gerado por máquina e você não precisa mantê-lo, apenas reimporte quando a definição principal mudar.

    
por 17.11.2011 / 20:52
fonte
0

Se tudo mais falhar, sempre consegui chegar ao código DRY pela geração de código. O pdr tem uma boa solução para quando o que você quer fazer se encaixa com o que a Microsoft oferece, mas se isso não acontecer, você pode sempre fazer sua própria geração de código.

Então, você pode manipular coisas como gerar código para clientes que não usam o .NET, criar regras codificadas explícitas como "O cliente B recebe a versão genérica do Quote, exceto o endereço de e-mail, mas adiciona um campo" (em vez de adicionar manualmente novos campos a todos os 302 serviços do cliente), etc.

    
por 17.11.2011 / 21:55
fonte
0

Eu pessoalmente prefiro uma abordagem ligeiramente diferente. Estou convencido de que na empresa de grande porte, o domínio de negócios é muito grande, então o DDD é o caminho a percorrer. Quando as entidades no lado do serviço (ou qualquer que seja o serviço de camada) são definidas da maneira necessária para o serviço , a lógica é definida para recuperá-las da persistência e executar lógica de qualquer tipo, sempre fornecer uma entidade mapeada (também conhecida como "contexto de ligação", "dto", "contrato de dados" etc) que é o mais adequado em tamanho e internals "irmão" para a entidade original, mas não inchada os detalhes que nunca serão expostos ao mundo exterior.

Então, quando o serviço é exposto, o contrato do serviço vai para uma DLL separada (biblioteca leve que você pode enviar para um cliente, sem lógica interna, apenas interfaces). Você também envia uma biblioteca contendo entidades para um cliente. Esses dois descrevem claramente o contrato de conversa e o formato das mensagens.

Se eu achar que há poucos pares para serem enviados agora, e eles são de estrutura diferente, então isso não é mais SOA, porque seu serviço blackbox agora está falando muito sobre si mesmo para os consumidores e além disso os consumidores pedem blackbox-service para mudar a forma. Eu normalmente uso o REST nesse caso para reduzir problemas com contratos de dados ou substituir métodos de serialização em objetos DTO e, dependendo do StreamingContext fornecido, fornecer uma forma diferente da entidade.

    
por 17.11.2011 / 23:25
fonte
0

Esta não é uma arquitetura ideal de SOA.

O provedor de serviços deve fornecer o mesmo serviço para todos os consumidores.

Os consumidores devem usar o que precisam das Respostas e ignorar o que não precisam.

Não vejo por que cada consumidor precisa de sua própria versão do serviço.

Mesmo no caso de um requisito de segurança que apenas alguns consumidores podem ver determinados dados, você pode colocar esses dados em um grupo opcional e simplesmente não enviá-los a consumidores não autorizados. Assim, preservando uma única interface para todos os clientes.

    
por 18.11.2011 / 03:12
fonte