From: Goran on
On Jun 23, 5:39 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote:
> public bool SearchForums(string sPattern)
> {
>    try
>    {
>
>      Regex rgx = new Regex(sPattern, RegexOptions.IgnoreCase);
>      foreach (var forum in ForumsList)
>      {
>        MatchCollection matches = rgx.Matches(forum.Description);
>        if (matches.Count > 0)
>        {
>            /// got something
>        }
>      }
>      return true;
>    }
>    catch (Exception ex)
>    {
>      MessageBox.Show("Regular Expression Error: " + ex.Message);
>    }
>    return false
>
> }

(Please don't think I am picking on you, it's just that this snippet
really makes my hear stand up on my back)

That's a horrible way to handle exceptions.

First off, you can't catch an Exception and say ""Regular Expression
Error: ". That's simply false. If nothing else, you could be out of
memory. On a more general note, in many-a-situation, you simply have
no idea what exactly went wrong, and going specific is an error.

I think I know why you did this, too: it's because people who struggle
with exceptions are in over-reaching fear of losing error context,
error context being e.g.: OK, I have this regexException, but once
caught, question is, where exactly did it happen and for what reason
(e.g. what inputs or program state etc). That loss of context is
luckily easily solved in rich execution environments à la .NET: inner
exceptions. So in your case, __if__ you think that you need more
context, you would do an equivalent of:

class MoreSpecificException
{ MoreSpecificException(params, Exception inner) {...} }
ResultType f(params)
{
try
{
workworkwork;
return someresult;
}
catch(RegexException e)
{
throw new MoreSpecificException(additional "context" info, e);
}
}

(But, as I said to RB, you are, just like him, not allowed to write a
try/catch ;-). When you think you need one, stop and think; question
to ask is "where is this caught if I do nothing?").

Second, this function presumes that there's a good context to go on
the screen with error message. That's a BIG presumption. E.g. what if
this is not called from the main thread? What if I want to call it
elsewhere (re-usability is low).

And third, that function STILL can exit with an exception. E.g. OOM,
or other resource shortage happened in your catch. So you potentially
lie to your caller.

All in all, that's a really poor way to write code with exceptions. In
fact, in exception-enabled environments, attempts to write error-
return code (you did that there) are often horribly misguided. Please,
for the love of God, don't do this. One can kinda-sorta escape in MFC,
but IMNSHO even there it's a bad idea.

Goran.
From: Hector Santos on
Goran, it was more of a tag, i.e. for tracing, something I do a lot
when I am adding something I consider "abnormal" to immediately know
where and what in the high possible levels of exceptions traps. I
think I wrote that here when posting the highly truncated function,
but the actual tag I have is:

MessageBox.Show("SEARCH EXCEPTION: "+ex.Message);

and again, that is a "tag" more than anything else. The actual
function is 5-6 times larger.

I see our points, but I won't agree it is "horrible."

But again, you proved my point. Until you are completely aware of all
the possible specific exceptions traps for a class, a documentation
and learning issue, the "catch all" is going to be common place. For
me, productivity wise, I am going wrap a catch all with a "tag" as
the fastest way to get going as I always done for any language. Then
the exercise of fine tuning it begins, possibly cleaning it up, adding
the specifics as you laid out.

Maybe Intellisense should have a macro for extracting from a selected
class and wrapping try block adding all the possible specific
exception catch blocks. Maybe its already there, I haven't checked.

--
HLS


Goran wrote:

