The Samurai Principle

P

Phlip

When you're using a language, you should use the style that the
language emphasizes.

You mean like this?

uri = reverse('my_uri_name', kwargs=dict(pk=record.pk))

That 'kwargs' there is ... a lapse of judgement. It is exposing a
technical detail (the "keyword arguments") instead of naming the
variable after its intent. It should be 'params=', at least, to match
the URI standards.

I'm just sayin'...
 
I

Ian Kelly

Exceptions are very dangerous by themselves, because if you don't trap
them just right they can cause side-effects.

And returning None on failure is dangerous, because if the programmer
does not take care to handle that case, the program may attempt to
regard it as actual data. This in turn results in hard-to-track bugs
elsewhere in the program, a fate much worse than an unhandled
exception. It's better to fail noisily than to fail silently.
They are worse than GOTO.

This assertion is questionable at best. Exceptions are structured;
goto is unstructured, giving you much more rope to hang yourself with.
 
I

Ian Kelly

Everyone gets defensive about the design flaws in their own language.
But the django.db situation is not even a design flaw; just a
misinterpretation of the Samurai Principle. int('yo') shall throw an
exception, but a missing record could be the result you were looking
for, so it's not exceptional.

I consider it exceptional because it breaks the rule that
Model.objects.get(...) returns an instance of Model. If it can also
return None, then this needs to be checked for every time the method
is called, because None does not implement the Model interface and
will break if you try to use it like that. You're still doing
exception handling; you're just doing it with an if instead of a
try-except. I prefer to do exception handling in a block clearly
marked as an exception handler.

Out of curiosity, would you also regard the case where two matching
records are found instead of one as not exceptional? After all, it
could be the result you were looking for. What should QuerySet.get
return in that case, if it doesn't raise an exception?
 
S

Steven D'Aprano

Exceptions are very dangerous by themselves, because if you don't trap
them just right they can cause side-effects.

Huh?

If you don't trap them just right, the cause a stack trace, which is a
side-effect I suppose. But it's an *intended* side-effect, since the
alternative would be a core dump (or worse, an incorrect program that
*doesn't* crash). This is a good thing!
 
S

Steven D'Aprano

While I'm at it, I'm going to log into comp.lang.java.misc and explain
to everyone why static typing is overkill, and implementation
inheritance is good for you.

Everyone gets defensive about the design flaws in their own language.
But the django.db situation is not even a design flaw; just a
misinterpretation of the Samurai Principle. int('yo') shall throw an
exception, but a missing record could be the result you were looking
for, so it's not exceptional.

I think you've misunderstood the meaning of "exception" if you think
that. It doesn't mean "error". Nor does it mean "rare". (Although, given
that exceptions in Python are expensive, one would hope they're not *too*
common.)

The unexceptional case of looking up a record is to find it. That, after
all, is the purpose of the lookup function -- to find the given record.
That's what it is designed to do, and anything else is considered
exceptional.

Whether the lookup function returns a special "not found" result, or
raises an exception, or sets some magic global error code somewhere, it's
still an exceptional case.
 
G

Grant Edwards

Huh?

If you don't trap them just right, they cause a stack trace,

Not always. That is the effect of not trapping them at all.
However, you can trap them incorrectly -- which can result in
hard-to-track down problems.

The main example of this is a "bare except" clause that not only
catches and handles the "expected" exception but also catches (and
mishandles/ignores) an unexpected one.
 
S

Steven D'Aprano

Not always. That is the effect of not trapping them at all. However,
you can trap them incorrectly -- which can result in hard-to-track down
problems.

The main example of this is a "bare except" clause that not only catches
and handles the "expected" exception but also catches (and
mishandles/ignores) an unexpected one.

Ah, fair enough. That would be a false positive error -- catching too
much rather than too little.

Still, that's no better, or worse, than misinterpreting special error
codes that are returned by functions. The main error mode there is
catching too little -- people neglect to check the error code, and
therefore have buggy code:

p = some_string.find('#')
print some_string[:p]

And who hasn't done this more than once?

re.search(pattern, some_string).group()
 
G

Grant Edwards

Ah, fair enough. That would be a false positive error -- catching too
much rather than too little.

Still, that's no better, or worse, than misinterpreting special error
codes that are returned by functions.

No, I didn't mean to imply that was the case. I agree with your
conclusion. I find it much easier to screw things up using the
"exceptional return value" method than the "exception raise" method.
 
P

Paul Rubin

Grant Edwards said:
I find it much easier to screw things up using the
"exceptional return value" method than the "exception raise" method.

That may be partly due to Python's not-so-good facilities for
implementing the "exceptional return value" method. To be fair, plenty
of other languages have similar shortcomings and it's mostly in more
recent languages that the problem has really been recognized, and
addressed with features like option types.
 
L

Lawrence D'Oliveiro

Ian Kelly said:
And returning None on failure is dangerous, because if the programmer
does not take care to handle that case, the program may attempt to
regard it as actual data.

But None *is* actual data.
 
R

Robert Kern

But None *is* actual data.

And that is exactly the reason why the Samurai Principle says to not return None
when the function fails to do what it intended to do.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
L

Lawrence D'Oliveiro

Robert said:
And that is exactly the reason why the Samurai Principle says to not
return None when the function fails to do what it intended to do.

How can the function “fail†when it returns what it is specified to return?
 
R

Robert Kern

How can the function “fail†when it returns what it is specified to return?

The Samurai Principle is about what specifications and guarantees a programmer
should make about his functions. It gives advice for programmers on how to
specify their functions in the face of failure conditions the function itself
sees. For example, a function that is supposed to fetch a record from a database
given a key, a failure condition would be that the key does not exist in the
database. Or the connection times out, or anything else that prevents the
function from retrieving a correct record for the key. The Principle says that a
programmer should specify his function such that it raises an exception to
signify this failure rather than to return None.

Of course, a programmer may make his functions' contracts as loose as he
pleases, and thus returning None may be "correct" in the sense that it satisfies
those contracts. The Principle simply advises that making such contracts is not
a good idea.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
S

Steven D'Aprano

How can the function “fail†when it returns what it is specified to
return?


Are you trolling?

On the unlikely event that you're not, if you have a function called
"len", the *intent* of the function is to return the length of its
argument. That's why it's called "len" rather than "raise_exception" or
"return_none", say.

The use of the term "fail" is entirely unexceptional here. It is normal
English to say such things as "the function re.match() returns None if
the regular expression fails to match" or "if we fail to acquire a lock,
raise an Exception".
 

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,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top