2010-06-26 63 views
8

假设一个类有一个修改它的内部的方法。 该方法是否应该在返回之前调用自己的保存方式,还是应该在调用修改方法后保存给调用方以显式保存?修改的类方法应该保存自己还是在方法被调用后被调用?

例子:

显式调用保存:

class Bar(models.Model): 
    def set_foo(self, foo): 
     self.foo = foo 

bar = Bar() 
bar.set_foo("foobar") 
bar.save() 

,或者允许方法调用保存:

class Bar(models.Model): 
    def set_foo(self, foo): 
     self.foo = foo 
     self.save() 

bar = Bar() 
bar.set_foo("foobar") 

我与Django的工作,但我想知道是否有一个在django或一般情况下的最佳做法。

+0

一些语法挑剔:短语“类方法”意味着一个用'@ classmethod'装饰的函数,用作类的方法而不是实例。你的问题应该只是说'修改方法'。 “自救”使得听起来像是在谈论保存方法,而不是实例;你应该说“保存'自我'”。最后,你让它听起来像方法应该被调用后再次调用。更好的可能是:“修改'self'的方法是否应该调用save()本身,还是应该save()之后被显式调用?” – Glyph 2010-06-26 19:52:07

回答

2

你的API的用户可能会忘记调用.save()然后搞砸了。所以我认为最好给他打电话保存。对于像那些Daslch提到,如果这是有道理的情况下,您可以定义:

def set_foo(self, foo, skip_save=False): 
    self.foo = foo 
    if not skip_save: 
     self.save() 

这样用户就可以,如果她希望(并明确规定),避免了保存。

+1

这似乎是最简单和最直观的解决方案。通过查看参数,用户将知道该方法正在进行保存,并且如果需要,还可以覆盖它。 – Simplecoder 2010-06-28 14:44:54

3

您的API的用户可能想进行一些更改,每次更改后保存对象都不好,所以不要,不要在您的方法中调用保存。

+0

这是最具Django风格的做事方式。保存应该明确并且在用户的控制之下。如果你想给人们一个方便的速记,你可以添加一个像'save = True'这样的kwarg ... – 2010-06-27 07:37:28

1

其实,我同意Ofri和Daslch ......这取决于它是一周中的哪一天。如果这只是您可能对特定对象执行的许多修改例程之一,那么它们将会相当昂贵,因为它们中的每一个都会自行保存。在另一方面,如果这是一个罕见的,自包含的事件,那么你要做的保存,因为它可能不是很明显给调用者(即,别人比,它需要做等。

例如,标记事件(无论如何使用ManyToMany)应该不需要在程序员部分上额外保存()

0

为了处理在各种现有答案中表达的所有问题,我建议采用以下方法:称之为savingmodifying,这是一个上下文管理器,该方法的入口设置了一个私有标志,表示修改正在进行;退出重置标志并执行保存;所有修改方法都检查f如果未设置,则会滞后并引发异常。例如,使用一个基类和save方法,真正的子类必须重写:

import contextlib 

class CarefullyDesigned(object): 

    def __init__(self): 
     self.__saving = False 

    def _save(self): 
     raise NotImplementedError('Must override `_save`!') 

    def _checksaving(self): 
     "Call at start of subclass `save` and modifying-methods" 
     if not self.__saving: raise ValueError('No saving in progress!') 

    @contextlib.contextmanager 
    def saving(self): 
     if self.__saving: raise ValueError('Saving already in progress!') 
     self.__saving = True 
     yield 
     self._save() 
     self.__saving = False 

使用例...:

class Bar(models.Model, CarefullyDesigned): 

    def __init__(self, *a, **k): 
     models.Model.__init__(self, *a, **k) 
     CarefullyDesigned.__init__(self) 

    def _save(self): 
     self._checksaving() 
     self.save() 

    def set_foo(self, foo): 
     self._checksaving() 
     self.foo = foo 

    def set_fie(self, fie): 
     self._checksaving() 
     self.fie = fie 

bar = Bar() 
with bar.saving(): 
    bar.set_foo("foobar") 
    bar.set_fie("fo fum") 

保证用户不会忘记打电话saving也不意外以嵌套的方式调用它(这是所有这些例外的目的),并且在完成修改方法组时,只需调用save一次,用一种方便的方式,并且我相当自然地说。