<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Ambiente Oak2</title>
  </head>

  <body>
    <h1>Ambiente Oak2</h1>

    <p>Uma questão importante para garantir a redução do acoplamento
      entre as partes de um sistema de informação complexo, é a de
      evitar chamadas a classes específicas para funcionalidades que
      podem em geral ser substituídas por outras implementações. Por
      exemplo, a camada de visualização da interface, pode precisar ser
      substituída entre, por exemplo, uma UI Gtk+, Qt, ncurses
      etc. Desta forma é interessante que todas essas escolhas sejam
      feitas através de pontos centralizadores.</p>

    <p>Este padrão é conhecido como "Class Factory". A idéia é, ao
      invés de instanciar um objeto de uma classe específica, ou de
      fazer o controle das alternativas em todos os pontos, delegar essa
      função a uma classe especial, responsável apenas por isso.</p>

    <p>E esta é a motivação do ambiente Oak2, representado pela classe
      Oak2::Environment. Esta classe irá receber as requisições para
      objetos que implementem determinadas APIs, e de acordo com regras
      que poderão ser parametrizadas ou estendidas, fazer a escolha de
      qual implementação será utilizada.</p>

    <p>Qualquer aplicação Oak2 terá o seu ambiente gerenciado, ou
      seja, isso fará parte da base de todo o Oak2, independente se
      estamos tratando de uma aplicação de pequeno porte, ou de um
      sistema de informação complexo e distribuído. Informações
      específicas como chaves de autenticação, caches etc serão
      gerenciados pelo ambiente.</p>

    <h2>A Visão dos Serviços</h2>

    <p>A classe Oak2::Environment tem uma certa similaridade com o
      InitialContext da API do Java, mas existem algumas diferenças
      claras. Em primeiro lugar, não é específico a uma tecnologia de
      comunicação. O InitialContext é bastante atrelado ao RMI, ele é,
      principalmente, um cliente JNDI. O Oak2::Environment vai permitir
      que serviços se registrem nele localmente, permitindo acesso
      (através dele) a classes locais e remotas.</p>

    <p>Para sintetizar, o Oak2::Environment é o local onde você irá
      localizar qualquer tipo de serviço, seja ele local ou remoto. É
      através dele que a infra-estrutura de plugins pode ser
      montada.</p>

    <p>A implementação de Oak2::Environment, sozinha, não pode fazer
      muita coisa, pois ela não conhece a implementação de nenhum
      serviço. Qualquer serviço que vá estar disponível precisa se
      registrar antecipadamente, dessa forma, qualquer aplicação Oak2 é
      potencialmente cliente e servidor de qualquer serviço.</p>

    <h3>Pequeno <i>background</i>: Como plugins podem fazer mágica em
      um sistema de informação?</h3>

    <p>Isso foi uma conclusão a qual eu cheguei após estar trabalhando
      na arquitetura de sistemas de informação relativamente complexos
      durante alguns anos. E foi a resposta que eu encontrei para uma
      pergunta que eu sempre me fazia até então: Como criar um sistema
      integrado mas mesmo assim manter o acoplamento reduzido?</p>

    <p>Vamos imaginar que você tem um sistema, com o cadastro de
      clientes, e que os dados dos clientes são utilizados na hora de
      criar um pedido de Venda. Você precisa, na interface de venda,
      permitir que o usuário navegue na lista de clientes (algo como um
      combobox) para escolher qual o cliente que está efetuando a
      compra.</p>

    <p>Agora vamos imaginar duas situações próximas. A primeira: Em
      uma das implantações do sistema os clientes não são gerenciados
      pelo seu sistema. Você deve obter a lista de um outro sistema, se
      mantendo integrado.</p>

    <p>A segunda: Um cliente específico quer que o usuário navegue
      utilizando o código de cadastro do cliente, e não o nome, mas você
      não pode mudar o sistema para ser dessa outra forma porque outros
      clientes continuam querendo que seja navegado pelo nome.</p>

    <p>Sem pensar em plugins, que opções você tem? Implementar as três
      versões e mantê-las separadamente, implementar parametrização no
      componente da lista de clientes (isso imaginando que você
      implementou um componente reutilizável para isso), parametrizar o
      código como um todo para saber de onde buscar a lista de
      clientes.</p>

    <p>É possível que você já tenha passado por essa situação e é bem
      provável que você tenha feito uma das três coisas. Não é tão
      absurdo pensar em um if clientex faça assim, else faça assado. Eu
      mesmo já cheguei a implementar coisas assim, porque se esse tipo
      de situação não for contornado arquiteturalmente, não será
      possível dar uma solução elegante, serão necessárias muitas
      gambiarras para tornar possíveis as coisas.</p>

    <p>No entanto, se o sistema tiver sido modelado utilizando
      plugins, será possível não acoplar o código do registro das vendas
      a nenhuma das três possibilidades, apenas à API que possibilita a
      seleção do cliente, de forma que será possível definir facilmente
      (sem if amarrado em código) que neste ambiente será usada esta
      implementação ou a outra.</p>

    <h2>E como funciona?</h2>

    <p>Isso é simples. Qualquer aplicação Oak2 sempre terá carregado a
      classe Oak2::Environment. Basta chamar o método, simples como:</p>

    <pre>$Oak2::Environment->methodX(parameters => values)</pre>
    
    <p>Isso é possível por que a classe é carregada pela classe
      Oak2::Object. Como todos os objetos são descendentes de
      Oak2::Object, ele sempre estará lá.</p>

    <h3>Principais métodos</h3>

    <p>Os métodos mais importantes da classe são os métodos
      register_service, unregister_service e request_service. Os três
      utilizam a mesma nomenclatura de URI (Universal Resource
      Identifier) para os serviços, mas existem duas URIs, a primeira é
      a URI da interface sendo implementada, utilizando o exemplo
      anterior seria algo como "/clientes/combobox". A segunda é a URI
      da implementação, que seria algo como "/clientes/combobox/byNome",
      "/clientes/combobox/byCodigo" e "/clientes/combobox/remote". Esses
      identificadores são as chaves para se obter os serviços.</p>

    <p>É possível registrar mais de um serviço com a mesma URI de
      interface no mesmo ambiente, mas a URI de implementação deve ser
      única. Quando o cliente requisitar o serviço, ele irá obter uma
      das implementações (se chamar o método no contexto de scalar) ou a
      lista de todas as implementações (se chamar o método no contexto
      de lista).</p>

    <p>Para maiores detalhes, veja a documentação da classe
    Oak2::Environment.</p>

    <hr>
    <address><a href="mailto:daniel@ruoso.com">Daniel Ruoso</a></address>
<!-- Created: Thu Apr  7 21:30:20 GMT+3 2005 -->
<!-- hhmts start -->
Last modified: Fri Apr  8 07:31:57 GMT+3 2005
<!-- hhmts end -->
  </body>
</html>