Search code examples
c#.netsql-serverwebapiinfrastructure

A better architecture then if(something) DoIt() else Dont()


I'm trying to create a mechanism that will allow the application to decide (in runtime) whether to execute some functionality.

"Some Functionality" can be anything, it can be C# code which is contained in several classes in several DLLs, it can be UI, it can be database query execution, etc.

Most importantly, it should fit in the current existing infrastructure I have, which I cannot re-design and build from scratch.

The more I think of it, it seems like the only solution I can use would be to hold some table which will be the "functionality repository" and it will tell (by unique key) if a functionality is on / off.

Then in code, I will have to place in each spot which handles such functionality an if else statement.

E.g.

If(functionalityEnabled)?
DoFunctionality()
Else
DoTheUsusal()

Is there a better way or a better design to implement it? I would like to keep the solution as simple as possible, but on the other hand, this solution is really ugly and will eventually make my code looks like spaghetti code.

Your thoughts will be appreciated, I'm using C# with SQL server, web API for web services.

Edit:

I want to say that I appreciate the time and effort of everyone answering my question, there were some really interesting ideas that you brought up. I eventually marked @dasblinkenlight answer since it suited by need the best, though other answers here are really good and may be useful to others.


Solution

  • A once-popular quip among OO programmers has been that every conditional in the code indicate a missed opportunity to subclass. Although this rule is far from being universal, and it falls short when it comes to composition, there is a grain of truth to it, especially when you see the same condition popping up in multiple ifs across different methods of the same class.

    A common way of dealing with ifs like that is using some combination of inheritance and composition, and moving the decision to a single place where your object is being created.

    The inheritance way looks like this:

    interface Doer {
        void doSomething();
    }
    class BasicDoer implements Doer {
        public void doSomething() {
            ...
        }
    }
    class EnhancedDoer extends BasicDoer {
        public void doSomething() {
            base.doSomething();
            ...
        }
    }
    
    // At construction time:
    
    Doer doer;
    if (someCondition)
        doer = new BasicDoer();
    else
        doer = new EnhancedDoer();
    

    The composition way looks like this:

    interface Doer {
        void doSomething();
    }
    // Create several implementations of Activity, then...
    
    // At construction time:
    List<Doer> doers = new ArrayList<>();
    if (someCondition1)
        doers.add(new SomeKindOfDoer());
    if (someCondition2)
        doers.add(new AnotherKindOfDoer());
    if (someCondition3)
        doers.add(new YetAnotherKindOfDoer());
    

    Now instead of an if you do this:

    for (Doer d : doers) {
        d.doSomething();
    }