Come si gestisce la logica di dominio che si estende su più oggetti del modello in un ORM?

3

Quindi so che la logica aziendale dovrebbe essere inserita nel modello. Ma usando un ORM non è così chiaro dove dovrei posizionare il codice che gestisce più oggetti.

es. diciamo che abbiamo un modello Customer che ha un type di sporty o posh e abbiamo voluto customer.add_bonus() per ogni cliente posh. Dove lo faremmo? Creiamo una nuova classe per gestire tutto questo? Se sì, dove lo mettiamo (insieme a tutte le altre classi di modelli, ma non la sottoclassi dall'ORM?)?

Attualmente sto usando il framework django in python, quindi i suggerimenti specifici sono ancora più ricercati.

    
posta duality_ 26.05.2014 - 14:36
fonte

1 risposta

4

In generale, dipende dalla tua architettura. Dato che usi il django, è naturale percorrere il percorso del django dei modelli grassi.

Non è chiaro dal tuo esempio quando desideri customer.add_bonus (), ma un approccio che puoi adottare è modellare clienti eleganti e sportivi come classi diverse utilizzando l'ereditarietà. per es.

class Customer(models.Model):
  pass

class PoshCustomer(Customer):
  def discount(self):
    self.add_bonus()

  class Meta:
    proxy = True

class SportyCustomer(Customer):
  def discount(self):
    pass

  class Meta:
    proxy = True

Qui stiamo usando le classi proxy di Django ( link ) a indica che questi clienti sono memorizzati nella stessa tabella del database e solo il comportamento è diverso.

Aggiornamento:

I tuoi commenti qui sotto sono stati presi in considerazione, ti consiglio di non bloccarti in una decisione architetturale finché non ne sai di più sui tuoi casi d'uso. Continuando sul tuo ultimo commento, sembra che tu abbia un comportamento che è principalmente diviso in due:

  • Identificazione di un gruppo di clienti
  • Applicazione di un'azione ai clienti del gruppo identificato.

Probabilmente modellerei questo come due concetti diversi e li uniamo insieme con i servizi case-aligned usati.

L'identificazione dei gruppi di clienti può essere incapsulata utilizzando un gestore di modelli personalizzato. ( link ). Per es.

class CustomerManager(models.Manager):
  def made_purchase_in(self, timespan):
    return self.filter(last_purchase__in=timespan)

Le azioni possono essere modellate in qualsiasi modo tu voglia, ad es. come metodi sul Cliente o come classi o funzioni che accettano i clienti come parametri:

class Customer(model.Model):
  ..
  def remind(self, email):
    self.send_mail(email)

o

class RegularCustomerReminder:
  def __init__(self, customers):
    self.customers = customers

  def remind(self):
    for customer in self.customers:
      customer.send_email(self.make_reminder())

E un servizio di esempio:

class CustomerPromotionService:
  def send_promotion(self):
    customers = Customer.objects.made_purchase_in(timespan.LAST_30_DAYS)
    reminder = RegularCustomerReminder(customers)
    reminder.remind()
    
risposta data 26.05.2014 - 16:19
fonte

Leggi altre domande sui tag