My boss gave me a project with a particular logic. I have to develop a web page which has to lead the navigator through many cases until he/she arrives at the product.

This is the path scheme of the navigation in the site:

Path Scheme


In the Products page the navigator can choose which filter he wants.

  • If A, he/she MUST go through the B (and then C of course) or C and reach the products.
  • If B, he/she MUST go through the C and reach the products.
  • If C, he/she reaches directly the products.

Of course if I start from A I am following the longest path and when I reach my products I have 3 active filters.

Until now I developed the following code which works fine.

if filter_A
  if filter_B
     .. else ..
    .. else ..
   if filter_B
     .. else ..
     .. else ..

I'm here to ask what would a more expert programmer have done in this situation. I didn't respect the DRY principle, I don't like it and I'd like to know an alternative way to develop this kind of logic.

I thought about splitting every section of code in functions but is it a good idea in this case?

  • possible duplicate of Avoid Code Repetition in Condition Statements
    – gnat
    Commented Mar 6, 2015 at 12:57
  • The control flow diagram shows all control going through filter_C, but the conditional statements indicate that control flow can go around filter_C. Is filter_C optional?
    – CurtisHx
    Commented Mar 6, 2015 at 12:59
  • @CurtisHx Filter C is mandatory. Yes sorry my mistake I made copy-paste. Commented Mar 6, 2015 at 13:18
  • 2
    How can this question be language-agnostic? An idiomatic solution in Java would be very different from an idiomatic solution in Haskell. Have you not decided on a language for your project? Commented Mar 6, 2015 at 23:04

5 Answers 5


You haven't said whether the filters take any parameters. For example, filter_A might be a category filter, so that it's not just a question of "do I need to apply filter_A", it could be "I need to apply filter_A and return all records in with the category field = fooCategory".

The simplest way to implement exactly what you've described (but make sure to read the second half of the answer below) is similar to the other answers, but I wouldn't have any boolean checks at all. I would define interfaces: FilterA, FilterB, FilterC. Then you can have something like (I'm a Java programmer, so this will be Java-esque syntax):

class RequestFilters {
    FilterA filterA;
    FilterB filterB;
    FilterC filterC;

Then you could have something like this (using the enum singleton pattern from Effective Java):

enum NoOpFilterA implements FilterA {

    public List<Item> applyFilter(List<Item> input) {
       return input;

But if you actually want some items to be filtered, you can instead provide an instance of a FilterA implementation that actually does something. Your filtration method will be the very simple

List<Item> filterItems(List<Item> data, RequestFilters filters) {
    List<Item> returnedList = data;
    returnedList = filters.filterA.filter(data);
    returnedList = filters.filterB.filter(data);
    returnedList = filters.filterC.filter(data);
    return returnedList;

But I'm just getting started.

I suspect that the applyFilter call will actually be quite similar for all three types of filters. If that's the case, I wouldn't even do it the way described above. You can get even cleaner code by only having one interface, then doing this:

class ChainedFilter implements Filter {
     List<Filter> filterList;

     void addFilter(Filter filter) {

     List<Item> applyFilter(List<Item> input) {
         List<Item> returnedList = input;
         for(Filter f : filterList) {
             returnedList = f.applyFilter(returnedList);
         return returnedList;

Then, as your user navigates through the pages, you just add a new instance of whatever filter you need when appropriate. This will allow you to be able to apply multiple instances of the same filter with different arguments should you need that behavior in the future, and also add additional filters in the future without having to change your design.

Additionally, you can add either something like the NoOpFilter above or you can just not add a particular filter at all to the list, whatever is easier for your code.

  • Thank you, because you find the simplest way possible to change logic without change the code as well. This makes your answer the best. I'll implement this code design ASAP Commented Mar 6, 2015 at 15:36
  • If you had your Filter as a Predicate then you could use it directly in the Stream API. Many languages have similar functional constructs. Commented Mar 6, 2015 at 16:38
  • 3
    @BoristheSpider That's only if he's using Java 8; he didn't even say what language he was using. Other languages do have such a construct but I didn't want to go into all the different flavors of how to do that
    – durron597
    Commented Mar 6, 2015 at 16:40
  • 3
    Understood - it's just worth mentioning that that is an avenue to explore if the OP wants to provide the cleanest possible implementation. You certainly have my +1 for an already excellent answer. Commented Mar 6, 2015 at 16:41

In this case, it is important to separate the logic of filtering, and the control flow of how the filters run. The filter logic should be separated out into individual functions, that can run independent of each other.


In the sample code posted, there's 3 booleans filter_A, filter_B, and filter_C. However, from the diagram, filter_C always runs, so that can be changed to an unconditional.

NOTE: I am assuming that the control flow diagram is correct. There is a discrepancy between the posted sample code and the control flow diagram.

A separate piece of code controls which filters get run

ApplyFilters(bool filter_A, bool filter_B)
    listOfProducts tmp;
    if (filter_A)
    if (filter_B)

There is a distinct separation between controlling which filters run, and what the filters do. Break those two pieces of logic apart.

  • +1 This seems a lot simpler and decoupled than the accepted answer.
    – winkbrace
    Commented Mar 12, 2015 at 20:01

I assume, that you want the simplest, clearest algorithm.
In this case, knowing that filter c is always applied, I would live it out of the if logic and apply it at the end regardless. As it looks in your flowchart, each filter before the c, is optional, because each of them can either be applied, or not. In this case, I would live ifs separate from each filter, without nesting and chaining:

if filter_a

if filter_b


if you have a flowchart with a variable number of filters, before the mandatory one, I would, instead, save all the filters to an array, in an order that they should appear. Then process optional filters in the loop and apply the mandatory one at the end, outside of the loop:

optional_filters_array = (a, b, c, d, e, f, g, h, etc)

for current_filter in optional_filters_array



optional_filters_array = (a, b, c, d, e, f, g, h, etc)
required_filter = last_filter

for current_filter in optional_filters_array


of cource, you would have to define the filter processing subroutine.


I'm going to assume filterA, filterB, and filterC actually modify the list of products. Otherwise, if they are just if-checks, then filterA and filterB can be ignored since all paths lead ultimately to filterC. Your description of the requirement seems to imply that each filter will reduce product list.

So assuming the filters actually reduce the list of products, here's bit of pseudo-code...

class filter
    func check(item) returns boolean

func applyFilter(filter, productList) returns list
    newList is list
    foreach item in productList
        if filter.check(item) then
            add item to newList
    return newList

filterA, filterB, filterC = subclasses of filter for each condition, chosen by the user
products = list of items to be filtered

if filterA then
    products = applyFilter(filterA, products)

if filterB then
    products = applyFilter(filterB, products)

if filterC then
    products = applyFilter(filterC, products)

# use products...

In your requirements, filterC is not automatically applied, but in the diagram, it is. If the requirement is that at least filterC should be applied no matter what, then you would call applyFilter(filterC, products) without checking if filterC is chosen.

filterC = instance of filter, always chosen


# if filterC then
products = applyFilter(filterC, products)
# endif

I wonder if modeling your filters to be some kind of objects in a graph would make sense. At least that's what I think of when seeing the diagram.

If you model the dependency of the filters like a object graph, then the code that handles the possible flow paths is pretty much straight forward without any hairy logic. Also, the graph (business logic) can change, while the code that interprets the graph stays the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.