Ok, eu sei que o título desta pergunta é quase idêntico a Quando devo usar a programação baseada em eventos? mas as respostas dessa pergunta não me ajudaram a decidir se devo usar eventos no caso específico que estou enfrentando.
Estou desenvolvendo um pequeno aplicativo. É um aplicativo simples e, na maioria das vezes, sua funcionalidade é CRUD básica.
Após certos eventos (ao modificar certos dados), o aplicativo deve gravar uma cópia local dos dados em um arquivo. Não tenho certeza sobre qual é a melhor maneira de implementar isso. Eu posso:
- Acione eventos quando os dados são modificados e vincule uma resposta (gere o arquivo) a esses eventos. Como alternativa, implemente o padrão observador. Parece complexidade desnecessária.
- Chame o código de geração de arquivo diretamente do código que modifica os dados. Muito mais simples, mas parece errado que a dependência seja assim, ou seja, parece errado que a funcionalidade principal do aplicativo (código que modifica os dados) seja acoplada a esse benefício extra (código que gera um arquivo de backup). Eu sei, no entanto, que este aplicativo não evoluirá para um ponto em que esse acoplamento represente um problema.
Qual é a melhor abordagem neste caso?
Respostas:
Siga o princípio do KISS: Mantenha-o simples, estúpido ou o princípio do YAGNI: você não precisará dele.
Você pode escrever o código como:
Ou você pode escrever um código como:
Na ausência de um motivo convincente para fazer o contrário, siga a rota mais simples. Técnicas como a manipulação de eventos são poderosas, mas aumentam a complexidade do seu código. Requer mais código para funcionar e dificulta o que acontece no seu código.
Os eventos são muito críticos na situação certa (imagine tentar fazer a programação da interface do usuário sem eventos!) Mas não os use quando puder usar o KISS ou o YAGNI.
fonte
O exemplo que você descreve de dados simples, nos quais a modificação aciona algum efeito, pode ser perfeitamente implementado com o padrão de design do observador :
A abordagem orientada a eventos vale a pena investir em cenários mais complexos, quando muitas interações diferentes podem ocorrer, em um contexto muitos-para-muitos, ou se são previstas reações em cadeia (por exemplo, um sujeito informa um observador, que em alguns casos deseja modificar o assunto ou outros assuntos)
fonte
Como você diz, os eventos são uma ótima ferramenta para reduzir o acoplamento entre classes; portanto, embora possa envolver a criação de código adicional em alguns idiomas sem suporte interno para eventos, reduz a complexidade da imagem geral.
Os eventos são sem dúvida uma das ferramentas mais importantes no OO (de acordo com Alan Kay - os objetos se comunicam enviando e recebendo mensagens ). Se você usa um idioma que possui suporte interno para eventos ou trata funções como cidadãos de primeira classe, usá-los não é fácil.
Mesmo em idiomas sem suporte interno, a quantidade de clichê para algo como o padrão Observer é bastante mínima. Você pode encontrar uma biblioteca de eventos genéricos decente em algum lugar que possa ser usado em todos os seus aplicativos para minimizar o clichê. (Um agregador de eventos genérico ou mediador de eventos é útil em quase qualquer tipo de aplicativo).
Vale a pena em um aplicativo pequeno? Eu diria que sim definitivamente .
Se você está pensando "Ah, mas é realmente apenas um aplicativo muito pequeno, isso não importa muito" , considere:
Em geral, o tamanho de um aplicativo não deve ser um fator decisivo para manter as classes fracamente acopladas; Os princípios do SOLID não são apenas para grandes aplicativos, são aplicáveis a software e bases de código em qualquer escala.
De fato, o tempo economizado no teste unitário de suas classes de acoplamento fraco isoladamente deve contrabalançar qualquer tempo adicional gasto na dissociação dessas classes.
fonte
O padrão de observador pode ser implementado de uma maneira muito menor do que o artigo da Wikipedia (ou o livro do GOF) o descreve, desde que suas linguagens de programação suportem algo como "retornos de chamada" ou "delegados". Basta passar um método de retorno de chamada para o seu código CRUD (o método observador, que pode ser um método genérico de "gravar em arquivo" ou um método vazio). Em vez de "acionamento de evento", basta chamar esse retorno de chamada.
O código resultante será apenas minimamente mais complexo do que chamar o código de geração de arquivo diretamente, mas sem as desvantagens do acoplamento rígido de componentes não relacionados.
Isso trará a você o "melhor dos dois mundos", sem sacrificar a dissociação de "YAGNI".
fonte