Suppose a class has a method that modifies it's internals. Should that method call save on itself before returning or should the save be left to the caller to explicitly save after the modifying method has been called?
假设一个类有一个修改它内部的方法。该方法应该在返回之前调用自身保存还是应该在调用修改方法后将保存留给调用者显式保存?
Example:
例:
Explicitly calling save:
明确地调用save:
class Bar(models.Model):
def set_foo(self, foo):
self.foo = foo
bar = Bar()
bar.set_foo("foobar")
bar.save()
or allowing method to call save:
或允许方法调用save:
class Bar(models.Model):
def set_foo(self, foo):
self.foo = foo
self.save()
bar = Bar()
bar.set_foo("foobar")
I'm working with django, but I was wondering if there was a best practice in django or in general for this situation.
我正在和django一起工作,但我想知道django或者这种情况下是否有最好的练习。
4 个解决方案
#1
2
The user of your API might forget to call .save() and then get screwed. So I think its better to call save for him. For cases like those Daslch mentions, if it makes sense, you can define:
API的用户可能忘记调用.save()然后搞砸了。所以我认为最好为他打电话。对于Daslch提到的案例,如果有意义,你可以定义:
def set_foo(self, foo, skip_save=False):
self.foo = foo
if not skip_save:
self.save()
so the user can, if she wishes to (and explicitly states that), avoid the save.
因此,如果用户愿意(并明确说明),用户可以避免保存。
#2
3
The user of your API might want to make several changes, saving the object after every change is anything but good so no, don't call save in your method.
您的API的用户可能希望进行多项更改,在每次更改之后保存对象都是好的,所以不要,不要在方法中调用save。
#3
1
Actually, I agree with both Ofri and Daslch ... depending on what day of the week it is. If this is just one of many modification routines you might do to a particular object, then it will get quite expensive having each of them do their own save. On the other hand, if this is a rare, self-contained event then you want to do the save because it may not be obvious to the caller (ie, someone other than you that it needs to be done.
实际上,我同意Ofri和Daslch ......取决于一周中的哪一天。如果这只是您可能对特定对象执行的许多修改例程之一,那么每个修改例程都会自行保存。另一方面,如果这是一个罕见的,自包含的事件,那么你想要进行保存,因为它对调用者来说可能并不明显(即,除了你以外的其他人需要完成它。
For example, tagging events (which use ManyToMany anyway) should require no additional save() on the programmers part.
例如,标记事件(无论如何都使用ManyToMany)应该不需要程序员部分的额外save()。
#4
0
To deal with all the issues expressed in various existing answers, I suggest the following approach: make a method, call it say saving
or modifying
, that is a context manager. The entry to that method sets a private flag which says the modification is in progress; the exit resets the flags and performs the saving; all modifying methods check the flag and raise an exception if not set. For example, using a base class and a save
method that real subclasses must override:
为了处理各种现有答案中表达的所有问题,我建议采用以下方法:创建一个方法,称之为保存或修改,即上下文管理器。该方法的条目设置一个私有标志,表示修改正在进行中;出口重置标志并执行保存;所有修改方法都检查标志,如果没有设置则引发异常。例如,使用实际子类必须覆盖的基类和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
Example use...:
使用示例......:
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")
This guarantees the user won't forget to call saving
nor accidentally call it in a nested way (that's the purpose of all of those exceptions), and call save
only once when the group of modifying-methods is done, in a handy and, I'd say, pretty natural way.
这保证了用户不会忘记调用保存,也不会意外地以嵌套方式调用它(这是所有这些异常的目的),并且在完成修改方法组时只调用一次,方便的,我会说,非常自然的方式。
#1
2
The user of your API might forget to call .save() and then get screwed. So I think its better to call save for him. For cases like those Daslch mentions, if it makes sense, you can define:
API的用户可能忘记调用.save()然后搞砸了。所以我认为最好为他打电话。对于Daslch提到的案例,如果有意义,你可以定义:
def set_foo(self, foo, skip_save=False):
self.foo = foo
if not skip_save:
self.save()
so the user can, if she wishes to (and explicitly states that), avoid the save.
因此,如果用户愿意(并明确说明),用户可以避免保存。
#2
3
The user of your API might want to make several changes, saving the object after every change is anything but good so no, don't call save in your method.
您的API的用户可能希望进行多项更改,在每次更改之后保存对象都是好的,所以不要,不要在方法中调用save。
#3
1
Actually, I agree with both Ofri and Daslch ... depending on what day of the week it is. If this is just one of many modification routines you might do to a particular object, then it will get quite expensive having each of them do their own save. On the other hand, if this is a rare, self-contained event then you want to do the save because it may not be obvious to the caller (ie, someone other than you that it needs to be done.
实际上,我同意Ofri和Daslch ......取决于一周中的哪一天。如果这只是您可能对特定对象执行的许多修改例程之一,那么每个修改例程都会自行保存。另一方面,如果这是一个罕见的,自包含的事件,那么你想要进行保存,因为它对调用者来说可能并不明显(即,除了你以外的其他人需要完成它。
For example, tagging events (which use ManyToMany anyway) should require no additional save() on the programmers part.
例如,标记事件(无论如何都使用ManyToMany)应该不需要程序员部分的额外save()。
#4
0
To deal with all the issues expressed in various existing answers, I suggest the following approach: make a method, call it say saving
or modifying
, that is a context manager. The entry to that method sets a private flag which says the modification is in progress; the exit resets the flags and performs the saving; all modifying methods check the flag and raise an exception if not set. For example, using a base class and a save
method that real subclasses must override:
为了处理各种现有答案中表达的所有问题,我建议采用以下方法:创建一个方法,称之为保存或修改,即上下文管理器。该方法的条目设置一个私有标志,表示修改正在进行中;出口重置标志并执行保存;所有修改方法都检查标志,如果没有设置则引发异常。例如,使用实际子类必须覆盖的基类和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
Example use...:
使用示例......:
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")
This guarantees the user won't forget to call saving
nor accidentally call it in a nested way (that's the purpose of all of those exceptions), and call save
only once when the group of modifying-methods is done, in a handy and, I'd say, pretty natural way.
这保证了用户不会忘记调用保存,也不会意外地以嵌套方式调用它(这是所有这些异常的目的),并且在完成修改方法组时只调用一次,方便的,我会说,非常自然的方式。