Должен ли метод модифицирующего класса сохранить себя или быть вызванным явным образом после вызова метода? - PullRequest
8 голосов
/ 26 июня 2010

Предположим, что у класса есть метод, который модифицирует его внутренности.Должен ли этот метод вызывать save для себя перед возвратом, или следует оставить сохранение вызывающей стороне для явного сохранения после вызова модифицирующего метода?

Пример:

Явный вызов save:

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

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

или разрешающий метод для вызова save:

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

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

Я работаю с django, но мне было интересно, есть ли лучшая практика в django или вообще для этой ситуации.

Ответы [ 4 ]

3 голосов
/ 26 июня 2010

Пользователь вашего API может захотеть внести несколько изменений, сохраняя объект после каждого изменения, но это не хорошо, так что нет, не вызывайте save в вашем методе.

2 голосов
/ 27 июня 2010

Пользователь вашего API может забыть вызвать .save (), а затем облажаться.Поэтому я думаю, что лучше позвонить сохранить для него.Для случаев, подобных тем, о которых упоминает Daslch, если это имеет смысл, вы можете определить:

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

, чтобы пользователь мог, если он хочет (и прямо заявляет об этом), избежать сохранения.

1 голос
/ 27 июня 2010

На самом деле, я согласен с Офри и Даслчем ... в зависимости от того, какой сегодня день недели.Если это всего лишь одна из многих процедур модификации, которые вы можете выполнить для конкретного объекта, то это будет довольно дорого, если каждая из них сделает свое собственное сохранение.С другой стороны, если это редкое, автономное событие, то вы хотите выполнить сохранение, поскольку для вызывающего абонента может быть неочевидно (т. Е. Для кого-то, кроме вас , что это необходимо сделать.

Например, тегирование событий (которые все равно используют ManyToMany) не должно требовать дополнительного сохранения () для программистов.

0 голосов
/ 27 июня 2010

Для решения всех проблем, выраженных в различных существующих ответах, я предлагаю следующий подход: создайте метод, назовите его скажем saving или modifying, который является менеджером контекста.Запись в этот метод устанавливает закрытый флаг, который говорит, что модификация выполняется;выход сбрасывает флаги и выполняет сохранение;все модифицирующие методы проверяют флаг и вызывают исключение, если не установлено.Например, при использовании базового класса и метода 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 только один раз, когда группа методов-модификаторов готова, в удобной искажем, довольно естественным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...