Em nosso aplicativo Rails, estamos adicionando notificações. Alguns deles são blocking
: Eles interrompem o progresso de qualquer recurso em que foram adicionados, porque faltam algumas informações sobre esse recurso.
Outras notificações são simples e fornecem apenas informações.
Hoje tive uma discussão com outro programador de nossa equipe. Eu criei a estrutura de herança como esta:
Ele, no entanto, prefere que eu adicione blocking
como método de retorno booleano em cada Notificação e especifique uma lista de subclasses que estão bloqueando dentro da classe pai da Notificação.
A diferença entre essas abordagens não é muito grande; na minha abordagem, não é necessário especificar essa lista, mantendo a classe raiz mais limpa. Por outro lado, a lógica especial que acontece Notification::Blocking
agora também não é muito grande.
Que tipo de abstração é mais adequado para esse problema?
Respostas:
Você deseja evitar que as classes base conheçam as classes derivadas. Ele apresenta acoplamento rígido e é uma dor de cabeça para manutenção, porque você deve se lembrar de adicionar à lista sempre que criar uma nova classe derivada.
Também impedirá que você seja capaz de colocar a classe Notification em um pacote / conjunto reutilizável, se você quiser usar essa classe em vários projetos.
Se você realmente deseja usar uma única classe base, outra maneira de resolver isso é adicionar uma propriedade virtual ou método IsBlocking na classe base Notification. Classes derivadas podem então substituir isso para retornar verdadeiro ou falso. Você teria uma solução de classe única sem a classe base sabendo sobre classes derivadas.
fonte
Isso parece muito peculiar e é um cheiro de código específico.
Eu forneceria subclasses se você tiver diferenças de comportamento entre as classes e quiser tratar todas essas notificações da mesma maneira (por exemplo, usando polimorfismo ).
fonte
Como uma conversa com as respostas existentes, sugiro que a propriedade booleana seja a melhor opção se for necessário alterar dinamicamente o modo a ser usado (por exemplo, através de um arquivo de configuração que fornece uma lista de quais tipos devem ser bloqueados). e que não são).
Dito isto, um design melhor, mesmo nessa situação, pode ser o uso de um objeto Decorator.
fonte
Eu diria que depende de quanto mais é especial sobre uma notificação de bloqueio, embora meu primeiro pensamento seja o de "ambos":
Dessa forma, você pode usar
n.Blocking
orn is BlockingNotification
(all in pseudo-code), embora, se você permitir que uma classe implemente umBlocking
valor sensível ao contexto , visto que você precisará verificar esse valor toda vez que aBlockingNotification
classe se tornar menos útil.De qualquer forma, concordo com as outras respostas das quais você não deseja que a implementação da classe base
Blocking
precise saber sobre as classes derivadas.fonte
Em vez de criar duas classes base e várias instâncias de cada uma, faça uma classe de notificação com um booleano para indicar se a notificação está bloqueando e qualquer outra informação necessária para comunicar a notificação ao usuário.
Isso permite que você use um conjunto de códigos para processar e apresentar notificações e reduz a complexidade do seu código.
fonte