È questa eccessiva astrazione? (E c'è un nome per questo?)

5

Lavoro su una grande applicazione Django che usa CouchDB come database e couchdbkit per mappare i documenti CouchDB in oggetti in Python, in modo simile all'ORM predefinito di Django. Ha dozzine di classi modello e cento o due visualizzazioni CouchDB.

L'applicazione consente agli utenti di registrare un "dominio", che fornisce loro un URL univoco contenente il nome di dominio che consente loro l'accesso a un progetto i cui dati non si sovrappongono ai dati di altri domini. Ogni documento che fa parte di un dominio ha la sua proprietà domain impostata sul nome di quel dominio.

Per quanto riguarda le relazioni tra i documenti, tutti i domini sono effettivamente sottoinsiemi mutuamente esclusivi dei dati, ad eccezione di alcuni casi limite (alcuni utenti possono essere membri di più di un dominio, e ci sono alcuni rapporti amministrativi che includono tutti domini, ecc.).

Il codice è pieno di riferimenti espliciti al nome di dominio, e mi chiedo se valga la pena aggiungere la complessità per estrapolarlo. Mi piacerebbe anche sapere se c'è un nome per il tipo di approccio legato alle proprietà che sto prendendo qui.

Fondamentalmente, ho in mente qualcosa di simile:

Prima

in models.py

class User(Document):
    domain = StringProperty()


class Group(Document):
    domain = StringProperty()
    name = StringProperty()
    user_ids = StringListProperty()

    # method that returns related document set
    def users(self):
        return [User.get(id) for id in self.user_ids]

    # method that queries a couch view optimized for a specific lookup
    @classmethod
    def by_name(cls, domain, name):
        # the view method is provided by couchdbkit and handles
        # wrapping json CouchDB results as Python objects, and 
        # can take various parameters modifying behavior
        return cls.view('groups/by_name', key=[domain, name])

    # method that creates a related document
    def get_new_user(self):
        user = User(domain=self.domain)
        user.save()
        self.user_ids.append(user._id)
        return user

in views.py:

from models import User, Group

# there are tons of views like this, (request, domain, ...)
def create_new_user_in_group(request, domain, group_name):
    group = Group.by_name(domain, group_name)[0]
    user = User(domain=domain)
    user.save()
    group.user_ids.append(user._id)
    group.save()

in group / by_name / map.js:

function (doc) {
    if (doc.doc_type == "Group") {
        emit([doc.domain, doc.name], null);
    }
}

Dopo

models.py

class DomainDocument(Document):
    domain = StringProperty()

    @classmethod
    def domain_view(cls, *args, **kwargs):
        kwargs['key'] = [cls.domain.default] + kwargs['key']
        return super(DomainDocument, cls).view(*args, **kwargs)

    @classmethod
    def get(cls, *args, **kwargs, validate_domain=True):
        ret = super(DomainDocument, cls).get(*args, **kwargs)

        if validate_domain and ret.domain != cls.domain.default:
            raise Exception()

        return ret

    def models(self):
        # a mapping of all models in the application. accessing one returns the equivalent of

        class BoundUser(User):
            domain = StringProperty(default=self.domain)


class User(DomainDocument):
    pass

class Group(DomainDocument):
    name = StringProperty()
    user_ids = StringListProperty()

    def users(self):
        return [self.models.User.get(id) for id in self.user_ids]

    @classmethod
    def by_name(cls, name):
        return cls.domain_view('groups/by_name', key=[name])

    def get_new_user(self):
        user = self.models.User()
        user.save()

views.py

@domain_view  # decorator that sets request.models to the same sort of object that is returned by DomainDocument.models and removes the domain argument from the URL router
def create_new_user_in_group(request, group_name):
    group = request.models.Group.by_name(group_name)
    user = request.models.User()
    user.save()
    group.user_ids.append(user._id)
    group.save()

(Potrebbe essere meglio lasciare qui l'astrazione che perde qui per evitare di dover gestire uno // stile! couchapp di un wrapper per emettere che antepone doc.domain alla chiave o qualche altra soluzione simile.)

function (doc) {
    if (doc.doc_type == "Group") {
        emit([doc.name], null);
    }
}

Pro e contro

Quindi quali sono i pro e i contro di questo?

Pro:

  • asciugatrice
  • ti impedisce di creare documenti correlati dimenticando di impostare il dominio.
  • ti impedisce di scrivere accidentalmente una vista di django - > percorso di esecuzione della visualizzazione del divano che porta a una violazione della sicurezza
  • non ti impedisce di accedere al sottostante self.domain e al normale metodo Document.view ()
  • potenzialmente elimina la necessità di un sacco di controlli di integrità verificando se due documenti i cui domini ci aspettiamo siano uguali.

Contro:

  • aggiunge una certa complessità
  • nasconde ciò che sta realmente accadendo
  • non richiede che i moduli del modello abbiano classi con lo stesso nome o che tu debba aggiungere attributi secondari a self.models per i moduli. Tuttavia, richiedere i nomi di classe univoci a livello di progetto per i modelli dovrebbe andare bene perché corrispondono alla proprietà doc_type che usa couchdbkit per decidere quale classe istanziarli come, che dovrebbe essere unica.
  • rimuove la documentazione di dipendenza esplicita (dal gruppo di importazione group.models)
posta mwhite 24.04.2013 - 03:56
fonte

1 risposta

1

Questa è davvero una domanda alla quale solo tu puoi rispondere, l'eccessiva astrazione è negli occhi di chi guarda. Il seguente è il mio modesto parere.

Per me Domain è una entità . È un'entità perché ha un'identità fondamentale per il ciclo di vita del concetto di dominio. Come tale astrazione da altri contesti è esattamente la cosa da fare, ma come il proprio oggetto di prima classe piuttosto che come parte di un'altra classe che si passa ancora in giro. Inoltre, a prima vista, mi sembra che Domain sia un'entità aggregata.

Il documento a mio parere esiste nello stesso contesto limitato del dominio, ma è un aggregato separato a cui verrà fatto riferimento solo per ID, ad es. un documento deve essere associato a un dominio ma poiché non c'è bisogno di coerenza transazionale tra i due è OK averli come aggregati separati.

    
risposta data 25.06.2013 - 19:39
fonte

Leggi altre domande sui tag