HOWTO use a Factory

G

Goran

Hi all,

i have some questions/problems about "Factories".

My origin is a constructor which needs a string in special format.

An example:

class Example_t {

public:
Example_t(std::string &aString);
...
}

My first idea was to check "aString" IN the constructor with
"boost::regex" AND to throw an exception if "aString" was bad.

Now I know it's bad to throw an exception in a constructor.

But what else?

How can I AVOID elegant a construction of an instance of "Example_t"
if "aString" is in bad format?

I've read a lot at the net but I'm still unhappy. At some other forum
I got the information to use something like that:

class Validator
{
public:
virtual bool validate(std::string) = 0;
};

class A
{
private:
A();
};

class Factory
{
public:
static A createA(std::string, *Validator);
static B createB(std::string, *Validator);
};

But I don't understand how to AVOID a construction with classes above
if the string is in bad format?

Thanks

Goran
 
V

Victor Bazarov

Goran said:
i have some questions/problems about "Factories".

My origin is a constructor which needs a string in special format.

An example:

class Example_t {

public:
Example_t(std::string &aString);
...
}

My first idea was to check "aString" IN the constructor with
"boost::regex" AND to throw an exception if "aString" was bad.

Now I know it's bad to throw an exception in a constructor.

No, it's not bad. It's the only way to let the caller know that
construction cannot be completed.
But what else?
Depends.

How can I AVOID elegant a construction of an instance of "Example_t"
if "aString" is in bad format?

Check before trying to construct it.
I've read a lot at the net but I'm still unhappy. At some other forum
I got the information to use something like that:

class Validator
{
public:
virtual bool validate(std::string) = 0;

Try to pass by reference to const wherever possible.
};

class A
{
private:
A();
};

class Factory
{
public:
static A createA(std::string, *Validator);
static B createB(std::string, *Validator);
};

But I don't understand how to AVOID a construction with classes above
if the string is in bad format?

The only "elegant" way that comes to mind is to return *a copy* of some
kind of "invalid" or "generic" object that can be inquired about its own
validity and discarded by the caller.

V
 
A

Alf P. Steinbach

* Goran:
Hi all,

i have some questions/problems about "Factories".

My origin is a constructor which needs a string in special format.

An example:

class Example_t {

public:
Example_t(std::string &aString);
...
}

My first idea was to check "aString" IN the constructor with
"boost::regex" AND to throw an exception if "aString" was bad.

Now I know it's bad to throw an exception in a constructor.

No, it isn't: it's the one and only rational way to deal with
construction failure.

But what else?

How can I AVOID elegant a construction of an instance of "Example_t"
if "aString" is in bad format?

Throw an exception from the constructor.

I've read a lot at the net but I'm still unhappy. At some other forum
I got the information to use something like that:

class Validator
{
public:
virtual bool validate(std::string) = 0;
};

class A
{
private:
A();
};

class Factory
{
public:
static A createA(std::string, *Validator);
static B createB(std::string, *Validator);
};

But I don't understand how to AVOID a construction with classes above
if the string is in bad format?

It's just meaningless, very bad advice.

However, you might and should probably consider introducing a class
ValidXXX that represents valid strings of whatever the format is.

Then the failure to validate can be detected as near to the source of
the string as possibly (by having /that/ class' constructor throw), and
valid strings can then be passed around as ValidXXX instances with no
need to check them everywhere for validity: you know they're valid.

This general principle of not passing possibly invalid data around tends
to simplify code enormously, thus also reducing the number of bugs.

And it's very very closely tied in with the concept of throwing from
constructors, so that you know that if you have an object at hand, then
that is perforce a /valid/ object with some class invariant established.
 
G

Goran

Goran wrote:
[...]
Now I know it's bad to throw an exception in a constructor.

No, it's not bad. It's the only way to let the caller know that
construction cannot be completed.
Ok, it's not bad :) but how could i use a try/catch with such a
constructor?

try {
Example_t myExample("fooBar");
}
// myExample is lost...
catch(...) {
cout << "Exception" << endl;
}
But what else?

Depends.

[...]

The only "elegant" way that comes to mind is to return *a copy* of some
kind of "invalid" or "generic" object that can be inquired about its own
validity and discarded by the caller.
How looks like such an object :) ?

