Come riutilizzare la logica del modello di dominio nei servizi?

2

Sto cercando di evitare modelli di dominio anemici perché si dice che sia un anti-pattern. Ma così facendo lascia i miei servizi per duplicare parte della logica.

class User
{
    public $status;

    public function ban()
    {
        $this->status = 'banned';
    }
}

Ora, un servizio di divieto consente di escludere gli utenti solo con l'id dell'utente, quindi non è necessario recuperare l'intero modello.

class BanService()
{
    public function __construct(IUserRepo $userRepo)
    {
        $this->userRepo = $userRepo;
    }

    public function banUser($userId)
    {
        $this->userRepo->update($userId, ['status' => 'banned'])
    }
}

Qual è lo schema comunemente usato per affrontare questo?

    
posta Denis Pshenov 26.07.2015 - 17:47
fonte

3 risposte

2

Chiamerei il metodo di un oggetto dall'altra, per evitare la replica del codice.

Troverei un modo per farlo in questo modo:

class BanService()
{
    public function __construct(IUserRepo $userRepo)
    {
        $this->userRepo = $userRepo;
    }

    public function banUser($userId)
    {
        $this->userRepo->getUser($userId)->ban()
    }
}

o in altro modo (forse meglio, se c'è bisogno di banService):

class User
{
    public function ban()
    {
        // get your banService instance, which could be a singleton and put it in $ban_service
        $ban_service->banUser($this->userId)
    }
}
    
risposta data 26.07.2015 - 19:01
fonte
1

Implementerei una classe BanCommand, che si occupa di questo. I modelli di dominio non devono necessariamente avere uno stato; a volte rappresentano azioni che prendono dati e fanno qualcosa. Anche questo è abbastanza normale OO; gli oggetti sono comportamento + stato, ma a volte gli oggetti non hanno realmente bisogno di uno stato per fare qualcosa di utile. Ecco perché elenco sempre il comportamento prima dello stato quando descrivo OO; la cosa vera è il comportamento che stai cercando di modellare. Lo stato è solo lì per abilitare il comportamento che l'utente desidera.

Non vedo alcun problema solo usando direttamente questa classe, proprio come faresti con qualsiasi altro modello di dominio. Si potrebbe avere un metodo Ban su Utente che delega al comando, ma questo sarebbe solo per comodità (diciamo che stai già modificando un utente e vuoi avere un pulsante Ban). Qualsiasi cosa tu finisca, sarà guidata dai tuoi esatti casi d'uso.

    
risposta data 27.07.2015 - 17:14
fonte
0

L'approccio che ho usato alcune volte (non sono sicuro che sia consigliato o meno) è il seguente:

  • Codifica della business logic in classi di business logic dedicate
  • Le tue entità utilizzano queste classi di business logic in modo che non siano anemiche
    • Che siano iniettati in costruzione o semplicemente istanziati direttamente dipende da te.
  • Ogni volta che ho bisogno della logica di business di una determinata entità senza un'istanza dell'entità stessa, utilizzo le corrispondenti classi di business logic.

Non l'ho mai usato in un'applicazione su larga scala, quindi non so se ha delle limitazioni importanti. In altre parole, YMMV.

    
risposta data 26.07.2015 - 18:16
fonte

Leggi altre domande sui tag