2012-03-14 12 views
15

Principalmente per curiosità, sto cercando un framework Python o un esempio per il pattern del repository di disaccoppiamento della logica di persistenza dalla logica del dominio.Implementazione del pattern di repository in Python?

Il nome "Pattern Repository" appare nel post "Untangle Domain and Persistence Logic with Curator" (Ruby), idea nasce da un section del libro "Domain-Driven Design" e Martin Fowler. La classe del modello non contiene alcuna logica di persistenza, ma l'app dichiara sottoclassi di repository le cui istanze si comportano come raccolte in memoria di istanze di modelli. Ogni repository persiste nel modello in diversi modi, ad esempio in SQL (varie convenzioni dello schema), in Riak o in altri noSQL e in memoria (per la memorizzazione nella cache). Le convenzioni del framework significano che le sottoclassi di repository richiedono in genere un codice minimo: solo la sottoclasse "WidgetRepository" di SQLRepository fornirebbe una raccolta che persiste il modello Widget nella tabella DB denominata "widget" e corrisponde alle colonne agli attributi del widget.

Differenze da altri modelli:

attivo Registra modello: per esempio, Django ORM. L'applicazione definisce solo la classe del modello con logica di dominio e alcuni metadati per la persistenza. L'ORM aggiunge la logica di persistenza alla classe del modello. Questo mescola dominio e persistenza in una classe (indesiderabile secondo il post).

Grazie a @marcin, vedo che quando Active Record supporta diversi backend e la funzione .save (using = "other_database"), fornisce il vantaggio multi-backend del Pattern di repository.

Quindi, in un certo senso, Repository Pattern è proprio come Active Record con la logica di persistenza spostata in una classe separata.

Data Mapper modello: per esempio, Mapping classici di SQLAlchemy. L'app definisce classi aggiuntive per le tabelle del database e i dati del/i mappatore/i dal modello al/i tabella/i. Pertanto l'istanza del modello può essere mappata a tabelle in diversi modi, ad es. per supportare schemi legacy. Non pensare che SQLAlchemy fornisca i mapping a storage non SQL.

+0

cosa fa la vostra ricerca suggerisce? Ho facilmente cercato su Google un certo numero di alternative. – Marcin

+0

Cerca su google per il modello di repository 'python" "non mostra alcuna implementazione. Che cosa hai cercato esattamente? – Graham

+0

http://www.google.co.uk/search?q=django+orm+backend – Marcin

risposta

1

Si potrebbe desiderare di avere una buona occhiata a James Dennis' DictShield project

"DictShield è un sistema di modellazione di database agnostico. Esso fornisce un modo per modellare, convalidare e rimodellare facilmente i dati. Il tutto senza richiedere alcuna particolare database ".

+0

DictShield fornisce aiutanti per la modellazione, la validazione, la relazione dei modelli. Repository Pattern fornirebbe classi di raccolta per vari backend. – Graham

7

Fuori dalla mia testa:

definisco due domini esempio, User e Animal, una classe di archiviazione di base Store e due classi di archiviazione specializzati UserStore e AnimalStore. L'uso del contesto responsabile chiude la connessione db (per semplicità io uso SQLite in questo esempio):

import sqlite3 

def get_connection(): 
    return sqlite3.connect('test.sqlite') 

class StoreException(Exception): 
    def __init__(self, message, *errors): 
     Exception.__init__(self, message) 
     self.errors = errors 


# domains 

class User(): 
    def __init__(self, name): 
     self.name = name 


class Animal(): 
    def __init__(self, name): 
     self.name = name 


# base store class 
class Store(): 
    def __init__(self): 
     try: 
      self.conn = get_connection() 
     except Exception as e: 
      raise StoreException(*e.args, **e.kwargs) 
     self._complete = False 

    def __enter__(self): 
     return self 

    def __exit__(self, type_, value, traceback): 
     # can test for type and handle different situations 
     self.close() 

    def complete(self): 
     self._complete = True 

    def close(self): 
     if self.conn: 
      try: 
       if self._complete: 
        self.conn.commit() 
       else: 
        self.conn.rollback() 
      except Exception as e: 
       raise StoreException(*e.args) 
      finally: 
       try: 
        self.conn.close() 
       except Exception as e: 
        raise StoreException(*e.args) 


# store for User obects 
class UserStore(Store): 

    def add_user(self, user): 
     try: 
      c = self.conn.cursor() 
      # this needs an appropriate table 
      c.execute('INSERT INTO user (name) VALUES(?)', (user.name,)) 
     except Exception as e: 
      raise StoreException('error storing user') 


# store for Animal obects 
class AnimalStore(Store): 

    def add_animal(self, animal): 
     try: 
      c = self.conn.cursor() 
      # this needs an appropriate table 
      c.execute('INSERT INTO animal (name) VALUES(?)', (animal.name,)) 
     except Exception as e: 
      raise StoreException('error storing animal') 

# do something 
try: 
    with UserStore() as user_store: 
     user_store.add_user(User('John')) 
     user_store.complete() 

    with AnimalStore() as animal_store: 
     animal_store.add_animal(Animal('Dog')) 
     animal_store.add_animal(Animal('Pig')) 
     animal_store.add_animal(Animal('Cat')) 
     animal_store.add_animal(Animal('Wolf')) 
     animal_store.complete() 
except StoreException as e: 
    # exception handling here 
    print(e) 
+0

Sì, questo implementa il modello di repository. In una libreria che lo fornisce, mi auguro che ogni back-end di storage fornisca una strategia predefinita per mappare i modelli allo storage, quindi non è richiesto alcun SQL scritto a mano. – Graham

+1

@graham [SQLAlchemy] (http://www.sqlalchemy.org/) potrebbe essere quello che vuoi, ma non è leggero, vedi [SQLAlchemy session] (http://docs.sqlalchemy.org/en/latest/orm /session.html). – laurasia

+0

È possibile utilizzare questo approccio per far funzionare i repository. Per gli agnostici di database basta usare [SQLAlchemy] (http://www.sqlalchemy.org/) per implementare gli interni. – famousgarkin

Problemi correlati