Quando è appropriato usare l'ereditarietà [duplicato]

0

Recentemente ho avuto un piccolo "argomento" sull'eredità con un amico. Penso che la gente la usi eccessivamente. L'intuizione mi dice che l'unica buona ragione per l'ereditarietà delle classi è il polimorfismo - quando c'è un caso in cui si desidera trattare un oggetto univoco di classi diverse ma correlate.

Il nostro argomento riguardava l'avere una classe BaseEntity per Entity Framework che ha solo la proprietà Id. Il mio amico dice che va bene perché può avere archivi generici allora. W non sono d'accordo con lui.

  1. Di solito non esiste un repository generico, finirai con l'odore di "Rifiuto lascito".
  2. Qual è il modo di trattare diciamo un utente e una fattura in modo univoco? Queste sono 2 cose completamente diverse.

Purtroppo non sono riuscito a fare punti positivi nonostante "non abbia senso". :)

Dopo un po 'ho anche capito che mi sono allontanato dall'ereditarietà stessa e ora tendo ad usare le interfacce. In realtà nel mio recente progetto web (abbastanza grande) non riesco a ricordare alcuna eredità. Ora non sono più sicuro quando è una tecnica appropriata.

Quindi ragazzi, per favore aiutatemi qui.

  1. Cosa ne pensi di ciò che ho scritto?
  2. Riesci a trovare argomenti che posso usare contro il mio amico?
  3. Quando è davvero una buona pratica usare l'ereditarietà? (Si prega di essere specifici e lanciare alcuni esempi)

Per favore non provare a spiegarmi di cosa tratta l'eredità. Conosco molto questo e l'ho usato molto. Come ho detto sopra, nel tempo mi sono semplicemente allontanato da esso, perché non riuscivo a trovare il giusto uso per questo. Semplicemente le interfacce sembrano essere un approccio migliore per me nella maggior parte dei casi.

    
posta Andrzej Gis 04.04.2014 - 23:12
fonte

1 risposta

1

Come te, tendo a favorire la composizione sull'eredità. Tuttavia, ti faccio un esempio in cui trovo che l'ereditarietà funzioni davvero bene ...

Supponiamo che tu abbia una schermata in cui stai modificando un elenco di User s. Quindi hai un'entità chiamata User che è il tuo oggetto di persistenza. Quindi preferisco presentare un modello appiattito di questo alla mia interfaccia utente per la modifica, dato che di solito c'è una logica extra e controlli in corso:

class User
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
}

interface IEditUser
{
    string Name { get; set; }
    DateTime DateOfBirth { get; set; }
    int Age { get; }
    void CommitChanges();
    void Delete();
}

Ora, quando è in corso la modifica, è necessario caricare l'elenco di User s con i valori iniziali, lasciarli modificare e quindi è possibile scegliere se salvare o annullare tali modifiche. Poiché la gestione di un User appena creato è molto diversa dalla gestione di un User esistente (alcuni campi vengono modificati solo in una di queste situazioni, il codice per la loro persistenza è diverso, ecc.). Ecco perché mi piace fare questo:

abstract class EditUserBase : IEditUser
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public int Age { get { return DateTime.Today.Year - this.DateOfBirth.Year; } }
    public abstract void CommitChanges();
    public abstract void Delete();
}

Poi la mia classe per rintracciare i nuovi utenti aggiunti alla lista (ma non salvati nel database):

class EditNewUser : EditUserBase
{
    public EditNewUser()
    {
        this.Name = string.Empty;
        this.DateOfBirth = DateTime.Today;
    }

    public override void CommitChanges()
    {
        var user = new User()
            {
                Name = this.Name,
                DateOfBirth = this.DateOfBirth,
            };
        // persist to database
    }

    public override void Delete() {} // nothing to do
}

... e infine una classe per tenere traccia delle modifiche alle entità esistenti:

class EditExistingUser : EditUserBase
{
    private readonly User existingUser;

    public EditExistingUser(User existingUser)
    {
        this.existingUser = existingUser;
        this.Name = existingUser.Name;
        this.DateOfBirth = existingUser.DateOfBirth;
    }

    public override void CommitChanges()
    {
        this.existingUser.Name = this.Name;
        this.existingUser.DateOfBirth = this.DateOfBirth;
        // possibly make database call here
    }

    public override void Delete()
    {
        // code to delete this.existingUser from database
    }
}

Ho trovato che funziona molto bene. Separa la mia logica di editing dalle mie entità e separa la logica della creazione di una nuova entità dalla modifica di una esistente. Crea anche un posto per mettere la logica che è comune a entrambe le entità nuove ed esistenti (come la proprietà calcolata Age , e sì, so che non è stata implementata correttamente:)

    
risposta data 05.04.2014 - 03:47
fonte

Leggi altre domande sui tag