Uso delle classi nidificate per l'input e l'output per un metodo di calcolo

4

Abbiamo un grande progetto che esegue molti modelli e calcoli. Questo codice viene suddiviso in blocchi più piccoli e più gestibili, spostando particolari calcoli nelle proprie classi.

Per provare a mantenere gli input e gli output vincolati al metodo di calcolo appropriato, sono state utilizzate due classi di proprietà nidificate pubbliche (se le classi di proprietà sono il termine corretto per una classe che ha solo proprietà).

Quello che segue è un esempio di come viene affrontato:

public class SomeCalculation
{
    public Result Calculate(Parameters p)
    {
        double foundValue = 0;

        switch (p.ParamD)
        {
            case SomeEnum.Element1:
                foundValue = p.ParamA + p.ParamB + p.ParamC;
                break;
            case SomeEnum.Element1:
                foundValue = p.ParamA + p.ParamB - p.ParamC;
                p.ParamC = 5;                    
                break;
            default:
                p.ParamB = -2;
                break;
        }

        return new Result()
        {
            FoundValue = foundValue,
            NewParamB = p.ParamB,
            NewParamC = p.ParamC
        };
    }

    public class Parameters
    {
        public double ParamA { get; set; }
        public double ParamB { get; set; }
        public int ParamC { get; set; }
        public SomeEnum ParamD { get; set; }
    }

    public class Result
    {
        public double FoundValue { get; set; }
        public double NewParamB { get; set; }
        public int NewParamC { get; set; }
    }

}

Questo calcolo sarebbe quindi eseguito istanziando e passando nella classe% co_de nidificata. I principali vantaggi di questo sono che le classi Parameters e Parameters vengono mantenute con la classe Result , e gli stessi nomi di classi annidate possono essere riutilizzati con altre classi calcolo .

Mi chiedo se il modello di design sopra riportato sia un approccio ragionevole, anche se la pagina Tipi nidificati di MSDN dice di evitare di esporre pubblicamente i tipi annidati. Inoltre, è conforme alle pratiche standard (come i principi SOLID) o avrà qualche limite che potrebbe causare problemi?

    
posta Ayb4btu 10.10.2016 - 07:26
fonte

3 risposte

2

La ragione per cui MSDN dice di evitare i tipi nidificati esposti pubblicamente è perché, se ne avessi bisogno, perché dovresti avere anche l'incapsulamento fornito da nidificazione?

Le classi nidificate vengono quindi solitamente utilizzate in luoghi in cui si usa solo la classe all'interno della classe esterna e da nessun'altra parte. Ho trovato occasione per farlo esattamente una volta. Non mi piacciono i classici Tuples in C #, e questa particolare classe includeva un piccolo DTO che non era esposto al mondo esterno .

Non avrai bisogno di classi nidificate circa il 99 percento delle volte. In genere, se è abbastanza importante fare una lezione, è abbastanza importante renderla pubblica e non annidata. I namespace sono un posto migliore per mettere tali classi.

L'accesso a una classe nidificata da un membro pubblico è quasi certamente una semi-violazione della "Legge" di Demetra ( anche se stai solo "contando i punti").

    
risposta data 10.10.2016 - 08:08
fonte
2

I tipi annidati pubblici sono generalmente solo un problema estetico. Non esiste funzionalmente alcuna differenza reale tra il tipo nidificato e quello non annodato diverso dal suo nome. Quindi tutto dipende da ciò che voi e il vostro team provate. Farebbe la differenza se il tipo annidato fosse privato, ma non è il tuo caso.

Ma sto vedendo un altro problema. Il tuo metodo prende ParamB e ParamC e restituisce NewParamB e NewParamC . Questa è una bandiera rossa per me, perché sembra che tu stia effettivamente separando qualcosa che dovrebbe essere una singola classe, perché più metodi condividono alcuni stati comuni che manipolano. Separare ciecamente ogni metodo di classe in puro metodo statico renderà il codice più complesso se quei metodi effettivamente appartengono a una singola classe. Dovresti mettere molta più attenzione nella creazione di classi con metodi che condividono e manipolano il singolo stato. Forse scoprirai che c'è molto di più nel tuo codice rispetto a un mucchio di calcoli.

    
risposta data 10.10.2016 - 07:47
fonte
1

Potrei sbagliarmi in questa asserzione, ma mi sembra che tu stia cercando di evitare il Principio di Responsabilità Unica semplicemente suddividendo la funzionalità in classi separate e poi inserendo le definizioni di classe all'interno di un'altra classe. Questo, o stai tentando di separare le funzionalità in classi separate quando in realtà tutto dipende l'un l'altro per funzionare correttamente, nel qual caso dovrebbe essere tutto in una singola classe comunque. In ogni caso, non vedo perché stai usando classi annidate qui.

Quello che potresti provare a fare è creare un'interfaccia che contenga le diverse funzioni necessarie per effettuare un calcolo completo, e quindi fare in modo che ciascuna classe implementi quell'interfaccia in modo diverso in base al tipo di calcolo che viene eseguito. Questo ha l'ulteriore vantaggio di rendere il tuo codice polimorfico, che il tuo codice attuale non sembra essere. Inoltre non dovresti aver bisogno di altre classi per verificare che i tuoi input e output siano validi. Se hai progettato correttamente la classe, dovrebbe farlo da sola.

Oppure, se l'implementazione rimarrà per lo più la stessa, con alcune differenze, puoi anche utilizzare una classe astratta per eseguire la maggior parte dell'implementazione in una classe base e implementare il resto nelle sottoclassi.

Essenzialmente quello che sto dicendo è mantenere il tuo codice modulare. Non dividere l'implementazione in un gruppo di classi diverse, indipendentemente dal fatto che siano nidificate o meno. Una classe dovrebbe essere in grado di funzionare completamente da sola e, in caso contrario, non dovrebbe essere una classe.

    
risposta data 10.10.2016 - 18:07
fonte

Leggi altre domande sui tag