How to hide the same code (not using MACRO) ?

RCF support and general discussion.
Post Reply
acDev
Posts: 27
Joined: Tue Oct 08, 2013 3:08 pm
Location: Moscow
Contact:

How to hide the same code (not using MACRO) ?

Post by acDev »

Client-side code:

Code: Select all

// interface (C-style)
int NI_Print(const std::string & text);
int NI_PrintSL(const QStringList & text);

int NI_Print(const std::string & text)
{
  int hr = NOERROR;
  int xi = 0;
  do {
    try
    {
      hr = g_rcfclnt->Print(text);
    }
    catch (const RCF::Exception & e)
    {  
      hr = E_FAIL;
      if (!xi && e.getErrorId() != RCF::RcfError_ClientReadFail) xi++;  // xi = 1;
      xi++;
      if (xi > 1) NI_SetLastErrorMsg(e);
    }
    if (xi > 1) break;    // when an error number 31, try running the query again
  } while (xi > 0);  
  return hr;
}

int NI_PrintSL(const QStringList & text)
{
  int hr = NOERROR;
  int xi = 0;
  do {
    try
    {
      hr = g_rcfclnt->PrintSL(text);
    }
    catch (const RCF::Exception & e)
    {     
      hr = E_FAIL;
      if (!xi && e.getErrorId() != RCF::RcfError_ClientReadFail) xi++;  // xi = 1;
      xi++;
      if (xi > 1) NI_SetLastErrorMsg(e);
    }
    if (xi > 1) break;    // when an error number 31, try running the query again
  } while (xi > 0);  
  return hr;
}
How to hide the same code?
I'm not good in the C++, boost, BOOSTPP and other.

jarl
Posts: 238
Joined: Mon Oct 03, 2011 4:53 am
Contact:

Re: How to hide the same code (not using MACRO) ?

Post by jarl »

This will remove the duplication for you:

Code: Select all

int doPrint(const std::string & text)
{
	int hr = g_rcfclnt->Print(text);
	return hr;
}

int doPrint(const QStringList & text)
{
	int hr = g_rcfclnt->PrintSL(text);
	return hr;
}

template<typename T>
int NI_Print(const T & text)
{
	int hr = NOERROR;
	int xi = 0;
	do {
		try
		{
			hr = doPrint(text);
		}
		catch (const RCF::Exception & e)
		{  
			hr = E_FAIL;
			if (!xi && e.getErrorId() != RCF::RcfError_ClientReadFail) xi++;  // xi = 1;
			xi++;
			if (xi > 1) NI_SetLastErrorMsg(e);
		}
		if (xi > 1) break;    // when an error number 31, try running the query again
	} while (xi > 0);  
	return hr;
}
Kind Regards

Jarl Lindrud
Delta V Software
http://www.deltavsoft.com

acDev
Posts: 27
Joined: Tue Oct 08, 2013 3:08 pm
Location: Moscow
Contact:

Re: How to hide the same code (not using MACRO) ?

Post by acDev »

jarl wrote:This will remove the duplication for you:

Code: Select all

....
But if the features have different number of arguments?

Now I've done this:

Code: Select all

#define M_PREFIX                  \
  int hr = NOERROR;               \
  int xi = 0;                     \
  do {                            \
    try {

#define M_POSTFIX                        \
    }                                    \
    catch (const RCF::Exception & e)     \
    {                                    \
      hr = E_FAIL;                       \
      if (!xi && e.getErrorId() != RCF::RcfError_ClientReadFail) xi++; \
      xi++;                              \
      if (xi > 1) NI_SetLastErrorMsg(e); \
    }                                    \
    if (xi > 1) break;   /* when an error number 31, try running the query again */ \
  } while (xi > 0);                      \
  return hr
  
#define RCFCLIENT_METHOD_R1(method,v1) \
  M_PREFIX hr = g_rcfclnt->##method((v1)); M_POSTFIX
  
#define RCFCLIENT_METHOD_R2(method,v1,v2) \
  M_PREFIX hr = g_rcfclnt->##method((v1),(v2)); M_POSTFIX
  
#define RCFCLIENT_METHOD_R3(method,v1,v2,v3) \
  M_PREFIX hr = g_rcfclnt->##method((v1),(v2),(v3)); M_POSTFIX
  
#define RCFCLIENT_METHOD_R4(method,v1,v2,v3,v4) \
  M_PREFIX hr = g_rcfclnt->##method((v1),(v2),(v3),(v4)); M_POSTFIX
  
#define RCFCLIENT_METHOD_R5(method,v1,v2,v3,v4,v5) \
  M_PREFIX hr = g_rcfclnt->##method((v1),(v2),(v3),(v4),(v5)); M_POSTFIX

int NI_Print(const std::string & text)
{
  RCFCLIENT_METHOD_R1(Print, text);
}

int NI_PrintSL(const QStringList & text)
{
  RCFCLIENT_METHOD_R1(PrintSL, text);
}
It's better?

jarl
Posts: 238
Joined: Mon Oct 03, 2011 4:53 am
Contact:

Re: How to hide the same code (not using MACRO) ?

Post by jarl »

It's not so easy in C++ to factor out try/catch wrappers like you are wanting to do here. It can be done by wrapping the RCF call with boost::function<> and boost::bind, and then passing that as a parameter to a common try/catch wrapper. However wrapping arguments with boost::bind can be pretty intricate, if you haven't used it before.

A simpler way to factor out at least part of the try/catch is the following:

Code: Select all

bool catchHandler(int numberOfAttempts)
{
	bool shouldRetry = false;
	try
	{
		throw;
	}
	catch(const std::exception & e)
	{
		// Common catch logic here.
		// ...

		shouldRetry =  true;
	}
	return shouldRetry;
}

void NI_Print(const std::string & text)
{
	int hr = 0;
	bool shouldRetry = true;
	int numberOfAttempts = 0;
	while (shouldRetry)
	{
		++numberOfAttempts;
		try
		{
			g_rcfclnt->Print(text);
		}
		catch(...)
		{
			shouldRetry = catchHandler(numberOfAttempts);
		}
	}
}
You will still have some duplicated code, but it's fairly limited and only contains boilerplate. Also I wouldn't bother with any macros. Although they can save you a couple of minutes when you're writing the code, they are likely to cost you much more time than that when you are maintaining the code later on.
Kind Regards

Jarl Lindrud
Delta V Software
http://www.deltavsoft.com

Post Reply