2

The company I work for follows a business model where a core product exists (originally written in C, now in C++) with some default implementation but details are tailor-made for each customer (there are cca. 10-20 of them). What's the best programming approach in such a scenario? Is there a good design pattern/methodology/paradigm/whatever out there that makes code reuse and maintenance optimal? (Versioning is just as much a headache, maybe it will be another SO question later).

Example: the system provides a service implemented as a function:

int doServiceA(const string & params);

A common dispatcher routine calls this function:

void dispatch(const string & cmd, const string & params)
{
    int ret = 0;
    if (cmd == "serviceA") {
        ret = doServiceA(params);
    }
    //...
}

In our earliest approach the implementation of doServiceA was littered with #ifdef's to handle customers' unique requirements.

After a couple of years we switched to using virtual functions:

Core module:

class ServiceA
{
    virtual int execute(const string & params); // with default implementation
};

ServiceA & getServiceA(); // factory method declaration

void dispatch(const string & cmd, const string & params)
{
    int ret = 0;
    if (cmd == "serviceA") {
        ret = getServiceA().execute(params);
    }
    //...
}

Extension for customer XXX:

class XXXServiceA : public ServiceA
{
    virtual int execute(const string & params); // implementation containing XXX-specific parts
};

ServiceA & getServiceA() // factory method implementation
{
    static XXXServiceA s;
    return s;
}

Extension for customer YYY:

class YYYServiceA : public ServiceA
{
    virtual int execute(const string & params); // implementation containing YYY-specific parts
};

ServiceA & getServiceA() // factory method implementation
{
    static YYYServiceA s;
    return s;
}

So far we've been OK with this technique, but I have some concerns:

  1. How do I differentiate from the default implementation when a customer requests a tiny change in the middle of my service? I guess I should break up ServiceA::execute() to pieces as small as possible and make them all virtual (as I really can't foresee which parts are going to be customized later)?

  2. Creating an object with no state feels like I'm violating the concept of OOP for techincal reasons.

  3. Sometimes a change makes sense for multiple customers which results in either code duplication (XXXServiceA and YYYServiceA with partially same implementations) or complex inheritance hierarchies (when adding a class between ServiceA and its descendants to accommodate common code).

  4. Just a feeling that virtuals may not be the right tool here as it's a means to achieve runtime polymorphism whereas what I need is compile-time polymorphism (no XXXServiceA and YYYServiceA objects will exist in the same binary).

I experimented with a lot of things I read about (policies, mixins, CRTP) but so far I failed to improve much on the above design. I am wondering if I am missing something really simple here?

migrated from stackoverflow.com May 10 '16 at 16:10

This question came from our site for professional and enthusiast programmers.

  • 2
    While you wait the question to be moved why do no you take a look at the delegation pattern – Marco May 10 '16 at 16:00
  • I have used delegation to good effect. However, its unpleasant side-effects (heap allocation, lifetime management) make me think it's not the ideal solution. In my understanding policies are a superior alternative, assuming type information is available compile time. But this may not be true as my experiences with policies are very limited. – peti May 17 '16 at 15:53
0

1.Tiny changes

There's no magic available for this aspect:

  • either you can define the execution as a set of more primitive virtual functions that you can override for tailoring purpose;
  • or you can use a policy based design using to obtain the same effect, but at compile time (but with similar structural issues as above)
  • or you could consider feature toggles
  • or you have to duplicate and maintain redundant code.

2.Stateless objects

This is a dogmatic question that will not bring you closer to any solution. I can ensure you that your bad feelings won't affect the accuracy of your code.

3.Common changes for multiple customers

Sharing common code parts for multiple customers is something that is a good candidate for refactoring the code with some template based policy design.

4.runtime vs. compile-time

As your problems seems to relate to customer specific variations, and you compile the code per customers, compile-time approach seems indeed to be more adapted. Use templates: the client specific classes would become a template argument.

template <class SerA> 
ServiceA & getServiceA() // factory method implementation
{
    static SerA s;
    return s;
}   

For the creation of the objects you could very well use an abstract factory base on templates, at compile time.

  • Though I have yet to put your suggestions into practice regarding policies (which will take some time), I think you summed up the options quite well. The essence of my question is indeed the right approach to the problem of having customer specific variations. I am interested if anyone else is willing to add to the above. – peti May 17 '16 at 15:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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