Aqui está o meu problema: eu quero ler as entradas de diferentes dispositivos HID, como um gamepad, corridas bem, joystick, etc. Praticamente qualquer controlador de jogo. A questão é que todos eles têm entradas diferentes.
O gamepad possui botões, interruptores e manípulos, enquanto o poço de corrida pode ter um manípulo. Consegui abstrair todos esses componentes diferentes em apenas 3, em vez de ter uma classe base com todas as combinações possíveis:
abstract class Device
{
public Buttons Buttons;
public Axes Axes;
public Switches Switches;
public GearSticks GearSticks;
//many more
}
Agora posso ter:
abstract class Device
{
public Buttons Buttons; //on or off
public Axes Axes; //range [-100%:100%]
public Switches Switches; //multiple states
}
No começo, fiquei feliz com isso, pois parecia cobrir todos os tipos possíveis de entrada e, portanto, minha classe pode permanecer fechada enquanto aberta à extensão através de todas as implementações concretas, pois tudo pode ser abstraído para apenas 3 tipos de entrada.
MAS então eu pensei comigo mesmo e se eu apenas estivesse atrasando o inevitável? E se um dia eu tiver que adicionar outro campo à minha Device
turma? Não suporta algo como um trackball!
Existe uma maneira de eu poder provar essa classe no futuro? Do jeito que eu vejo, eu terminaria com algo assim:
public Device1 : Device
{
//buttons
//trackball
}
public Device2 : Device
{
//Switch
//Axis
}
public Device3 : Device
{
//trackball
//switch
}
E eu teria que continuar adicionando propriedades à minha classe base sempre que houver algo novo para implementar.
fonte
parameter1=value1¶meter2=value2
, etc.Respostas:
Tenho certeza de que isso pode ser feito introduzindo um conceito como um resumo
InputChannel
e dispositivos com uma lista configurável de canais de entrada. Um canal de entrada terá um nome, um tipo, talvez alguns metadados, e precisará ser capaz de produzir algum "estado" que se ajuste a esse tipo. Pode haver canais predefinidos, como um botão, um machado ou um comutador, ou algum novo canal que você não conhece no momento (mas pode ser adicionado posteriormente introduzindo uma novaInputChannel
classe filho).Dessa forma, um dispositivo se tornará algum tipo de metamodelo e você também precisará de uma maneira de gerenciar os estados do dispositivo, que devem corresponder à lista de canais de entrada do dispositivo.
No entanto, esse tipo de abordagem genérica tem um certo risco de superengenharia, também conhecido como efeito da plataforma interna . Por exemplo, pode não ser fácil adicionar funcionalidades específicas a um dispositivo genérico, eventos específicos ou interações entre diferentes canais de entrada. Também pode ser mais difícil de usar e entender para um usuário da sua biblioteca de dispositivos genéricos.
Observe que nem sempre é benéfico criar a solução mais abstrata possível. A alteração dos requisitos de hardware normalmente exige muito mais esforço para ser implementada no próprio hardware do que no software correspondente; portanto, é melhor seguir uma solução mais específica no software e alterá-lo quando necessário.
fonte
InputChannel
pode funcionar, tudo que eu preciso fazer é atualizar seu estado e aumentar umonChangedEvent
. Mas você pode estar certo sobre a engenharia excedente ... Vou manter isso em mente. Você acha que adicionar outro campo a uma classe de vez em quando é aceitável?A idéia por trás do princípio de aberto-fechado é que você tem menos probabilidade de quebrar a funcionalidade existente se implementar nova funcionalidade por herança, em vez de modificar uma classe existente. E você pode fazer isso, herdando do seu Hid. Em um ano e alguns meses, você pode criar um Hid2020 que herda o Hid e adiciona suporte para o trackball que será inventado no quarto trimestre de 2019. Após a invenção e popularização do detector de compressão em 2023, você pode criar uma classe Hid2024 que descende de Hid2019.
Essa seria a abordagem defensiva. Mas também seria um pouco desleixado de uma perspectiva de design limpo. No seu caso, eu não perderia o sono por violar O e apenas mudaria a classe base à medida que o mundo ao seu redor mudasse. Parece que a implementação do trackball ou qualquer outro novo tipo de controle afetará a maneira como você lida com os pressionamentos de botão ou com as alterações de status agora.
fonte