dimanche 22 février 2015

How to disable a class API when the class cannot operate under some conditions?

Say I have the following:



class Processor
{
public:
void Activate();
/* some more interface functions*/
};

void main()
{
Processor().Activate();
}


class Processor is just an example of any class that provides public interface.


Problem


What if class Processor is only operational iff some conditions are met. Just for example, class Processor is preforming some file system operations on a directory X and if the directory 'X` does not exist it can't operate at all.


Issue


Who is responsible to validate the conditions are met and the class is operational?




Let's encapsulate evaluating those conditions to one logic function called Enabled()


Suggestion 1 - Caller responsibility



void main()
{
if (Enabled() )
Processor().Activate();
}


In this case, initiator of class Processor is responsible to make sure these condition are met before initiating the class.


Cons



  1. Caller may not know what are the condition

  2. This doesn't resolve the bigger issue, what if we have other callers that don't verify the condition?




Suggestion 2 - Class responsibility



class Processor
{
public:

Processor()
{
// init m_bIsEnabled based on conditions
}

void Activate()
{
if (!m_bIsEnabled)
return;

// do something
}
/* some more interface functions*/
private:
bool m_bIsEnabled;
};


in this case, all public interface functions are disabled if class is not enabled.


Cons



  1. What if class Processor has numerous interface function, do we check the value of m_bIsEnabled in the beginning of each function?

  2. What if in the future some developer enhance the interface and forgets to check the value of m_bIsEnabled?

  3. What are the default values returned in each functions in case m_bIsEnabled == false




Suggestion 3 - Factory



using Processor_ptr = shared_ptr < Processor > ;

class ProcessorFactory
{
static Processor_ptr create()
{
Processor_ptr p;

p.reset(new Processor);
if (!p->IsEnabled())
p.reset(nullptr);

return p;
}
};


class Processor
{
public:
void Activate();
bool IsEnabled();
friend class ProcessorFactory;
private:
Processor();
bool m_bIsEnabled;
};


This method is so far my favorite since we prevent class generation if it cannot operate.


Cons 1. Perhaps an overkill?




Question


Which of the suggestions is preferable in terms of best practice? do we have other suggestions?


Aucun commentaire:

Enregistrer un commentaire