design criticism
class BigClass
{
....
protected:
void
_FindLayoutToSet(CApplicationContextManager::EApplicationContext/
*resolve_state_param*/ i_param );
void _SetLayout(MLayoutManager::ELayoutType/*state*/ i_param );
};
void
BigClass::_FindLayoutToSet(CApplicationContextManager::EApplicationContext
i_param )
{
MLayoutManager::ELayoutType state_to_set;
switch(i_param)
{
case 0:
{
A a;
a.DoSmth();
bool a_ret = a.GetSmth();
B b;
bool b_ret = b.DoSmth();
if (a && b)
{
state_to_set = some_state;
}
else
{
state_to_set = another_state;
}
break;
}
case 1:
... //the same complex logic
break;
default:
break;
}
_SetLayout(state_to_set);
}
I decided to redesign it into smth like this :
class BigClass //more 15000 lines in cpp
{
....
public:
typedef boost::function<MLayoutManager::ELayoutType (void)>
get_layout_func;
typedef boost::shared_ptr<get_layout_func> p_get_layout_func;
void
SetLayoutFuncToContextPredicate(boost::shared_ptr<IContextToLayoutPred>
i_pred);
boost::shared_ptr<IContextToLayoutPred>
GetLayoutFuncToContextPredicate() const;
void
SetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin,
p_get_layout_func ip_get_layout_type_from_context);
bool
RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin);
p_get_layout_func
GetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin) const;
protected:
void _FindApplicationStateToSet(int i_param );
void _SetApplicationState(state i_param );
private:
struct CSCDocImpl;
std::auto_ptr<CSCDocImpl> mp_impl;
};
class DefaultContextToLayoutPred:public IContextToLayoutPred
{
public:
DefaultContextToLayoutPred():m_layout_type(MLayoutManager::LAYOUT_UNKNOWN)
{};
virtual MLayoutManager::ELayoutType GetLayoutType() const
{
return m_layout_type;
}
bool Compare(CSCDoc::p_get_layout_func i_func) const // bad
method name. means get result of function ,
// change
internal predicate state and return,
// if got
enough information
{
const MLayoutManager::ELayoutType layout_type = (*i_func)();
if (layout_type != m_layout_type)
{
m_layout_type = layout_type;
return true;
}
return false;
}
virtual void Reset()
{
m_layout_type = MLayoutManager::LAYOUT_UNKNOWN;
}
private:
mutable MLayoutManager::ELayoutType m_layout_type;
};
//-----------------------------------------------------------------------------
struct CSCDoc::CSCDocImpl
{
ContextToLayout m_context_to_layout;
boost::shared_ptr<IContextToLayoutPred> mp_layout_to_contex_pred;
MLayoutManager::ELayoutType
GetLayoutType(CApplicationContextManager::EApplicationContext
i_context) const;
bool
RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context, const std::string_t & i_name_origin);
};
//-----------------------------------------------------------------------------
MLayoutManager::ELayoutType
CSCDoc::CSCDocImpl::GetLayoutType(CApplicationContextManager::EApplicationContext
i_context) const
{
if (false == mp_layout_to_contex_pred)
{
return MLayoutManager::LAYOUT_UNKNOWN;
}
return m_context_to_layout.GetLayoutType(i_context,
mp_layout_to_contex_pred);
}
//-----------------------------------------------------------------------------
bool
CSCDoc::CSCDocImpl::RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context, const std::string_t & i_name_origin)
{
bool ret =
m_context_to_layout.RemoveLayoutFuncToContext(i_context,
i_name_origin);
return ret;
}
//------------------------------------------------------------------------------------
void
CSCDoc::SetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin,
p_get_layout_func ip_get_layout_type_from_context)
{
mp_impl->m_context_to_layout.SetLayoutFuncToContext(i_context,
i_name_origin, ip_get_layout_type_from_context);
}
//------------------------------------------------------------------------------------
bool
CSCDoc::RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin)
{
return mp_impl->RemoveLayoutFuncToContext(i_context,
i_name_origin);
}
//------------------------------------------------------------------------------------
CSCDoc::p_get_layout_func
CSCDoc::GetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin) const
{
return mp_impl-
m_context_to_layout.GetLayoutFuncToContext(i_context, i_name_origin);
}
//------------------------------------------------------------------------------------
void
CSCDoc::SetLayoutFuncToContextPredicate(boost::shared_ptr<IContextToLayoutPred>
i_pred)
{
mp_impl->mp_layout_to_contex_pred = i_pred;
}
//------------------------------------------------------------------------------------
boost::shared_ptr<IContextToLayoutPred>
CSCDoc::GetLayoutFuncToContextPredicate() const
{
return mp_impl->mp_layout_to_contex_pred;
}
/*-------------------ContextToLayout + IContextToLayoutPred
---------------------------------------*/
#pragma once
#include <boost/function.hpp>
#include "MLayoutManager.h"
class IContextToLayoutPred
{
public:
virtual ~IContextToLayoutPred(){};
virtual void Reset(){};
virtual MLayoutManager::ELayoutType GetLayoutType() const
{return MLayoutManager::LAYOUT_UNKNOWN;};
virtual bool Compare(CSCDoc::p_get_layout_func i_func) const
{ return false;};
bool operator()(const CSCDoc::p_get_layout_func & i_func)
{
return Compare(i_func);
}
};
//-----------------------------------------------------------------------------
class ContextToLayout
{
public:
typedef boost::function<MLayoutManager::ELayoutType (void)>
get_layout_func;
typedef boost::shared_ptr<get_layout_func> p_get_layout_func;
private:
typedef std::map<std::string_t, p_get_layout_func >
get_layout_func_map;
typedef
std::map<CApplicationContextManager::EApplicationContext,
get_layout_func_map > context_to_layout;
public:
MLayoutManager::ELayoutType
GetLayoutType(CApplicationContextManager::EApplicationContext
i_context,
boost::shared_ptr<IContextToLayoutPred> ip_pred) const;
p_get_layout_func
GetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin) const;
void
SetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin,
p_get_layout_func i_get_layout_type_from_context);
bool
RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin);
private:
context_to_layout m_context_to_layout;
};
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "ContextToLayout.h"
#include "ApplicationContextManager.h"
#include <boost/bind.hpp>
//-----------------------------------------------------------------------------
void
ContextToLayout::SetLayoutFuncToContext( CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin,
p_get_layout_func ip_get_layout_type_from_context)
{
m_context_to_layout[i_context][i_name_origin] =
ip_get_layout_type_from_context;
}
//-----------------------------------------------------------------------------
bool
ContextToLayout::RemoveLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin)
{
context_to_layout::iterator iter_context =
std::find_if( m_context_to_layout.begin(),
m_context_to_layout.end(),
boost::bind(&context_to_layout::value_type::first,_1) == i_context);
get_layout_func_map & named_func_map = iter_context->second;
context_to_layout::mapped_type::iterator iter_context_name =
named_func_map.find(i_name_origin);
if (named_func_map.end() != iter_context_name)
{
named_func_map.erase(iter_context_name);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
ContextToLayout::p_get_layout_func
ContextToLayout::GetLayoutFuncToContext(CApplicationContextManager::EApplicationContext
i_context,
const std::string_t & i_name_origin) const
{
context_to_layout::const_iterator iter_context =
std::find_if( m_context_to_layout.begin(),
m_context_to_layout.end(),
boost::bind(&context_to_layout::value_type::first,_1) == i_context);
const get_layout_func_map & named_func_map = iter_context-
second;
context_to_layout::mapped_type::const_iterator iter_context_name
= named_func_map.find(i_name_origin);
return iter_context_name != named_func_map.end() ?
(iter_context_name->second) : p_get_layout_func();
}
//-----------------------------------------------------------------------------
MLayoutManager::ELayoutType
ContextToLayout::GetLayoutType(CApplicationContextManager::EApplicationContext
i_context,
boost::shared_ptr<IContextToLayoutPred> ip_pred) const
{
MLayoutManager::ELayoutType layout_type =
MLayoutManager::LAYOUT_UNKNOWN;
context_to_layout::const_iterator iter_context =
m_context_to_layout.find(i_context);
if (m_context_to_layout.end() == iter_context)
{
layout_type = ip_pred->GetLayoutType();
ip_pred->Reset();
return layout_type;
}
const get_layout_func_map & named_func_map = iter_context-
second;
get_layout_func_map::const_iterator iter_func =
std::find_if(named_func_map.begin(), named_func_map.end(),
boost::bind(&IContextToLayoutPred::Compare, ip_pred,
boost::bind(&get_layout_func_map::value_type::second, _1)));
layout_type = ip_pred->GetLayoutType();
ip_pred->Reset();
return layout_type;
}
//-----------------------------------------------------------------------------
So as a result we have :
void
BigClass::_FindLayoutToSet(CApplicationContextManager::EApplicationContext
i_param )
{
MLayoutManager::ELayoutType state_to_set = mp_impl-
GetLayoutType(i_context);
_SetLayout(state_to_set);
}
So there are no dependecies between this class and
and classes wich really knows what layout we must
have based on their internal state.
Thank you very much if you have read all above.
Looking forward to your comments.