Greets

Goran
 
G

Goran

* Goran:
[...]

However, you might and should probably consider introducing a class
ValidXXX that represents valid strings of whatever the format is.

Then the failure to validate can be detected as near to the source of
the string as possibly (by having /that/ class' constructor throw), and
valid strings can then be passed around as ValidXXX instances with no
need to check them everywhere for validity: you know they're valid.

This general principle of not passing possibly invalid data around tends
to simplify code enormously, thus also reducing the number of bugs.

And it's very very closely tied in with the concept of throwing from
constructors, so that you know that if you have an object at hand, then
that is perforce a /valid/ object with some class invariant established.
Ahh, that's a good way I think...

Greets

Goran
 
A

Andre Kostur

Goran wrote:
[...]
Now I know it's bad to throw an exception in a constructor.

No, it's not bad. It's the only way to let the caller know that
construction cannot be completed.
Ok, it's not bad :) but how could i use a try/catch with such a
constructor?

try {
Example_t myExample("fooBar");
}
// myExample is lost...

Yes, and why is that bad? A valid Example_t was unable to be created.
 
V

Victor Bazarov

Goran said:
Goran wrote:
[...]
Now I know it's bad to throw an exception in a constructor.

No, it's not bad. It's the only way to let the caller know that
construction cannot be completed.
Ok, it's not bad :) but how could i use a try/catch with such a
constructor?

try {
Example_t myExample("fooBar");
}
// myExample is lost...

Yes, here it's lost. Put all your code inside the 'try' clause.
catch(...) {
cout << "Exception" << endl;
}
But what else?

Depends.

[...]

The only "elegant" way that comes to mind is to return *a copy* of
some kind of "invalid" or "generic" object that can be inquired
about its own validity and discarded by the caller.
How looks like such an object :) ?

If you meant to ask, "what does such an object look like?", then
I have no idea since it's *your* object, *your* problem domain,
*your* model.

V
 
F

Frank Birbacher

Hi!
How looks like such an object :) ?

The easiest would be a "bool" to indicate success:

class MayFail
{
bool failed;
public:
MayFail(string const& input);
bool isGood() const throw() { return !failed; }
bool isBad() const throw() { return failed; }
};


MayFail::MayFail(string const& input)
: failed(true)
{
if(input.empty())
return; //failed
if( (input.length() & 1) == 0 )
return; //failed
...
failed = false; //success
}

MayFail mf("Hello");
if(mf.isBad())
reportError("MayFail failed");

HTH,
Frank
 
J

Joe Greer

However, you might and should probably consider introducing a class
ValidXXX that represents valid strings of whatever the format is.

Then the failure to validate can be detected as near to the source of
the string as possibly (by having /that/ class' constructor throw),
and valid strings can then be passed around as ValidXXX instances with
no need to check them everywhere for validity: you know they're valid.

This general principle of not passing possibly invalid data around
tends to simplify code enormously, thus also reducing the number of
bugs.

And it's very very closely tied in with the concept of throwing from
constructors, so that you know that if you have an object at hand,
then that is perforce a /valid/ object with some class invariant
established.

I have to strongly agree with this. :) I find it best to validate data
coming into the application as early as possible. For one thing, it
makes it easier to pinpoint where the problem originates and reprompt
the user if necessary for valid data. It also allows you to assume
correctness for the rest of the application (at least in release builds,
you might want some asserts here and there to validate assumptions about
the data that are active in debug/development builds.).

Another thing that comes to mind... You didn't mention whether this
data comes from the user or another programmer on the team. If it's the
later, then you may just want to validate in debug builds and make the
programmer fix his erroneous code rather than go through a possibly
expensive validation process all the time. In other words, some design
choices vary depending upon the target audience. For example, we would
all hate it if the STL did too much parameter validation each time we
tried to use it.

joe
 
T

Tobias

Now I know it's bad to throw an exception in a constructor.

It is bad to throw an exception from a destructor since the
destructors are used for stack unwinding (destroying objects on the
stack) after an exception.
Throwing an exception from a constructor is not so much a problem.

Best regards,
Tobias
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top