What is the proper way to encapsulate such functionality?

For example, I have a function that basically works like this:

function myfunc(data,type_of_analysis){
    if type_of_analysis is "Smith-Jones Method" 
          return smith_jones(data)
    else if type_of_analysis is "Pineapple-Mango Method"
          return pineapple_mango(data)
}

      

The names are, of course, made up, and imagine there are several more types of analysis than that. What would be the correct way to restructure myfunc ()? Is there a better / more standard way for people to pass arguments to determine what analysis they want to perform? Or is this something the user will have to find in the documentation?

+3


source to share


1 answer


Here's an example in C ++ that uses a map between enum values ​​and function objects to create a safe and flexible dispatch structure:

//dummy analysis functions
void smithJonesAnalysis (int data){cout << "Smith";}
void pineappleMangoAnalysis (int data){cout << "Pineapple";}

class Analyzer
{
    //different analysis methods
    enum class AnalysisMethod {SmithJones, PineappleMango};
    //a map from analysis method to a function object
    std::map<AnalysisMethod, std::function<void(int)>> m_analysis_map;

    AnalysisMethod stringToMethod (std::string method)
    {
        //some basic string canonicalisation
        std::transform(method.begin(), method.end(), method.begin(), ::tolower);
        if (method == "smith-jones method")
            return AnalysisMethod::SmithJones;
        if (method == "pineapple-mango method")
            return AnalysisMethod::PineappleMango;

        throw std::runtime_error("Invalid analysis method");
    }
public:
    Analyzer()
    {
        //register all the different functions here
        m_analysis_map[AnalysisMethod::SmithJones] = smithJonesAnalysis;
        m_analysis_map[AnalysisMethod::PineappleMango] = pineappleMangoAnalysis;
    }

    //dispatcher function
    void operator() (std::string method, int data)
    {
        AnalysisMethod am = stringToMethod(method);
        m_analysis_map[am](data);
    }
};

      

Used like this:

Analyzer a;
a("Smith-Jones Method", 0);
a("Pineapple-Mango Method", 0);

      



Demo

This has several advantages over simple switch statements:

  • Easier to add / remove analysis methods.
  • It's easier to change the data type that methods accept.
  • You can have different Analyzer

    for different areas, template and specialized, and all you need to change is the registration method.
  • You can enable / disable analysis methods at runtime very clearly.
+1


source







All Articles