2012-03-14 16 views
15

मुख्य रूप से जिज्ञासा से बाहर, मैं डोमेन लॉजिक से decoupling दृढ़ता तर्क के रिपोजिटरी पैटर्न के लिए एक पायथन ढांचे या उदाहरण की तलाश में हूं।पायथन में रिपोजिटरी पैटर्न का कार्यान्वयन?

नाम "भंडार पैटर्न" (रूबी) पोस्ट "Untangle Domain and Persistence Logic with Curator" में प्रकट होता है, विचार "डोमेन संचालित डिजाइन" पुस्तक की एक section और Martin Fowler से आता है। मॉडल क्लास में कोई दृढ़ता तर्क नहीं है, बल्कि ऐप रिपोजिटरी उप-वर्गों की घोषणा करता है जिनके उदाहरण मॉडल उदाहरणों के इन-मेमोरी संग्रह की तरह कार्य करते हैं। प्रत्येक भंडार मॉडल को अलग-अलग तरीकों से बना देता है, उदाहरण के लिए एसक्यूएल (विभिन्न स्कीमा सम्मेलन), रीक या अन्य नोएसक्यूएल और मेमोरी (कैशिंग के लिए) के लिए। फ्रेमवर्क सम्मेलनों का मतलब है कि रिपॉजिटरी उप-वर्गों को आम तौर पर न्यूनतम कोड की आवश्यकता होती है: केवल SQLRepository के "विजेट रिपोजिटरी" उप-वर्ग को घोषित करना एक संग्रह प्रदान करेगा जो "विजेट" नामक डीबी तालिका में मॉडल विजेट को जारी रखता है और विजेट विशेषताओं के लिए कॉलम मिलान करता है। अन्य पैटर्न से

अंतर:

सक्रिय रिकॉर्ड पैटर्न: उदाहरण के लिए, Django ORM। एप्लिकेशन केवल डोमेन तर्क के साथ मॉडल वर्ग और दृढ़ता के लिए कुछ मेटाडेटा परिभाषित करता है। ओआरएम मॉडल वर्ग में दृढ़ता तर्क जोड़ता है। यह एक वर्ग में डोमेन और दृढ़ता को मिश्रित करता है (पोस्ट के अनुसार अवांछनीय)।

@marcin के लिए धन्यवाद मैं देखता हूं कि जब सक्रिय रिकॉर्ड विविध बैकएंड और .save (= "other_database" का उपयोग करके) का समर्थन करता है, जो रिपोजिटरी पैटर्न का बहु बैकएंड लाभ देता है।

तो एक अर्थ में रिपोजिटरी पैटर्न एक अलग वर्ग में स्थानांतरित होने के साथ सक्रिय रिकॉर्ड की तरह है।

डाटा मैपर पैटर्न: उदाहरण के लिए, SQLAlchemy के शास्त्रीय मैपिंग। ऐप डेटाबेस तालिका (एस) के लिए अतिरिक्त कक्षाओं को परिभाषित करता है, और डेटा मैपर (ओं) से मॉडल से टेबल तक। इस प्रकार मॉडल उदाहरण को कई तरीकों से तालिकाओं में मैप किया जा सकता है उदा। विरासत स्कीमा का समर्थन करने के लिए। ऐसा नहीं लगता कि SQLAlchemy गैर-SQL स्टोरेज में मैपर प्रदान करता है।

+0

आपके शोध से क्या पता चलता है? मैंने बस कई विकल्पों को आसानी से गुगल किया। – Marcin

+0

'पायथन "भंडार पैटर्न के लिए गुगलिंग" 'कोई कार्यान्वयन नहीं करता है। आपने वास्तव में क्या खोजा? – Graham

+0

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

उत्तर

1

आप अच्छी तरह से देखने के लिए चाहते हो सकता है जेम्स डेनिस 'DictShield project

"DictShield एक डेटाबेस-नास्तिक मॉडलिंग प्रणाली है। यह सभी किसी विशेष डेटाबेस की आवश्यकता के बिना आसानी से मॉडल को मान्य और नयी आकृति प्रदान आंकड़ों के। एक तरीका प्रदान करता । "

+0

डिक्टशील्ड मॉडलिंग से संबंधित मॉडलिंग, सत्यापन, सहायक के लिए सहायक प्रदान करता है। रिपोजिटरी पैटर्न विभिन्न बैकएंडों के लिए संग्रह-जैसी कक्षाएं प्रदान करेगा। – Graham

7

मेरे सिर से बाहर:

मैं दो उदाहरण डोमेन, User और Animal, एक आधार भंडारण वर्ग Store और दो विशेष भंडारण वर्गों UserStore और AnimalStore परिभाषित करते हैं। संदर्भ प्रबंधक का उपयोग डीबी कनेक्शन बंद करता है (सादगी के लिए मैं इस उदाहरण में एसक्लाइट का उपयोग करता हूं):

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

हां, यह रिपोजिटरी पैटर्न को कार्यान्वित करता है। इसे प्रदान करने वाली लाइब्रेरी में, मैं आशा करता हूं कि प्रत्येक स्टोरेज बैकएंड के लिए मॉडलों को स्टोरेज में मैप करने के लिए एक डिफ़ॉल्ट रणनीति प्रदान की जाए, इसलिए कोई हस्तलिखित एसक्यूएल आवश्यक नहीं है। – Graham

+1

@ ग्राहम [SQLAlchemy] (http://www.sqlalchemy.org/) हो सकता है जो आप चाहते हैं, लेकिन यह हल्का नहीं है, [SQLAlchemy सत्र] देखें (http://docs.sqlalchemy.org/en/latest/orm /session.html)। – laurasia

+0

रिपोजिटरी काम करने के लिए आप निश्चित रूप से इस दृष्टिकोण का उपयोग कर सकते हैं। डेटाबेस अज्ञेयकों के लिए आंतरिक [आंतरिक] को लागू करने के लिए बस [SQLAlchemy] (http://www.sqlalchemy.org/) का उपयोग करें। – famousgarkin

संबंधित मुद्दे