Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > The Samurai Principle

Reply
Thread Tools

The Samurai Principle

 
 
Phlip
Guest
Posts: n/a
 
      09-07-2010
Pythonistas:

The "Samurai Principle" says to return victorious, or not at all. This
is why django.db wisely throws an exception, instead of simply
returning None, if it encounters a "record not found".

I illustrated the value of that concept, here:

http://c2.com/cgi/wiki?SamuraiPrinciple
 
Reply With Quote
 
 
 
 
Albert Hopkins
Guest
Posts: n/a
 
      09-07-2010
On Mon, 2010-09-06 at 20:48 -0700, Phlip wrote:
> Pythonistas:
>
> The "Samurai Principle" says to return victorious, or not at all. This
> is why django.db wisely throws an exception, instead of simply
> returning None, if it encounters a "record not found".


How does that compare to, say, the "Kamikaze Principle"?

-a


 
Reply With Quote
 
 
 
 
Phlip
Guest
Posts: n/a
 
      09-07-2010
> How does that compare to, say, the "Kamikaze Principle"?

Return victorious AND not at all!

(All return values are packed up and thrown...
 
Reply With Quote
 
geremy condra
Guest
Posts: n/a
 
      09-07-2010
On Tue, Sep 7, 2010 at 6:56 AM, Bruno Desthuilliers
<(E-Mail Removed)> wrote:
> Phlip a écrit :
>>>
>>> How does that compare to, say, the "Kamikaze Principle"?

>>
>> Return victorious AND not at all!
>>
>> (All return values are packed up and thrown...

>
> ... and then it raises a SystemError !-)


general protection fault

Geremy Condra
 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      09-07-2010
Back to the topic, I tend to do this:

for record in Model.objects.filter(pk=42):
return record

return sentinel

Having lots of short methods helps, because return provides both
control-flow and a result value. But it abuses 'for' to mean 'if'. I
feel _reeeeally_ guilty about that!

But I miss this, from (cough) RoR:

record = Model.find(42) || sentinel

Django should provide this:

record = Model.objects.get(pk=42, _if_does_not_exist=sentinel)

sentinel could be a lambda that concocts a new record (where such a
record should not be created with get_or_create()). That would be
efficient when you don't spend time constructing it just so the happy-
path of .get() can throw it away.

Or sentinel could be None, or a NullObject that efficiently behaves
like a record but provides stubbed-out behaviors.

My committees will be submitting these proposals to the Django
committees shortly... C-:

--
Phlip
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      09-07-2010
On Tue, Sep 7, 2010 at 10:02 AM, Phlip <(E-Mail Removed)> wrote:
> Back to the topic, I tend to do this:
>
> *for record in Model.objects.filter(pk=42):
> * * return record
>
> *return sentinel


How is that any better than just catching the exception?

try:
return Model.objects.get(pk=42)
except Model.DoesNotExist:
return sentinel

The flow of control is much clearer this way.

Cheers,
Ian
 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      09-07-2010
On Sep 7, 10:36*am, Ian Kelly <(E-Mail Removed)> wrote:
> On Tue, Sep 7, 2010 at 10:02 AM, Phlip <(E-Mail Removed)> wrote:
> > Back to the topic, I tend to do this:

>
> > *for record in Model.objects.filter(pk=42):
> > * * return record

>
> > *return sentinel

>
> How is that any better than just catching the exception?
>
> try:
> * * return Model.objects.get(pk=42)
> except Model.DoesNotExist:
> * * return sentinel
>
> The flow of control is much clearer this way.


It reminds me of Visual Basic.

And no it's not "much clearer". Exceptions are for catastrophic errors
that the caller should care not to handle. A "record not found" is not
a catastrophe. Read my original post.

AAAND you need to test that the DoesNotExist occurs for the exact
reason you expect. Your except is not complete. Making it complete is
very hard, and will break as soon as the model changes.
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      09-07-2010
On Tue, Sep 7, 2010 at 11:52 AM, Phlip <(E-Mail Removed)> wrote:
> And no it's not "much clearer".


It's clearer because it does exactly what it says it does, unlike your
approach that masquerades as a loop.

> Exceptions are for catastrophic errors


No, they're for flagging "exceptional" states. /Errors/ are for
catastrophic errors. The fact that errors are a subset of exceptions
is just for convenience in handling.

> AAAND you need to test that the DoesNotExist occurs for the exact
> reason you expect.


I'm not following you here. The only possible reason the exception
can occur is if no matching row exists. If there were some other
reason for raising an exception, then a different exception would be
raised.

> Your except is not complete. Making it complete is
> very hard, and will break as soon as the model changes.


Still not following you. What is it missing, and how will it break?
 
Reply With Quote
 
Tim Chase
Guest
Posts: n/a
 
      09-07-2010
On 09/07/10 12:52, Phlip wrote:
>> try:
>> return Model.objects.get(pk=42)
>> except Model.DoesNotExist:
>> return sentinel
>>
>> The flow of control is much clearer this way.

>
> It reminds me of Visual Basic.
>
> And no it's not "much clearer". Exceptions are for catastrophic errors
> that the caller should care not to handle. A "record not found" is not
> a catastrophe.


Exceptions are not limited to catastrophic errors, simply
exceptional (not the common) cases. E.g. iterators raising
StopException when exhausted.

>>> i = iter(range(2))
>>> i.next()

0
>>> i.next()

1
>>> i.next()

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

>>> i = iter(range(2))
>>> for v in i:

.... print v
....
0
1

Running out of things to iterate over is pretty non-catastrophic
in my book.

Using exceptions as in the grandparent's post seem perfectly fine
to me. The other option would be to LBYL:

items = list(MyModel.objects.filter(...))
if len(items) == 1:
do_something(items[0])
else:
what_the(...)

-tkc




 
Reply With Quote
 
Phlip
Guest
Posts: n/a
 
      09-07-2010
On Sep 7, 11:36*am, Tim Chase <(E-Mail Removed)> wrote:

> > And no it's not "much clearer". Exceptions are for catastrophic errors
> > that the caller should care not to handle. A "record not found" is not
> > a catastrophe.

>
> Exceptions are not limited to catastrophic errors, simply
> exceptional (not the common) cases. *E.g. iterators raising
> StopException when exhausted.


Exceptions are not "because we should only return one type of thing".
They are for situations which the caller should care not to handle.
Exceptions are for propagating. A "record not found" is an exemplary
example of a situation the caller _should_ handle.

> * *items = list(MyModel.objects.filter(...))
> * *if len(items) == 1:
> * * *do_something(items[0])
> * *else:
> * * *what_the(...)


Both your version and mine read an entire cursor. But mine only rezzed
the first object, whereas yours rezzed every object in the cursor,
just to throw most of them away!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Scythe Samurai Z Silverstrand Front Page News 0 02-08-2006 04:29 AM
Re: [Ent] From "sword master" Nick Powell to the last Samurai Tom Cruise John Doe Computer Support 0 09-16-2003 03:49 PM
[Entertainment] The Last Samurai Dzuyen Computer Support 1 09-15-2003 03:12 PM
Re: [Infor.] The Last Samurai John Doe Computer Support 0 09-15-2003 03:08 PM
[Info.] Tom Cruise in The Last Samurai Dzuyen Computer Support 1 09-15-2003 09:06 AM



Advertisments