Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   The Samurai Principle (http://www.velocityreviews.com/forums/t732692-the-samurai-principle.html)

Phlip 09-07-2010 03:48 AM

The Samurai Principle
 
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

Albert Hopkins 09-07-2010 11:14 AM

Re: The Samurai Principle
 
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



Phlip 09-07-2010 01:40 PM

Re: The Samurai Principle
 
> How does that compare to, say, the "Kamikaze Principle"? ;)

Return victorious AND not at all!

(All return values are packed up and thrown...;)

geremy condra 09-07-2010 02:23 PM

Re: The Samurai Principle
 
On Tue, Sep 7, 2010 at 6:56 AM, Bruno Desthuilliers
<bruno.42.desthuilliers@websiteburo.invalid> 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

Phlip 09-07-2010 04:02 PM

Re: The Samurai Principle
 
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

Ian Kelly 09-07-2010 05:36 PM

Re: The Samurai Principle
 
On Tue, Sep 7, 2010 at 10:02 AM, Phlip <phlip2005@gmail.com> 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

Phlip 09-07-2010 05:52 PM

Re: The Samurai Principle
 
On Sep 7, 10:36*am, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> On Tue, Sep 7, 2010 at 10:02 AM, Phlip <phlip2...@gmail.com> 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.

Ian Kelly 09-07-2010 06:21 PM

Re: The Samurai Principle
 
On Tue, Sep 7, 2010 at 11:52 AM, Phlip <phlip2005@gmail.com> 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?

Tim Chase 09-07-2010 06:36 PM

Re: The Samurai Principle
 
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





Phlip 09-07-2010 06:53 PM

Re: The Samurai Principle
 
On Sep 7, 11:36*am, Tim Chase <python.l...@tim.thechases.com> 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!


All times are GMT. The time now is 11:02 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.