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
- Caller may not know what are the condition
- 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
- What if class
Processorhas numerous interface function, do we check the value ofm_bIsEnabledin the beginning of each function? - What if in the future some developer enhance the interface and forgets to check the value of
m_bIsEnabled? - 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