SensediaSensediaSensediaSensedia
  • Products
    • API Management Platform
    • Governança de APIs
    • Event-Driven Architecture
    • Microservices & Service Mesh Architecture
    • PCI
    • Flexible Actions
  • Services
    • Consulting & Professional Services
    • API Care
    • Developer Experience
  • Solutions
    • Insurance
    • Open Banking
    • Retail & e-commerce
  • Content
    • Webinar e Ebooks
    • Blog
    • Cases
  • Contact
    • Customers
    • Support
  • Careers
  • Português
    • Inglês
    • Espanhol

Evolução de Componentes e Serviços

    Home SOA Evolução de Componentes e Serviços

    Evolução de Componentes e Serviços

    By Marcilio Oliveira | SOA | 5 comments | 13 agosto, 2008 | 0

    Quantos de vocês já passaram por este cenário?

    1. Um departamento da empresa solicita recursos para a criação de um novo componente de software (ou um serviço técnico). A justificativa é a padronização da forma de resolver um certo problema, e o conseqüente ganho de produtividade.
    2. Os recursos são aprovados e o tal componente é desenvolvido.
    3. Projetos começam a usar o componente, acham bom, ganham produtividade. Começam a solicitar novas features e correções de defeitos.
    4. Depois de algumas iterações do passo 3, os projetos estão reclamando da complexidade. O time de arquitetura então solicita recursos para fazer um refactoring do componente. A justificativa é a redução da complexidade e conseqüente ganho de produtividade.
    5. Volte ao passo 2. Não passe pelo início, não receba $200.

    Existem vários nomes para este fenômeno; pode ser “Feature Creep”, “Scope Creep”, ou até “crescimento desenfreado”. É fácil encontrar exemplos, tanto em projetos comerciais dentro das organizações quanto em projetos open-source (estou olhando pra você, Axis!). E vêm algumas perguntas: Onde é que nós erramos? E como não errar mais?

    Bom. Pode ser que isso não seja um erro, afinal.

    Fatalmente, durante o desenvolvimento de qualquer parte de um software, estamos sujeitos ao impasse de fazer tudo rápido e corrido, ou esperar demais e deixar a oportunidade passar. Na prática, estamos sempre pendendo para o primeiro extremo: criamos software que atende um certo problema, sem nos preocuparmos demais com os detalhes, justamente na esperança de evoluir e adaptar conforme os requisitos vão ficando mais claros. Isso é um ciclo de vida natural. Para um componente ou serviço já nascer redondinho, otimizado, seria necessário muito tempo, recursos, e conhecimento das especificações (“escolha quaisquer dois…”).

    Pode ser que o pulo do gato não seja evitar o refactoring. Talvez o certo seja considerá-lo uma necessidade, como uma troca de pele, e apenas nos programarmos para que essa troca não tenha grandes impactos. Neste ponto de vista, o componente nasce, ainda simples e rude; evolui, ganhando features e perdendo defeitos, tornando-se quase um “ouriço de software”; e por fim sofre uma metamorfose, onde os espinhos são aparados e sua forma é reavaliada.

    Evolução de um Componente
    Evolução de um Componente. Quanto mais demoramos, mais difícil é remover os espinhos…

    Isto ocorre tanto com componentes e frameworks “tradicionais” de software, quanto com serviços em uma SOA. Contudo, esta última está muito melhor preparada para tratar os sintomas.

    Considere uma arquitetura convencional, onde componentes de software são bibliotecas (JARs ou DLLs, por exemplo) de objetos, métodos e funções.

    • O acoplamento ainda é alto; mesmo usando fábricas e interfaces (Programação Orientada a Interfaces, uma das melhores práticas de SOA), uma nova versão de um componente implica pelo menos na implantação de um novo pacote.
    • Esse empacotamento é delicado: versões erradas ou duplicadas de classes num mesmo pacote podem causar erros estranhos, intermitentes e extremamente difíceis e frustrantes de corrigir.
    • Alterações que modificam a API (alterações das grandes!) implicam em alterar os clientes; na melhor das hipóteses, serão criados métodos sobrescritos, para que alguns fluxos continuem funcionando. Pode não parecer, mas a manutenção desses métodos sobrescritos é muito custosa: no decorrer do tempo, eles se acumulam e viram lixo, poluindo o código e dificultando o trabalho.

    Agora considere uma arquitetura orientada a serviços, onde existe um nó intermediário (Message Oriented Middleware — o seu ESB).

    • Este nó ajuda a reduzir o acoplamento entre clientes e provedores (como visto em um post anterior). Alterações que não afetam a API não precisam nem mesmo da implantação de um pacote; basta atualizar o provedor de serviços. Não há alterações físicas de código, pois estamos usando mensagens neutras.
    • Não é necessário manter métodos sobrescritos; o ESB pode, ao invés disso, aplicar content-based routing. Mensagens para a versão 1.0 do serviço são transformadas e encaminhadas para a 2.0; ou então um outro serviço de adaptação é criado para tratar esses casos. Manter o que já existe rodando e ao mesmo possibilitar novos cenários de uso é mais fácil.
    • A composição de serviços torna possível, e de fato exige, uma política de governança. Saber quais serviços são interligados, quais são as versões atuais, quem está usando as versões antigas.

    Ao fim e ao cabo, o ciclo nascimento-evolução-refactoring pode não ser nocivo. Ao contrário, pode ser bom para a maturidade do componente ou do serviço. O mais importante é gerenciar os riscos, saber quando é hora de limpar os espinhos, e saber usar um intermediário para facilitar esse trabalho de “jardinagem de software”.

    No tags.

    5 comments

    • joseventura Responder 14 de agosto de 2008 at 13:35

      Opa Fábio,

      Sim, tem uma relação. Tive uma experiência em projeto que era exatamente essa situação de “inchaço” de um componente. Ficamos conscientes do problema, e na época tentamos conter esse crescimento. Pouco depois fui em uma palestra de XP onde por coincidência foi mencionada a mesma situação, e realmente a abordagem ágil não é conter, mas gerenciar com consciência.

      Sobre extrapolar para um sistema inteiro: acredito que um refactoring desse porte, de uma vez só, teria um custo proibitivo. Por sorte, conforme os sistemas vão se tornando mais desacoplados (e temos várias técnicas para isso), os impactos vão diminuindo; justamente porque podemos fazer evoluções em partes isoladas.

    • frosato Responder 14 de agosto de 2008 at 12:56

      Ventura,

      Muito bom o artigo!!! Parabéns!!!

      Esta estratégia de nascimento-evolução-refactoring dos componentes ou serviços parece ter relação com as práticas dos métodos ágeis, onde o refactoring de uma aplicação é considerado uma tarefa nobre e necessária. Você concorda e extrapolaria esta tática para o desenvolvimento, não só de componentes, mas da aplicação como um todo? Essa possível relação foi casual ou você se baseou nessas metodologias ágeis?

      abraço,

      Fábio

    • Paulo Camara Responder 15 de agosto de 2008 at 12:08

      Deixa eu só fazer um comentário aqui sobre o lance do refactoring em métodos ágeis. Sim, Fábio, você está certo: os metodos Ageis pregam o refactoring como algo real e necessário. Porém, a experiência prática mostra que nenhum cliente tem dinheiro sobrando para permitir que seus sistemas (ou componentes) sofram alterações profundas e custosas de tempos em tempos. Isso não é justificável economicamente. Por isso que um bom projeto (aka design) é fundamental, independente do seu paradigma de desenvolvimento.

      Vejam que isso é bem diferente de tentar prever o futuro e fazer um design a prova dele. Isso, a experiência também prova que é improdutivo e ineficiente.

      Encontrar o meio termo é a arte de projetar sistemas. 🙂

      []s,

      Paulo

    • marcilio Responder 15 de agosto de 2008 at 13:22

      Aproveitando o assunto e ótimo texto do Ventura….

      Quando falamos de refactoring de componentes de caixinha, pensamos no update de versão do componente para os sistemas em produção que o utilizam.

      Embora seja o ideal, sob ponto de vista de gerenciamento dos componentes e controle de qualidade, isso pode muitas vezes não ser atrante, e nem ser justificável para os projetos.

      O que tenho percebido é que, de boa vontade, os sistemas vão evoluir ou atualizar versões de componentes apenas para duas situações:
      -1) evoluções que de fato impactem diretamente na utilização do componente no sistema (performance, por exemplo).
      -2) correção de defeito 🙂

      O sonho do grupo de componentes em manter todos os usuários usando as mesma versão do componente é um desafio e tanto, imagino que quem já teve que passar por isso por muitas vezes (Alô Paulão!), sabe do que estou falando…

      []s
      Marcílio

    • Eduardo Machado Responder 18 de agosto de 2008 at 11:58

      – A principal referência que conheço que liga métodos ágeis e refactoring é o livro do Fowler “Refactoring: Improving the Design of Existing Code”. Ele justamente prega essa necessidade rotineira por limpeza de código durante iteration, sprint, etc. Além do mais acho que a questão levantada pelo Paulo Camara é abordada justamente na definição que Fowler faz desta atividade, que é obter uma versão do software que seja funcionalmente idêntica, porém com aspectos de qualidade (o principal é a manutenibilidade) melhoradas.
      – A evolução de componentes é sempre complicado, e uma das referências que gosto são pesquisas de CBD do IC-UNICAMP. Este artigo é uma metodologia que, dentro do esquema tradicional de atribuir números de versão no formato Major.Minor.Update, essa metodologia mostra uma forma sistemática de incrementar esses números a partir de alterações no componente (e por extensão serviços).
      http://www.ic.unicamp.br/~alobo/publications/04-lobo.pdf

      Abs.

    Leave a Comment

    Cancelar resposta

    O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

    • Política de Privacidade
    Copyright © 2020 Sensedia | All Rights Reserved
    • Products
      • API Management Platform
      • Governança de APIs
      • Event-Driven Architecture
      • Microservices & Service Mesh Architecture
      • PCI
      • Flexible Actions
    • Services
      • Consulting & Professional Services
      • API Care
      • Developer Experience
    • Solutions
      • Insurance
      • Open Banking
      • Retail & e-commerce
    • Content
      • Webinar e Ebooks
      • Blog
      • Cases
    • Contact
      • Customers
      • Support
    • Careers
    • Português
      • Inglês
      • Espanhol
    Sensedia