Design Patterns - caso de publicação de componentes

Boa tarde!!!

Estou fazendo um sistema em que um agente (serviço em um servidor) deve receber uma requisição para instalar um componente na própria máquina.

Em meu modelo, pensei em ter uma classe que atuaria como um “Gateway” para receber as requisições, ordená-las, direcioná-las, etc. Além disso, criaria classes que implementam uma interface “Component”, em que o principal é ter um método “install()”, que faria o componente se instalar. Então, o “Gateway” iteraria sobre uma lista de "Component"s chamando o “install()”. Isso porque os componentes podem ser COM+, .Net, DLLs, arquivos em geral, etc, e o jeito de instalá-los é diferente.

OK, mas a impressão que tive ao analisar esse modelo é que algo está errado. Isso porque acredito que os componentes não poderiam se instalar, visto que são entidades do sistema. Deveria haver uma classe (ou conjunto de) para instalar esses componentes, só que elas deveriam diferenciar entre o tipo de componente. Outro motivo é que existem partes da instalação que são comuns entre alguns componentes, e eu não consegui uma solução de reaproveitamento nessa arquitetura. Deve haver um ou mais patterns para resolver esse tipo de problema.

Enfim, estou tentando encontrar uma solução melhor, mas como sou iniciante em arquitetura e design patterns (estou começando pelo GOF), estou perdido.

Vocês tem alguma idéia?

Wellington, obrigado pela ajuda!

Pesquisando um pouquinho, descobri que a tática de ter uma interface “Component” com “install()” em que as implementações saberiam como usar e tal faz parte do design pattern Strategy (http://en.wikipedia.org/wiki/Strategy_pattern).

Também achei uma alternativa para evitar a repetição de código em comum dos processos de instalação de componentes. É o design pattern Template Method (http://en.wikipedia.org/wiki/Template_method_pattern), que sugere a construção de uma classe abstrata que possui métodos referentes a fases do processo (no caso de instalação). Então, as classes que herdam desta, devem implementar os métodos abstratos ou sobrescrevê-los quando o comportamento for específico.

Wellington, acredito que neste caso o Template Method é uma solução mais adequada do que o GenericProcess, pq evita que alguém implemente Component, por exemplo, e não use o GenericProcess, refazendo código.

Agora em relação a separar a entidade Component da classe que instala um componente, estou pensando no seguinte: vou definir a interface Component em que suas implementações (ex: COMPlusComponent) tem os dados específicos de cada tipo (ex: instalar como proxy?). E vou criar uma outra estrutura de classes usando o Template Method, em que a classe abstrata seria ComponentInstaler (e uma subclasse seria ComPlusComponentInstaller). Aí resta um detalhe: precisaria de uma classe que devolve um instaler a partir de um componente (conforme o tipo). O que eu pensei foi que dessa forma, apesar de duplicar o número de classes (rs), eu não terei repetição de código, aumentarei a coesão (Component não serviria para 2 coisas ao mesmo tempo) e diminuirei o acoplamento (uma classe intermediária vai ligar Component a ComponentInstaller), de acordo com o GRASP. Só fico pensando ainda se existe algum pattern para essa ligação Component com ComponentInstaller.

E aí, pessoal? O que vocês acham disso tudo?

Obrigado.

Não acho que seu pensamento esteja, necessariamente errado.
Pode-se acertar isso definindo o processo em si e criar classes que façam partes do processo.
Por exemplo:
Você disse que parte do processo será comum a todas. Encapsule num GenericProcess. Forneça ao mesmo o Component e crie um método que, ao ser invocado, fará essa parte genérica.
Quanto ao que é distinto para cada um, pode-se criar estratégias onde seja possível reconhecer qual o tipo de componente e, com base nisso, instancie (ou obtenha) uma classe que encapsule esse comportamento único.

[quote=DanielGimenes]Wellington, obrigado pela ajuda!

Pesquisando um pouquinho, descobri que a tática de ter uma interface “Component” com “install()” em que as implementações saberiam como usar e tal faz parte do design pattern Strategy (http://en.wikipedia.org/wiki/Strategy_pattern).

Também achei uma alternativa para evitar a repetição de código em comum dos processos de instalação de componentes. É o design pattern Template Method (http://en.wikipedia.org/wiki/Template_method_pattern), que sugere a construção de uma classe abstrata que possui métodos referentes a fases do processo (no caso de instalação). Então, as classes que herdam desta, devem implementar os métodos abstratos ou sobrescrevê-los quando o comportamento for específico.

Wellington, acredito que neste caso o Template Method é uma solução mais adequada do que o GenericProcess, pq evita que alguém implemente Component, por exemplo, e não use o GenericProcess, refazendo código.

Agora em relação a separar a entidade Component da classe que instala um componente, estou pensando no seguinte: vou definir a interface Component em que suas implementações (ex: COMPlusComponent) tem os dados específicos de cada tipo (ex: instalar como proxy?). E vou criar uma outra estrutura de classes usando o Template Method, em que a classe abstrata seria ComponentInstaler (e uma subclasse seria ComPlusComponentInstaller). Aí resta um detalhe: precisaria de uma classe que devolve um instaler a partir de um componente (conforme o tipo). O que eu pensei foi que dessa forma, apesar de duplicar o número de classes (rs), eu não terei repetição de código, aumentarei a coesão (Component não serviria para 2 coisas ao mesmo tempo) e diminuirei o acoplamento (uma classe intermediária vai ligar Component a ComponentInstaller), de acordo com o GRASP. Só fico pensando ainda se existe algum pattern para essa ligação Component com ComponentInstaller.

E aí, pessoal? O que vocês acham disso tudo?

Obrigado.
[/quote]
Eu não gosto muito de usar TemplateMethods pois insere a necessidade de herança de classes abstratas e nem sempre isso é adequado mas não nego que também resolva seu problema. (PS: Sou péssimo com nomes de Patterns hehehe). Mas concordo plenamente com o Pattern Strategy :slight_smile:

Onde você citou “pq evita que alguém implemente Component, por exemplo, e não use o GenericProcess, refazendo código.”, não é o Pattern em si não evita isso :wink:
Meu exemplo, se não me engano, se encaixaria no Command Pattern http://en.wikipedia.org/wiki/Command_pattern

Quanto ao Component e o ComponentInstaller, acredito que o ComponentInstaller deva conhecer quem ele vai instalar (Component). Imaginei um Factory que, informando qual componente a ser instalado (não precisa ser um objeto, mas um identificador do mesmo), o Factory devolva um objeto ComponentInstaller adequado ao componente.