Reputation: 3809
Imaging a class which is doing the following thing
class AClass
{
AClass() : mode(0) {}
void a()
{
if (mode != 0) throw ("Error mode should be 0");
// we pass the test, so now do something
...
mode = 1;
}
void b()
{
if (mode != 1) throw("Error mode should be 1");
// we pass the test, so now do something
...
}
int mode;
};
The class contains many methods (easily than 20) and for each one of these methods we need to do a check on the value of mode which is obviously a lot of code duplication. Furthermore, we can identify two categories of methods, those who will throw an error if mode !=0 and those who will throw an error if mode != 1. Could it somehow be possible to group these methods in two categories (category A = method who throw an error if mode != 0) and category B for method who throw an error if mode != 1)?
EDIT: Looking at the current answers I realise the way I formulate the question and the problem is probably not clear enough. What I want to avoid is to have to call for a function in each method of the class. Whether we write code at the beginning of the methods or put this code in a function and call this function is not the problem. The question is whether we can avoid this all together. Whether there is a technique that would help to automatically check whether the call to a method of a class is valid depending on some context.
AClass is actually an API in the context of my project. a(), b(), etc. are some functions that the programmer can call if she/he wants to use the API however some of these methods can only be called in some precise order. For example you can see in the code that a() sets mode = 1. So the programmer could do something like this:
a(); // mode = 0 so it's good
b(); // mode = 1 so it's good
but this code needs to fail (it will compile of course but at execution time I need to throw an error mentioning that the context in which b() was called was wrong.
b(); // mode 0 so it won't work
a(); // it will compile but throw an exception
I tried to see if any pattern could work for doing this but couldn't find anything at all. It seems impossible to me and I believe the only option is really to write the necessary code. Could anyone though suggest something? Thank you very much.
Upvotes: 1
Views: 512
Reputation: 3809
After looking into the problem a bit more, it seems that the closest helpful answer is (by Nick):
Try looking into Aspect Oriented Software Development en.wikipedia.org/wiki/Aspect-oriented_software_development – Nick
The Wikipedia page is not easy to read and doesn't provide a C++ example, so it stays very abstract at first, but if you search for Aspect Oriented Programming and C++ you will find links with examples.
The idea behind it (and it just a very quick summary) is to find a way of adding "services" or "functionalities" to a class. These services can notably be added at compile time through the use of templates. This is what I was intuitively experimenting with as an attempt at solving my problem, and I am glad to see this technique has been around for many years.
This document is a good reference:
Aspect-Oriented Programming & C++ By Christopher Diggins, August 01, 2004.
And I found this link with example useful to understand the concept:
Implementing Aspects using Generative Programming by Calum Grant.
Upvotes: 0
Reputation: 14619
Aside from implementing the check in a dedicated method (a great suggestion), you could also consider decomposing the behavior in AClass
into two distinct classes, or delegate the specific portion to a new pair of classes. This seems especially appropriate if the mode
is invariant for an instance (as it is in the example).
Upvotes: 2
Reputation: 76245
Just add private member functions:
void assert_mode_0() {
assert_mode(0);
}
void assert_mode_1() {
assert_mode(1);
}
void assert_mode(int m) {
if (mode != m)
throw msg[m];
}
with a suitable definition of msg
, of course.
Upvotes: 3
Reputation:
Well I guess the simplest solution would be defining a macro or some inline function like this:
#define checkErrorMode0(x) \
if ((x) != 0) throw ("Error mode should be 0");
#define checkErrorMode1(x) \
if ((x) != 1) throw ("Error mode should be 1");
// or, probably within your class
inline void checkErrorMode0(int x){
if ( x != 0 ) throw ("Error mode should be 0");
}
inline void checkErrorMode1(int x){
if ( x != 1 ) throw ("Error mode should be 1");
}
So you could simply call one of these methods inside of the functions that require them.
But most likely there is a more elegant workaround for what you want to do.
Upvotes: 0