> On Jun 23, 5:39 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote:
>> public bool SearchForums(string sPattern)
>> {
>> try
>> {
>>
>> Regex rgx = new Regex(sPattern, RegexOptions.IgnoreCase);
>> foreach (var forum in ForumsList)
>> {
>> MatchCollection matches = rgx.Matches(forum.Description);
>> if (matches.Count > 0)
>> {
>> /// got something
>> }
>> }
>> return true;
>> }
>> catch (Exception ex)
>> {
>> MessageBox.Show("Regular Expression Error: " + ex.Message);
>> }
>> return false
>>
>> }
>
> (Please don't think I am picking on you, it's just that this snippet
> really makes my hear stand up on my back)
>
> That's a horrible way to handle exceptions.
>
> First off, you can't catch an Exception and say ""Regular Expression
> Error: ". That's simply false. If nothing else, you could be out of
> memory. On a more general note, in many-a-situation, you simply have
> no idea what exactly went wrong, and going specific is an error.
>
> I think I know why you did this, too: it's because people who struggle
> with exceptions are in over-reaching fear of losing error context,
> error context being e.g.: OK, I have this regexException, but once
> caught, question is, where exactly did it happen and for what reason
> (e.g. what inputs or program state etc). That loss of context is
> luckily easily solved in rich execution environments � la .NET: inner
> exceptions. So in your case, __if__ you think that you need more
> context, you would do an equivalent of:
>
> class MoreSpecificException
> { MoreSpecificException(params, Exception inner) {...} }
> ResultType f(params)
> {
> try
> {
> workworkwork;
> return someresult;
> }
> catch(RegexException e)
> {
> throw new MoreSpecificException(additional "context" info, e);
> }
> }
>
> (But, as I said to RB, you are, just like him, not allowed to write a
> try/catch ;-). When you think you need one, stop and think; question
> to ask is "where is this caught if I do nothing?").
>
> Second, this function presumes that there's a good context to go on
> the screen with error message. That's a BIG presumption. E.g. what if
> this is not called from the main thread? What if I want to call it
> elsewhere (re-usability is low).
>
> And third, that function STILL can exit with an exception. E.g. OOM,
> or other resource shortage happened in your catch. So you potentially
> lie to your caller.
>
> All in all, that's a really poor way to write code with exceptions. In
> fact, in exception-enabled environments, attempts to write error-
> return code (you did that there) are often horribly misguided. Please,
> for the love of God, don't do this. One can kinda-sorta escape in MFC,
> but IMNSHO even there it's a bad idea.
>
> Goran.

From: Hector Santos on
As an engineer, I look at all things the same way, i.e, the same
issues, the same error points, the same I/O behavior. That is
regardless of the language or framework because at the end of the day,
we are all faced with the same issues - and it should be. On any
given day, I have to work in about 4-6 or more languages and
environments, today, its C, C++, Java, Javascript, VB, PHP, WCBASIC
(our own), DELPHI Pascal, and now more of .NET, VB.NET, C#.NET and my
dabbling in C++.NET and I probably missed a few, oh yeah, if we want
to call it "languages", SQL, XML, HTML, ASP, WSP (Our own ASP), now
I'm looking at LINQ and learning (actually restarting in earnest)
writing many sub-classes and interfaces that we will need, all these
need different levels of thinking. It can hurt the brain, but I manage
it. I am a speed demon so I look for the fastest way to get going -
fine tuning is an after thought. I think I am pretty good at getting
it right the first time by this point, but I am also fully aware when
somethings needs more intention and make a note of it mentally or
inline comments.

As it often the case, the devils are in the details, as such, 99% of
the time, my comments here and even in most areas are more
generalizations. Yet, I am fully aware that can be easy pickings for
some that don't, won't or can't see the points. So I should be
careful of that.

That said, I don't think it is irrational at this day of age of having
a knowledge base of the most possible errors seen and a common set of
errors for a given sub-set or category of functions. Maybe that is
part of being an Software Engineering expert - which is not
necessarily programming - but interfacing systems and sub-systems.

Case in point, I/O, there is a pretty well define set of highly
probably errors and then ones that are common to general I/O.

For fopen, for example, some people will view

not found
bad input (bad path)
locked error
sharing error

are natural errors with a high expectation, with a certain level of
natural recovery, while others are global and not highly recovery:

out of memory
out of disk space
hard drive problem

Again, don't focus on the attempts for details mentioned, but the
generalization I am making.

As I mentioned early, I still think exceptions are a crutch, but
environments like .NET need them because of the high complexity mostly
and also for the way methods are written as procedures, not as
functions. Given a choice, some developers are are familar with both,
will choose. Other, newer generation developers will most likely see
it one way - traps. But if even the option, maybe they (or some) will
using a boolean approach.

There is no cut and dry answer - thats for sure. :)

--

Goran wrote:

