Мой босс дал мне проект с особой логикой. Я должен разработать веб-страницу, которая должна вести навигатор по многим случаям, пока он не достигнет продукта.
Вот схема пути навигации по сайту:
ВАЖНЫЙ!
На странице Продукты навигатор может выбрать, какой фильтр он хочет.
- Если A, он / она ДОЛЖЕН пройти через B (и, конечно, C) или C и добраться до продуктов.
- Если B, он / она ДОЛЖЕН пройти через C и добраться до продуктов.
- Если C, он / она достигает непосредственно продуктов.
Конечно, если я начинаю с ИИ, я иду по самому длинному пути, и когда я достигаю своих продуктов, у меня есть 3 активных фильтра.
До сих пор я разработал следующий код, который отлично работает.
if filter_A
if filter_B
filter_C()
.. else ..
else
filter_C
.. else ..
else
if filter_B
filter_C()
.. else ..
else
filter_C()
.. else ..
Я здесь, чтобы спросить, что бы сделал более опытный программист в этой ситуации. Я не уважал принцип СУХОЙ, мне это не нравится, и я хотел бы знать альтернативный способ разработки такой логики.
Я думал о разделении каждого раздела кода в функциях, но это хорошая идея в этом случае?
design
design-patterns
language-agnostic
conditions
if-statement
Кевин Читтадини
источник
источник
filter_C
, но условные операторы указывают, что поток управления может проходитьfilter_C
. Являетсяfilter_C
необязательным?Ответы:
Вы не сказали, принимают ли фильтры какие-либо параметры. Например, это
filter_A
может быть фильтр категорий, так что это не просто вопрос «нужно ли мне применятьfilter_A
», это может быть «мне нужно применитьfilter_A
и вернуть все записи с полем категории =fooCategory
».Самый простой способ реализовать именно то, что вы описали (но обязательно прочитайте вторую половину ответа ниже) , похож на другие ответы, но у меня не будет никаких булевых проверок вообще. Я хотел бы определить интерфейсы:
FilterA, FilterB, FilterC
. Тогда у вас может быть что-то вроде (я программист на Java, так что это будет синтаксис Java-esque):Тогда вы можете получить что-то вроде этого (используя шаблон enum singleton из Effective Java ):
Но если вы действительно хотите, чтобы некоторые элементы были отфильтрованы, вы можете вместо этого предоставить экземпляр
FilterA
реализации, который действительно что-то делает. Ваш метод фильтрации будет очень простымНо я только начинаю.
Я подозреваю, что
applyFilter
вызов на самом деле будет очень похожим для всех трех типов фильтров. Если это так, я бы даже не сделал это так, как описано выше. Вы можете получить более чистый код, имея только один интерфейс, а затем сделайте следующее:Затем, когда ваш пользователь перемещается по страницам, вы просто добавляете новый экземпляр того фильтра, который вам необходим, когда это необходимо. Это позволит вам иметь возможность применять несколько экземпляров одного и того же фильтра с разными аргументами, если вам понадобится такое поведение в будущем, а также добавлять дополнительные фильтры в будущем, не меняя дизайн .
Кроме того, вы можете добавить что-то подобное
NoOpFilter
вышеописанному или просто не добавлять какой-либо конкретный фильтр в список, что проще для вашего кода.источник
Filter
как,Predicate
то вы можете использовать его непосредственно вStream
API. Многие языки имеют похожие функциональные конструкции.В этом случае важно разделить логику фильтрации и поток управления работой фильтров. Логика фильтра должна быть разделена на отдельные функции, которые могут работать независимо друг от друга.
В примере кода в курсе, что есть 3 булевы
filter_A
,filter_B
иfilter_C
. Тем не менее, из диаграммыfilter_C
всегда выполняется, так что может быть изменен на безусловный.ПРИМЕЧАНИЕ. Я предполагаю, что диаграмма потока управления правильная. Существует несоответствие между размещенным образцом кода и блок-схемой управления.
Отдельная часть кода контролирует, какие фильтры запускаются
Существует четкое разделение между контролем того, какие фильтры работают, и что делают фильтры. Разбейте эти две части логики на части.
источник
Я предполагаю, что вы хотите самый простой, понятный алгоритм.
В этом случае, зная, что фильтр c всегда применяется, я бы использовал его в логике if и применил бы его в конце независимо. Как видно на вашей потоковой диаграмме, каждый фильтр до c необязателен, потому что каждый из них может быть применен или нет. В этом случае я бы жил, если бы отдельно от каждого фильтра, без вложенности и цепочки:
если у вас есть блок-схема с переменным числом фильтров, перед обязательным я бы вместо этого сохранил все фильтры в массив в порядке их появления. Затем обработайте необязательные фильтры в цикле и примените обязательный в конце вне цикла:
или:
Конечно, вы должны определить подпрограмму обработки фильтра.
источник
Я собираюсь предположить, что filterA, filterB и filterC действительно изменяют список продуктов. В противном случае, если они просто проверки if, то filterA и filterB можно игнорировать, поскольку все пути в конечном итоге ведут к filterC. Ваше описание требования подразумевает, что каждый фильтр будет сокращать список товаров.
Если предположить, что фильтры на самом деле сокращают список продуктов, вот немного псевдокода ...
В ваших требованиях filterC не применяется автоматически, но на диаграмме это так. Если требуется, чтобы по крайней мере что-то применялось filterC, то вы бы вызвали applyFilter (filterC, products), не проверяя, выбран ли filterC.
источник
Интересно, имеет ли смысл моделировать ваши фильтры в виде объектов на графике. По крайней мере, это то, о чем я думаю, когда вижу диаграмму.
Если вы моделируете зависимость фильтров как граф объектов, то код, который обрабатывает возможные пути потока, в значительной степени прост без какой-либо сложной логики. Кроме того, график (бизнес-логика) может измениться, в то время как код, который интерпретирует график, остается неизменным.
источник