Meu chefe me deu um projeto com uma lógica específica. Eu tenho que desenvolver uma página da web que deve liderar o navegador em muitos casos até que ele chegue ao produto.
Este é o esquema de caminho da navegação no site:
IMPORTANTE!
Na página Produtos, o navegador pode escolher qual filtro ele deseja.
- Se A, ele / ela DEVE passar pelo B (e depois C, é claro) ou C e alcançar os produtos.
- Se B, ele / ela DEVE passar pelo C e alcançar os produtos.
- Se C, ele / ela alcança diretamente os produtos.
Obviamente, se eu começar da IA, estou seguindo o caminho mais longo e, quando chego aos meus produtos, tenho 3 filtros ativos.
Até agora desenvolvi o seguinte código, que funciona bem.
if filter_A
if filter_B
filter_C()
.. else ..
else
filter_C
.. else ..
else
if filter_B
filter_C()
.. else ..
else
filter_C()
.. else ..
Estou aqui para perguntar o que um programador mais experiente teria feito nessa situação. Não respeitei o princípio DRY, não gosto e gostaria de conhecer uma maneira alternativa de desenvolver esse tipo de lógica.
Pensei em dividir cada seção do código em funções, mas é uma boa idéia neste caso?
fonte
filter_C
, mas as instruções condicionais indicam que o fluxo de controle pode ser contornadofilter_C
. Éfilter_C
opcional?Respostas:
Você não disse se os filtros têm algum parâmetro. Por exemplo,
filter_A
pode ser um filtro de categoria, para que não seja apenas uma questão de "preciso aplicarfilter_A
", mas sim "preciso aplicarfilter_A
e retornar todos os registros com o campo de categoria =fooCategory
".A maneira mais simples de implementar exatamente o que você descreveu (mas não deixe de ler a segunda metade da resposta abaixo) é semelhante às outras respostas, mas eu não teria nenhuma verificação booleana. Gostaria de definir interfaces:
FilterA, FilterB, FilterC
. Então você pode ter algo como (eu sou um programador Java, então essa será a sintaxe em estilo Java):Então você pode ter algo parecido com isto (usando o padrão enum singleton do Effective Java ):
Mas se você realmente deseja filtrar alguns itens, pode fornecer uma instância de uma
FilterA
implementação que realmente faz alguma coisa. O seu método de filtragem será muito simplesMas estou apenas começando.
Suspeito que a
applyFilter
chamada seja realmente semelhante para todos os três tipos de filtros. Se for esse o caso, eu nem faria da maneira descrita acima. Você pode obter um código ainda mais limpo, tendo apenas uma interface e fazendo o seguinte:Em seguida, à medida que o usuário navega pelas páginas, basta adicionar uma nova instância de qualquer filtro necessário, quando apropriado. Isso permitirá que você possa aplicar várias instâncias do mesmo filtro com argumentos diferentes, caso precise desse comportamento no futuro, além de adicionar filtros adicionais no futuro sem precisar alterar seu design .
Além disso, você pode adicionar algo como o
NoOpFilter
descrito acima ou simplesmente não pode adicionar um filtro específico à lista, o que for mais fácil para o seu código.fonte
Filter
como,Predicate
então você pode usá-lo diretamente naStream
API. Muitos idiomas têm construções funcionais semelhantes.Nesse caso, é importante separar a lógica da filtragem e o fluxo de controle de como os filtros são executados. A lógica do filtro deve ser separada em funções individuais, que podem funcionar independentemente uma da outra.
No código de exemplo postado, há 3 booleans
filter_A
,filter_B
efilter_C
. No entanto, no diagrama,filter_C
sempre é executado, para que possa ser alterado para um incondicional.NOTA: Estou assumindo que o diagrama de fluxo de controle está correto. Há uma discrepância entre o código de amostra publicado e o diagrama de fluxo de controle.
Um trecho de código separado controla quais filtros são executados
Há uma separação distinta entre o controle de quais filtros são executados e o que os filtros fazem. Quebre esses dois pedaços de lógica.
fonte
Suponho que você deseja o algoritmo mais simples e claro.
Nesse caso, sabendo que o filtro c é sempre aplicado, eu o tiraria da lógica if e o aplicaria no final independentemente. Como parece em seu fluxograma, cada filtro antes de c é opcional, porque cada um deles pode ser aplicado ou não. Nesse caso, eu viveria ifs separados de cada filtro, sem aninhamento e encadeamento:
se você tiver um fluxograma com um número variável de filtros, antes do obrigatório, eu salvaria todos os filtros em uma matriz, na ordem em que eles deveriam aparecer. Em seguida, processe filtros opcionais no loop e aplique o obrigatório no final, fora do loop:
ou:
Por exemplo, você teria que definir a sub-rotina de processamento do filtro.
fonte
Vou assumir que filterA, filterB e filterC realmente modificam a lista de produtos. Caso contrário, se forem apenas verificações de if, o filterA e o filterB poderão ser ignorados, pois todos os caminhos levam ao filterC. Sua descrição do requisito parece implicar que cada filtro reduzirá a lista de produtos.
Supondo que os filtros realmente reduzam a lista de produtos, aqui está um pouco de pseudo-código ...
Nos seus requisitos, o filterC não é aplicado automaticamente, mas no diagrama, é. Se o requisito é que pelo menos filterC deva ser aplicado independentemente do que seja, você chamaria applyFilter (filterC, products) sem verificar se o filterC é escolhido.
fonte
Gostaria de saber se a modelagem de seus filtros para ser algum tipo de objeto em um gráfico faria sentido. Pelo menos é o que penso quando vejo o diagrama.
Se você modelar a dependência dos filtros como um gráfico de objeto, o código que lida com os possíveis caminhos de fluxo é bastante simples, sem lógica lógica. Além disso, o gráfico (lógica de negócios) pode mudar, enquanto o código que interpreta o gráfico permanece o mesmo.
fonte