fundo
Eu tenho um projeto que depende do uso de um determinado tipo de dispositivo de hardware, embora realmente não importe quem faz esse dispositivo de hardware desde que faça o que eu preciso. Com isso dito, mesmo dois dispositivos que devem fazer a mesma coisa terão diferenças quando não forem fabricados pelo mesmo fabricante. Então, estou pensando em usar uma interface para desacoplar o aplicativo da marca / modelo específico do dispositivo envolvido e, em vez disso, fazer com que a interface cubra apenas a funcionalidade de nível mais alto. Aqui está o que eu acho que minha arquitetura será:
- Defina uma interface em um projeto C #
IDevice
. - Tenha um concreto em uma biblioteca definida em outro projeto C #, que será usado para representar o dispositivo.
- Faça com que o dispositivo concreto implemente a
IDevice
interface. - A
IDevice
interface pode ter métodos comoGetMeasurement
ouSetRange
. - Faça com que o aplicativo tenha conhecimento sobre o concreto e passe o concreto para o código do aplicativo que utiliza ( não implementa ) o
IDevice
dispositivo.
Tenho certeza de que esse é o caminho certo a seguir, porque poderei alterar qual dispositivo está sendo usado sem afetar o aplicativo (o que parece acontecer algumas vezes). Em outras palavras, não importa como as implementações GetMeasurement
ou SetRange
realmente funcionem no concreto (pois podem diferir entre os fabricantes do dispositivo).
A única dúvida em minha mente é que agora tanto o aplicativo quanto a classe concreta do dispositivo dependem da biblioteca que contém a IDevice
interface. Mas isso é uma coisa ruim?
Também não vejo como o aplicativo não precisará saber sobre o dispositivo, a menos que ele IDevice
esteja no mesmo espaço para nome.
Questão
Parece a abordagem correta para implementar uma interface para dissociar a dependência entre meu aplicativo e o dispositivo que ele usa?
Respostas:
Eu acho que você tem um bom entendimento de como o software dissociado funciona :)
Não precisa ser!
Você pode lidar com todas essas preocupações com a Estrutura do projeto .
Do jeito que eu normalmente faço:
Common
projeto. Algo comoMyBiz.Project.Common
. Outros projetos são livres para fazer referência a ele, mas pode não fazer referência a outros projetos.MyBiz.Project.Devices.TemperatureSensors
. Este projeto fará referência aoCommon
projeto.Client
projeto, que é o ponto de entrada para o meu aplicativo (algo comoMyBiz.Project.Desktop
). Na inicialização, o aplicativo passa por um processo de Bootstrapping no qual eu configuro mapeamentos de abstração / implementação concreta. Posso instanciar meu concretoIDevices
como aquiWaterTemperatureSensor
eIRCameraTemperatureSensor
aqui, ou posso configurar serviços como Fábricas ou um contêiner de IoC para instanciar os tipos de concreto certos para mim mais tarde.O principal aqui é que apenas o seu
Client
projeto precisa estar ciente doCommon
projeto abstrato e de todos os projetos de implementação concretos. Ao restringir o mapeamento abstract-> Concrete ao seu código de Bootstrap, você possibilita que o restante do seu aplicativo não tenha conhecimento dos tipos de concreto.Código vagamente acoplado ftw :)
fonte
new Foo(new DeviceA());
), em vez de ter um campo privado no Foo instanciar o próprio DeviceA (private IDevice idevice = new DeviceA();
) - você ainda obtém o DI, como Foo desconhece o DeviceA no primeiro casoSim, essa parece ser a abordagem correta. Não, não é uma coisa ruim para o aplicativo e a biblioteca de dispositivos depender da interface, especialmente se você estiver no controle da implementação.
Se você estiver preocupado que os dispositivos nem sempre implementem a interface, por qualquer motivo, poderá utilizar o padrão do adaptador e adaptar a implementação concreta dos dispositivos à interface.
EDITAR
Ao abordar sua quinta preocupação, pense em uma estrutura como esta (suponho que você esteja no controle da definição de seus dispositivos):
Você tem uma biblioteca principal. Nele está uma interface chamada IDevice.
Na sua biblioteca de dispositivos, você tem uma referência à sua biblioteca principal e definiu uma série de dispositivos que implementam todos os dispositivos de ID. Você também tem uma fábrica que sabe como criar diferentes tipos de dispositivos de identificação.
No seu aplicativo, você inclui referências à biblioteca principal e à biblioteca de dispositivos. Seu aplicativo agora usa a fábrica para criar instâncias de objetos em conformidade com a interface do dispositivo de ID.
Essa é uma das muitas maneiras possíveis de solucionar suas preocupações.
EXEMPLOS:
fonte
Você precisa pensar o contrário. Se você não seguir esse caminho, o aplicativo precisará conhecer todos os diferentes dispositivos / implementações. O que você deve ter em mente é que alterar essa interface pode interromper seu aplicativo se ele já estiver disponível, portanto, você deve projetar essa interface com cuidado.
Simplesmente sim
O aplicativo pode carregar a montagem de concreto (dll) em tempo de execução. Consulte: /programming/465488/can-i-load-a-net-assembly-at-runtime-and-instantiate-a-type-knowing-only-the-na
Se você precisar descarregar / carregar dinamicamente esse "driver", precisará carregar o assembly em um AppDomain separado .
fonte
IDevice
interface para que seu dispositivo possa ser usado com seu aplicativo; portanto, não haveria outra maneira de IMO.