> On Jun 23, 9:58 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote:
>> That is why I say the real issue is the lack of documentation or the
>> "hidden" knowledge that are wrapped into classes.
>>
>> When you use fopen(), you know what the possible errors are, basically
>>
>> invalid file path, error 2
>> not found, for a already exist mode, error 3
>> read/write sharing issue, error 5 or 32
>>
>> but regardless of the error code, the #1 idea is that the FILE *
>> stream variable is NULL.
>>
>> Some of the things I am coming across with .NET is that some old
>> traditional and SOLID concept no longer apply.
>
> I disagree very much with this observation. The thing is, even fopen
> has more failure modes than that (and they are probably OS-specific,
> too). And fopen is a mighty simple, very low-level operation.
>
> On "big" frameworks like .NET, one function hides much much more
> functionality, and consequently, much more failure modes. So without
> exceptions, you can either simplify failure info going out of the
> function to stay in a "manageable" situation (effectively, lie),
> either make it effectively unmanageable by specifying all failure
> modes.
>
> Here, case in point is a random Win32 API: it's BOOL fn(params), and
> doc says: in case of failure, call GetLastError for more info. Seldom
> it is defined what GetLastError might return. Why is that? Simply
> because documenting all possible failure modes is mighty irrational.
>
> Goran.



--
HLS
From: Goran on
On Jun 24, 1:18 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote:
> But again, you proved my point.  Until you are completely aware of all
> the possible specific exceptions traps for a class, a documentation
> and learning issue, the "catch all" is going to be common place.

Hey, I am trying to grind a different axe here!

I am trying to say this: exceptions or error-return, it's both
unrealistic and needles to be aware of / handle all possible
exceptions / failure modes at any given place. It's easy to see why
it's unrealistic: consider your own function somewhere in the call
stack. Say that it can call X "base"/"system" functions, each having a
small number of Y failure modes, some of them overlapping, for a total
of e.g. X*Y*0.75 failure modes. Say that function is in usual win32/
CRT form of "BOOL result + GetLastError" How do you work with that?

if (!myfunc(params))
switch (GetLastError()) { bloody hell, it's ful of cases! }

?

Of course not. For the most part, you just do

if (!myfunc(params))
return false;

(or equivalent thereof)

Typical error-return code looks like the above. IOW, for the most part
(like, 90% of cases), it does not try to "handle" any failure modes at
the place of the call.

Well... (drum roll...) exceptions give you that behavior automatically
(and number of failure modes does not change due to them; in that
respect, there's no difference). But you seem to want to catch all
these exceptions. Now I clearly have to ask: why? Just do "return
false"! (That is, in case of exceptions, do nothing). That is the
error of your ways WRT exceptions. No, seriously!

> Maybe Intellisense should have a macro for extracting from a selected
> class and wrapping try block adding all the possible specific
> exception catch blocks.

Seems like you yearn for Java checked exceptions ;-).

Goran.
From: Goran on
On Jun 24, 1:58 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote:
> Case in point, I/O, there is a pretty well define set of highly
> probably errors and then ones that are common to general I/O.
>
> For fopen, for example, some people will view
>
>      not found
>      bad input (bad path)
>      locked error
>      sharing error
>
> are natural errors with a high expectation, with a certain level of
> natural recovery, while others are global and not highly recovery:
>
>      out of memory
>      out of disk space
>      hard drive problem
>
> Again, don't focus on the attempts for details mentioned, but the
> generalization I am making.

Yeah, I've heard (a variation of) that reasoning before, and I don't
like it ;-). Here's why: I believe that it creates a hybrid system for
error propagation that is ultimately harder to work with than clear-
cut error-return (or clear-cut exceptions). For example, you still
have to take care about making code exception safe, and you still have
to know where are "if" functions.

Sure, you might want to something differently about your "natural"
errors. With exceptions, that translates to catching particular
exception type here and there, and taking corrective action (or, in
error-return code, taking said corrective action in a rare "if" (but!
drawback is that there are zillions of "if"s in error-return, so the
"interesting" ones are harder to spot ;-)). So there, IMHO, you don't
gain much by having an "if" being simpler than a try/catch.

Goran.