SOLID principi in questa classe

3

Voglio chiedere ad esperti sviluppatori e architetti di software su questa classe di dominio che ho trovato un giorno in qualche codice.

public class User : Entity
{
    public virtual string Firstname { get; set; }
    public virtual string Lastname { get; set; }
    public User(string firstName, string lastName, IUserRepository userRepository, IUserService userService)
    {
        Firstname = firstName;
        Lastname = lastName
        userRepository.Save(this);
        userService.DoSomeStaff(this);
    }
}

Cosa pensi dei principi SOLID in particolare per quanto riguarda il costruttore? Penso che rompa almeno il principio della singola responsabilità, perché:

  1. il costruttore inizializza l'oggetto e
  2. salva l'oggetto nel DB utilizzando un repository e
  3. fa cose usando un servizio.

Forse c'è qualche architettura di progetto che consiglia questo stile di codice?

Ecco le definizioni per il repository e il servizio coinvolti:

public class UserRepository : IUserRepository
{
    // some code of repository pattern with Nhibernate
    public void Save(User user)
    {
        //here Session is Nhibernate.ISession
        Session.SaveOrUpdate(user); 
    }
}

public class UserService : IUserService
{
    private readonly ISomeName1Repository _someName1Repository;
    private readonly ISomeName2Repository _someName2Repository;
    public UserService(ISomeName1Repository someName1Repository, ISomeName2Repository someName2Repository)
    {
        _someName1Repository = someName1Repository;
        _someName2Repository = someName2Repository;
    }

    public void DoSomeStaff(User user)
    {
        var foo = _someName1Repository.DoSomeStaff();
        // some work here with user
    }
}
    
posta Stanislav Machel 16.11.2017 - 17:13
fonte

3 risposte

3

What you think about SOLID principles

Bene, almeno il costruttore usa l'iniezione delle dipendenze, quindi la D di SOLID viene applicata qui, immagino? ;-) Ma presumo che la tua domanda riguardi l'SRP, non riguardo a SOLID in generale.

Quindi per essere seri, questo design mi sembra come se qualcuno volesse avere un "callback" o "hook" da chiamare ogni volta che viene creato un oggetto User (probabilmente con l'intenzione speciale di assicurarsi che l'oggetto esista anche in un repository o un altro servizio è informato sulla creazione degli oggetti).

In realtà, penso che sia discutibile se questo violi realmente l'SRP, (poiché sarà facile annullare una chiamata come userRepository.Save passando un repository fittizio). Per questo motivo, i due parametri aggiuntivi non proibiscono il test o il riutilizzo dell'unità di quella classe in un contesto in cui il repo e / o il servizio non sono necessari (il che sarebbe un chiaro segno di violazione dell'SRP).

Tuttavia, penso che questo violi il più fondamentale principio KISS. Le interfacce iniettate rendono il codice chiamante più complicato. Non vediamo l'intero codice circostante, ma IMHO è (quasi) sempre possibile mantenere gli oggetti del dominio completamente puliti da eventuali callback o chiamate di servizio e lasciare che l'ambiente circostante gestisca queste cose. Secondo la mia esperienza, ciò porterà a un sistema che è nel complesso più semplice, più facile da capire e più facile da mantenere.

    
risposta data 18.11.2017 - 14:41
fonte
1

I costruttori sono un'area grigia qui. Non mi farei prendere dalla correttezza che implica per l'oggetto circostante. Lo stesso vale per gli inizializzatori statici e i metodi di produzione statici. Concentrati invece sui metodi di istanza dell'oggetto.

Se sei preoccupato che il bloat si infiltra negli inizializzatori, sposta il codice ad es. in un framework di iniezione delle dipendenze.

    
risposta data 16.11.2017 - 18:44
fonte
1

Il punto di SRP riguarda non implementare più di una responsabilità nella stessa classe. La classe di esempio stessa è solo un contenitore per nome e cognome, non ha più dati e non ha più logica / comportamento. Può richiamare altri oggetti per eseguire compiti diversi, ma tali compiti non sono implementati nella classe User, quindi da una prospettiva SRP ciò è perfettamente corretto.

    
risposta data 16.11.2017 - 21:13
fonte

Leggi altre domande sui tag