Re: Improving ugly(?) design: Data validation
On 17 Jun, 22:14, Rune Allnor <all...@tele.ntnu.no> wrote:
Hi all.
I have this class to validate a string according to a
specification contained in a string.
I have come up with a design for my validation, which
combines a few of the ideas that have been presented
in this thread with some of my own ideas (code below,
in case somebody are interested).
While the resulting design is nifty from a user's
point of view, I suspect there might be a hidden
'bomb' here. Any comments and criticism is welcome!
---
The validation comprises three classes:
- The error codes, which follows the ideas presented
by Ganesh
- The validator and report handler classes, which
are adaptions of the ideas presented by Stefan
The set-up is simple. An instance of the (Report)Handler
class is responsible for formatting and displaying
error reorts. The Validator class needs an instance
of the report handler to know how to display any
error messages.
The validation itself takes place in terms of an
'object function' call (overloaded Validator::operator()())
which returns true or false according to the result
of the test.
The way things presently work, the caller only gets
to know whether the data are valid, the implicit assumption
being that the ReportHandler can fully deal with error
recovery, and possibly throw exceptions if required.
This last assumption is somewhat fuzzy to me - I find
the resulting validation test very terse and nifty,
but I don't really believe no one else has checked out
this pattern before as there are lots of people a lot
smarter than me who deal with C++.
If somebody already tested this pattern and no one
suggest it when questions for validation patterns
come up, it makes me suspect there might be a hidden
'bomb' somewhere here.
Again, any comments and criticism is welcome.
Rune
//////////////////////////////////////////////////////////
#include <iostream>
#include <memory>
class EbClass; // Exception base class
class E1Class; // Exception type 1 class
class E2Class; // Exception type 2 class
class HandlerClass{
public:
virtual bool handleReport(std::auto_ptr<EbClass>);
virtual bool handleReport(std::auto_ptr<E1Class>);
virtual bool handleReport(std::auto_ptr<E2Class>);
};
class EbClass{
public:
virtual bool setHandler(HandlerClass*) = 0;
};
class E1Class : public EbClass {
public:
virtual bool setHandler(HandlerClass*);
};
class E2Class : public EbClass {
public:
virtual bool setHandler(HandlerClass*);
};
class ValidatorClass{
private:
HandlerClass* handler_;
std::auto_ptr<EbClass> error1(int) const;
std::auto_ptr<EbClass> error2(int) const;
public:
ValidatorClass(HandlerClass* h):handler_(h){};
bool operator()(const int) const;
};
std::auto_ptr<EbClass> ValidatorClass::error1(int i) const
{
if (i==1) // Check #1 fails is i == 1
{
return std::auto_ptr<EbClass>(new E1Class());
}
return std::auto_ptr<EbClass>();
}
std::auto_ptr<EbClass> ValidatorClass::error2(int i) const
{
if (i==2) // Check #2 fails is i == 2
{
return std::auto_ptr<EbClass>(new E2Class());
}
return std::auto_ptr<EbClass>();
}
bool ValidatorClass::operator()(int i) const
{
std::auto_ptr<EbClass> p = error1(i);
if (!handler_->handleReport(p))
{
// Insert report handling code,
// like issuing error messages here
std::cerr << "Error 1 detected: ";
return false;
}
p = error2(i);
if (!handler_->handleReport(p))
{
// Insert report handling code,
// like issuing error messages here
std::cerr << "Error 2 detected: ";
return false;
}
return true;
}
bool HandlerClass::handleReport(std::auto_ptr<EbClass> e)
{
if (e.get()) return e->setHandler(this);
else return true;
}
bool HandlerClass::handleReport(std::auto_ptr<E1Class> e)
{
if (e.get())
{
return false;
}
return true;
}
bool HandlerClass::handleReport(std::auto_ptr<E2Class> e)
{
if (e.get())
{
return false;
}
return true;
}
bool E1Class::setHandler(HandlerClass* h)
{
return h->handleReport(std::auto_ptr<E1Class>(this));
}
bool E2Class::setHandler(HandlerClass* h)
{
return h->handleReport(std::auto_ptr<E2Class>(this));
}
int main()
{
HandlerClass h;
ValidatorClass v(&h);
for (int i=0;i<6;++i)
{
if (v(i)) // Note the simplicity of the test!
{std::cout<< i << " is valid" << std::endl; }
else
{std::cout<< i << " is invalid" << std::endl; }
}
return(0);
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]