473,473 Members | 2,155 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

[Design] Should accessors throw exception ?

Hi there,

I'd like to know if there is a general answer to the following
question: when making a public interface that access a container
should the function throw an exception when the element is not found ?
Otherwise I need two functions: a Find and a Get function which put
the burden on the application programmer to always call Find before
Get.
The other alternative would be to return some kind of sentinel (like
std::set<>::end() )...

Comments ?

Thanks
-Mathieu

eg.
#include <map>
#include <string.h>

struct Phone { int P; };
struct Name { const char *N;
bool operator <(Name const &n) const { return strcmp(N,n.N) < 0; }
};
struct YellowPage
{
void Insert(Name const &n,Phone const &p)
{ I.insert( std::map<Name,Phone>::value_type(n,p) ); }
bool Find(Name const & n) { return I.find(n) != I.end(); }
Phone const &Get(Name const&n) { return I.find(n)->second; }
private:
std::map<Name,PhoneI;
};
Sep 12 '08 #1
11 1475
Hi,

I think returning a special value like end() or 0 for a pointer is the best
solution.

I think exception should only be used when something exceptional occurs, for
instance you expect a conifiguration file is there yet when you try to open
it it is missing or you try to access a database but the DBA took it down
for maintenance. This way you (or the user of your library) can catch those
thiings somewhere 'high up' in the code knowing that everything in between
is released and handled nicely and continue (maybe waiting a few minutes and
try again.

And indeed a find/get combination is more work. Also with the end() you make
it work the same as the STL.

Regards, Ron AF Greve

http://www.InformationSuperHighway.eu

"mathieu" <ma***************@gmail.comwrote in message
news:32**********************************@k13g2000 hse.googlegroups.com...
Hi there,

I'd like to know if there is a general answer to the following
question: when making a public interface that access a container
should the function throw an exception when the element is not found ?
Otherwise I need two functions: a Find and a Get function which put
the burden on the application programmer to always call Find before
Get.
The other alternative would be to return some kind of sentinel (like
std::set<>::end() )...

Comments ?

Thanks
-Mathieu

eg.
#include <map>
#include <string.h>

struct Phone { int P; };
struct Name { const char *N;
bool operator <(Name const &n) const { return strcmp(N,n.N) < 0; }
};
struct YellowPage
{
void Insert(Name const &n,Phone const &p)
{ I.insert( std::map<Name,Phone>::value_type(n,p) ); }
bool Find(Name const & n) { return I.find(n) != I.end(); }
Phone const &Get(Name const&n) { return I.find(n)->second; }
private:
std::map<Name,PhoneI;
};

Sep 12 '08 #2
mathieu wrote:
Hi there,

I'd like to know if there is a general answer to the following
question: when making a public interface that access a container
should the function throw an exception when the element is not found ?
Otherwise I need two functions: a Find and a Get function which put
the burden on the application programmer to always call Find before
Get.
I tend to favour returning NULL if the return type is a pointer and
throwing an exception if the return type is a reference or an object
without an obvious bad value.

--
Ian Collins.
Sep 12 '08 #3
On Sep 12, 11:07 pm, mathieu <mathieu.malate...@gmail.comwrote:
I'd like to know if there is a general answer to the following
question: when making a public interface that access a
container should the function throw an exception when the
element is not found ? Otherwise I need two functions: a Find
and a Get function which put the burden on the application
programmer to always call Find before Get.
It depends on the application. I used two different solutions
in my pre-standard AssocArray (a hash table): the operator[] had
a pre-condition that the element was present, and asserted this
precondition, but there was a get function which returned a
pointer to the element, and returned a null pointer if the
element wasn't found. In other contexts, I've found the
behavior of std::map<>::operator[] to be useful as well: just
insert the missing element. On the other hand, I can't think of
a context where throwing an exception would be the desired
behavior.
The other alternative would be to return some kind of sentinel
(like std::set<>::end() )...
Just return a pointer to the element, rather than a reference,
and you have a sentinel value defined by the standard, the null
pointer.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 12 '08 #4
On Sep 13, 12:55 am, Ian Collins <ian-n...@hotmail.comwrote:
mathieu wrote:
I'd like to know if there is a general answer to the
following question: when making a public interface that
access a container should the function throw an exception
when the element is not found ? Otherwise I need two
functions: a Find and a Get function which put the burden on
the application programmer to always call Find before Get.
I tend to favour returning NULL if the return type is a
pointer and throwing an exception if the return type is a
reference or an object without an obvious bad value.
Isn't this inversing cause and effect. I tend to choose to
return a pointer if I need a sentinel value, and a reference
otherwise.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 12 '08 #5
James Kanze wrote:
On Sep 13, 12:55 am, Ian Collins <ian-n...@hotmail.comwrote:
>mathieu wrote:
>>I'd like to know if there is a general answer to the
following question: when making a public interface that
access a container should the function throw an exception
when the element is not found ? Otherwise I need two
functions: a Find and a Get function which put the burden on
the application programmer to always call Find before Get.
>I tend to favour returning NULL if the return type is a
pointer and throwing an exception if the return type is a
reference or an object without an obvious bad value.

Isn't this inversing cause and effect. I tend to choose to
return a pointer if I need a sentinel value, and a reference
otherwise.
Not really, consider dynamic_cast. I think you have given the same
answer I did in a different way. NULL is a sentinel value.

--
Ian Collins.
Sep 13 '08 #6
On Sep 13, 3:45 am, Ian Collins <ian-n...@hotmail.comwrote:
James Kanze wrote:
On Sep 13, 12:55 am, Ian Collins <ian-n...@hotmail.comwrote:
mathieu wrote:
>I'd like to know if there is a general answer to the
following question: when making a public interface that
access a container should the function throw an exception
when the element is not found ? Otherwise I need two
functions: a Find and a Get function which put the burden
on the application programmer to always call Find before
Get.
I tend to favour returning NULL if the return type is a
pointer and throwing an exception if the return type is a
reference or an object without an obvious bad value.
Isn't this inversing cause and effect. I tend to choose to
return a pointer if I need a sentinel value, and a reference
otherwise.
Not really, consider dynamic_cast. I think you have given the same
answer I did in a different way.
Partially, but you seemed to be saying that you chose the means
of reporting errors according to the return value, where as I
would choose the type of the return value according to whether I
needed to report errors or not. (Supposing there is a choice,
of course. For constructors and overloaded operators, you often
don't have any choice but to throw an exception in case of
error.)
NULL is a sentinel value.
Which is why I choose to return a pointer if I need a sentinal
value. (In cases where I don't actually have something to
point to, for example if the function returns a calculated
value, I will use Fallible.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 13 '08 #7
James Kanze wrote:
Which is why I choose to return a pointer if I need a sentinal
value. (In cases where I don't actually have something to
point to, for example if the function returns a calculated
value, I will use Fallible.)
Do you have particular reasons to avoid Fallible references?

--
Gennaro Prota | name.surname yahoo.com
Breeze C++ (preview): <https://sourceforge.net/projects/breeze/>
Do you need expertise in C++? I'm available.
Sep 13 '08 #8
mathieu <ma***************@gmail.comkirjutas:
Hi there,

I'd like to know if there is a general answer to the following
question: when making a public interface that access a container
should the function throw an exception when the element is not found ?
Otherwise I need two functions: a Find and a Get function which put
the burden on the application programmer to always call Find before
Get.
The other alternative would be to return some kind of sentinel (like
std::set<>::end() )...
One design I have found handy:

T GetByName(const std::string name) const; // throws if name not found
T GetByName(const std::string name, T defaultvalue) const; // returns
defaultvalue if name not found

So the client code has the option to choose if it wants a hard or soft
fallback.

This design is to be suggested if the content of the container is not
well controlled (filled by user input or by some other software
component, for example), so the container is not in a good position to
decide about what to do in case of missing elements. In this situation,
the client code is often able to define the needed behavior better.

hth
Paavo
Sep 13 '08 #9
In article <Xn*************************@216.196.97.131>, Paavo Helde
<no****@ebi.eewrote:
[...]
One design I have found handy:

T GetByName(const std::string name) const; // throws if name not found
T GetByName(const std::string name, T defaultvalue) const; // returns
defaultvalue if name not found

So the client code has the option to choose if it wants a hard or soft
fallback.
Nifty pattern, but wouldn't it tend to expand the interface and bloat
implementation if there were lots of functions like this? I'd think
returning something like boost::optional<Tthat throws when attempting to
dereference when empty would be best:

template<typename T>
checked_optional {
T t;
bool exists;
public:
checked_optional() : exists( false ) { }
checked_optional( T t ) : t( t ), exists( true ) { }
operator bool () const { return exists; }
T& operator * () const
{
if ( !exists )
throw "Bla bla";
return t;
}
};

checked_optional<TGetByName( std::string name );

void use_t( T );

// Just dereference result if you want exception
use_t( *GetByName( "foo" ) );

// Check the result before dereferencing if you want to handle not found
checked_optional<Tt = GetByName( "foo" );
if ( t )
use_t( *t );
else
not_found();
Sep 14 '08 #10
On Sep 14, 3:48 pm, blargg....@gishpuppy.com (blargg) wrote:
In article <Xns9B18DCFE7997Fnobodyeb...@216.196.97.131>, Paavo
Helde<nob...@ebi.eewrote:
[...]
One design I have found handy:
T GetByName(const std::string name) const; // throws if name not found
T GetByName(const std::string name, T defaultvalue) const; // returns
defaultvalue if name not found
So the client code has the option to choose if it wants a
hard or soft fallback.
Nifty pattern, but wouldn't it tend to expand the interface
and bloat implementation if there were lots of functions like
this?
How many getters do you have in one class? In cases where you
systematically have something like this (e.g. data base access,
with null values in some columns), you would, of course, use a
class to represent nullable values; the above function would be
in that class, and the class representing a row would simply
return instances of that class.
I'd think returning something like boost::optional<Tthat
throws when attempting to dereference when empty would be
best:
template<typename T>
checked_optional {
T t;
bool exists;
public:
checked_optional() : exists( false ) { }
checked_optional( T t ) : t( t ), exists( true ) { }
operator bool () const { return exists; }
T& operator * () const
{
if ( !exists )
throw "Bla bla";
return t;
}
};
checked_optional<TGetByName( std::string name );
void use_t( T );
// Just dereference result if you want exception
use_t( *GetByName( "foo" ) );
But that doesn't solve the problem. At the client level, if you
want a default value, you have to declare an instance of a
variable, then test it. The whole point is to be able to
combine everything into a simple functional expression. (Also,
the use of implicit conversion to bool is blatant overload
abuse. If you want to check for validity, provide an isValid()
function.)
// Check the result before dereferencing if you want to handle not found
checked_optional<Tt = GetByName( "foo" );
if ( t )
use_t( *t );
else
not_found();
Wordy and obfuscated. And the interesting example would call
use_t with a default value if the value wasn't found, e.g.:

use_t( container.get( key ).elseDefaultTo( defaultValue ) ) ;

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 14 '08 #11
bl********@gishpuppy.com (blargg) kirjutas:
In article <Xn*************************@216.196.97.131>, Paavo Helde
<no****@ebi.eewrote:
[...]
>One design I have found handy:

T GetByName(const std::string name) const; // throws if name not
found T GetByName(const std::string name, T defaultvalue) const; //
returns defaultvalue if name not found

So the client code has the option to choose if it wants a hard or
soft fallback.

Nifty pattern, but wouldn't it tend to expand the interface and bloat
implementation if there were lots of functions like this? I'd think
returning something like boost::optional<Tthat throws when
attempting to dereference when empty would be best:
In this case you would have two decision branches, one inside of the
getter function to decide whether to return the "empty" value, and one in
the client code to test if the value was empty. I think this is more
complex design and unneeded if the client code really does not care if
the item was present or not, and just wants to apply the default value
when needed.

And yes, you shouldn't have this pattern in lots of functions. Only the
kind of "general" containers deserve it, which may be used in situations
where the desired default behavior is not the same in all cases. Maybe
providing two different container classes would be a cleaner solution
indeed.

Regards
Paavo
Sep 14 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: fred | last post by:
Hello, I have a program that reads from a file at several different places. I want to find when the file hits the EOF. At this point I want to tell the calling method that this has happened so...
3
by: Steve - DND | last post by:
I was wondering if anyone can point me to some articles or practices they use for dealing with errors in their applications; particularly in an n-tier design. I am trying to find one way to...
11
by: chopsnsauce | last post by:
Here's the example: Dim frm As New FORM1 Try frm.show Catch ex As Exception msgbox ex.message
1
by: GS | last post by:
Any points of what would be the good error handling design for application? User error handling in Application_OnError and throw() new errors on conditions through the code? I'd like utlimiately to...
8
by: cat | last post by:
I had a long and heated discussion with other developers on my team on when it makes sense to throw an exception and when to use an alternate solution. The .NET documentation recommends that an...
6
by: GarrettD78 | last post by:
Accidently posted this to the wrong group so I am reposting. This is probably a newbie question but I am a little confused about how to go next with my code. I think I want to use a factory pattern...
4
by: Helge Jensen | last post by:
In C# 2.0 System.IO.Stream is declared as: public class Stream: ..., IDisposable { ... public void Dispose(); public void Dispose(bool); IDisposable.Dispose(); } Which must be a...
9
by: Mr Flibble | last post by:
Hi all, happy Friday! (certainly Friday is a day worth celebrating). I have a question on try/catch design (an exciting Friday topic for sure): I can either put a try/catch block in every...
3
by: Mousam | last post by:
Hi All, First of all forgive me for the length of this post. I am developing one library for some text editor. In this library I want to provide a set of C++ classes which will enable client (of...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.