2010-06-26 21 views
8

Supongamos que una clase tiene un método que modifica su funcionamiento interno. ¿Debería ese método llamar a guardar en sí mismo antes de regresar o debería guardarse para que la persona que llama guarde explícitamente después de haber llamado al método de modificación?¿Debería un método de clase modificadora guardarse o ser llamado explícitamente después de llamar al método?

Ejemplo:

Explícitamente llamar a save:

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

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

o permitiendo método para llamar a ahorrar:

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

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

estoy trabajando con Django, pero me preguntaba si había una las mejores prácticas en django o en general para esta situación.

+0

Algunos nitidez de gramática: La frase "método de clase" implica una función decorada con '@ classmethod', que se utiliza como un método en la clase en lugar de una instancia. Tu pregunta probablemente debería simplemente decir 'método de modificación'. 'guardarse' hace que parezca que estás hablando de guardar el método, en lugar de la instancia; usted debe decir "guardarse" '. Finalmente, lo hace sonar como si el método se llamara nuevamente después de ser llamado.Mejor podría ser: "¿Debería un método que modifica 'auto' llamar a save() en sí mismo, o debería guardar() explícitamente después?" – Glyph

Respuesta

2

El usuario de su API puede olvidarse de llamar a .save() y luego ser atornillado. Entonces creo que es mejor llamar a salvarlo. Para casos como los Daslch menciona, si tiene sentido, puede definir:

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

por lo que el usuario puede, si lo desea (y explícitamente establece que), evitar el salve.

+1

Esta parece ser la solución más simple e intuitiva. Al observar los argumentos, el usuario sabrá que está ocurriendo un guardado en el método y también podrá anularlo si surge la necesidad. – Simplecoder

3

El usuario de su API podría querer hacer varios cambios, guardando el objeto después de que cada cambio sea cualquier cosa menos bueno, así que no, no llame a guardar en su método.

+0

Esta es la forma más Django de hacer las cosas. El ahorro debe ser explícito y estar bajo el control del usuario. Quizás podrías agregar un kwarg como 'save = True' al método si quisieras darle a la gente una taquigrafía conveniente ... –

1

En realidad, estoy de acuerdo con Ofri y Daslch ... dependiendo de qué día de la semana es. Si esta es solo una de las muchas rutinas de modificación que podría hacerle a un objeto en particular, entonces será bastante caro que cada uno de ellos haga su propio ahorro. Por otro lado, si se trata de un evento raro e independiente, entonces debe guardar porque no es obvio para la persona que llama (es decir, alguien que no sea que debe hacerse.

Por ejemplo, los eventos de etiquetado (que usan ManyToMany de todos modos) no requieren guardar adicional() en la parte de programadores

0

Para tratar todos los problemas expresados ​​en varias respuestas existentes, sugiero el siguiente enfoque: crear un método, llamarlo decir saving o modifying, que es un administrador de contexto. La entrada a ese método establece una bandera privada que dice que la modificación está en progreso; la salida restablece los indicadores y realiza el guardado; todos los métodos de modificación verifican rezagar y generar una excepción si no se establece. Por ejemplo, el uso de una clase base y un método que save subclases reales deben prevalecer:

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 

Ejemplo del uso ...:

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") 

Esto garantiza que el usuario no se olvide de llamar saving ni accidentalmente llámalo de forma anidada (ese es el propósito de todas esas excepciones), y llama al save solo una vez cuando el grupo de métodos modificadores esté hecho, de una forma práctica y, diría, bastante natural.

Cuestiones relacionadas