Refactoring: quando aggiungere una nuova classe nel progetto?

4

Quando ritieni di aver bisogno di una nuova classe (magari quando stai sviluppando o dopo lo sviluppo per scopi di refactoring)?

Forse posso iniziare dalle mie variabili esistenti e pensare a come posso riorganizzarle in alcune classi! Per favore aggiungi altro!

    
posta Ahmad 25.12.2014 - 08:19
fonte

4 risposte

14

Il motivo principale per usare una classe è che esiste un concetto nel dominio che stai cercando di esprimere nel tuo codice e che vuoi codificare in qualche modo questo concetto. Solitamente, le classi vengono create quando tu, come sviluppatore, vedi, attraverso i tuoi anni di esperienza, che esiste un concetto in ciò che stai cercando di ottenere e vuoi convertire esplicitamente questo concetto in codice.

Ma anche, molti dei concetti appaiono dopo aver scritto il codice, abbastanza spesso come i vari odori di codice. Ci sono due esempi:

Più valori passati insieme.

Sia Point o Cliente, a volte puoi vedere che ci sono più variabili (3+) che passano insieme. Il codice di solito ha bisogno di tutte, o la maggior parte di queste variabili e anche se non ne ha direttamente bisogno, le dipendenze potrebbero farlo. Questa è una grande opportunità per introdurre una classe per incapsulare tutte quelle variabili. Successivamente, ti rendi conto che molte delle funzioni che funzionano su quei campi potrebbero effettivamente far parte della classe stessa. E poi, potresti realizzare che questo è un concetto all'interno del tuo dominio, che ti è mancato durante l'analisi o la progettazione.

Funzioni grandi

È successo più volte a me, che ho trovato una funzione troppo lunga. Ma quando ho provato a dividerlo in funzioni più piccole, ha comportato il passaggio di tutti gli stati della funzione nei parametri. Questa è una grande opportunità per introdurre una classe per rappresentare l'intera funzione stessa. I parametri della funzione potrebbero diventare il costruttore di una classe. Le variabili della funzione diventano campi. E poi, puoi facilmente separare la grande funzione in quelle più piccole, perché usano tutte lo stato condiviso invece di affidarsi al passaggio dei parametri. E poi, ti rendi conto che alcuni degli if s e switch es potrebbero essere rappresentati come sottoclassi invece dei costrutti del flusso di codice, creando una rappresentazione ricca, manutenibile ed espressiva invece di una enorme funzione difficile da seguire e mantenere. Questo dovrebbe farti pensare: se questo pezzo di codice fosse così complesso, non dovrebbe essere una specie di concetto nel dominio in cui lavoro?

Classi come "strutture con funzioni"

Stai dicendo che hai esperienza con la programmazione procedurale. Quindi devi conoscere le strutture e i loro casi d'uso. Strutture e classi si sovrappongono in molti di questi casi d'uso. Alcuni dicono addirittura che le classi sono solo strutture con funzioni imbullonate su di esse e che non sono diverse dalla programmazione procedurale. Anche se non sono d'accordo, potrebbe essere un buon modo per iniziare a pensare alle lezioni. Quindi, ogni volta che si crea una struttura, si crea invece una classe non statica. Il resto poi segue.

Dipendenze trasparenti e flusso di controllo

Un altro problema con le classi statiche è quello della dipendenza. Se il metodo di una classe è statico, diventa difficile stabilire quale codice usi effettivamente questo metodo. Diventa un problema ancora peggiore se è coinvolto lo stato statico (in forma di campi statici). Diventa estremamente difficile seguire il flusso di un codice quando non si sa quali altri metodi potrebbero essere coinvolti. Se si usano classi non statiche, diventa molto più pulito, perché si conosce quale parte del metodo di memoria può essere modificata, invece di lavorare con lo stato globale. In realtà, lo stato globale è la parola chiave qui. È generalmente noto che i problemi con lo stato globale vanno dal dolore nel culo all'incubo totale. Dovresti sforzarti di ridurre al minimo la quantità di stato globale nei tuoi programmi. L'utilizzo di classi non statiche dovrebbe essere prioritario su classi statiche, quando possibile.

    
risposta data 25.12.2014 - 22:43
fonte
4

In OOA&D I would like to know how you easily distinguish if a class is non-static?

Perché? In OO, le classi statiche dovrebbero essere molto rare (se la lingua le consente affatto). Il tuo IDE ti dirà rapidamente che non esiste un costruttore per quella classe, e se non è il tuo IDE, il compilatore sicuramente lo farà.

But for the one who is used to procedural programming how he can think of classes and the necessity for objects?

Practice . Gli oggetti non sono una necessità. Ma entrare nel treno dei pensieri per guardare ai problemi da "quali pacchetti di dati / comportamenti costituiscono questo problema?" prospettiva piuttosto che "quali passi devo fare per risolvere questo problema?" la prospettiva richiede tempo e pratica.

Objects also have state and are mutable.

Non ci sono.

Nella moderna progettazione OO, gli oggetti molto spesso sono non mutabili. Hanno più spesso lo stato, ma anche questa non è una buona regola per fare oggetti. Molti dei modelli di progettazione OO (strategia, la maggior parte delle fabbriche, alcuni visitatori, ecc.) Useranno oggetti che non contengono stati.

I would like some rules of thumb or a short definition to easily distinguish classes in any project.

Non esistono regole empiriche universali. Esistono regole pratiche per le funzioni da eseguire nella programmazione procedurale? No, cambierà in base al tipo di problema che stai affrontando, alla lingua che stai utilizzando e al tuo particolare stile di codifica. Anche i programmatori esperti spesso non sono d'accordo su dove devono essere disegnate le linee per suddividere le classi.

    
risposta data 25.12.2014 - 15:06
fonte
1

L'uso delle classi rende il tuo programma più breve e più chiaro (in realtà se il programma non è troppo semplice). Le classi possono incapsulare alcune delle variabili esistenti e i metodi correlati. Ogni classe rappresenta un concetto che a sua volta facilita il reperimento e la comprensione della soluzione.

Per chiarire questi, faccio un esempio:

1- Supponi un programma che prende le dimensioni di un rettangolo e calcola la sua area, potrebbe essere:

static void Main()
{
    int w,h;
    read(w,h);
    int a = calcArea(w,h); // it simply returns w x h
    print(a);
}

2- Un programma che prende tre rettangoli in diverse coordinate e stampa l'area intersecata, il vecchio approccio ti dà

static void Main()
{
    int x1,y1,w1,h1,x2,y2,w2,h2,x3,y3,w3,h3; // for rectangles
    int x4,y4,w4,h4;  // for the intersect
    calcIntersect(x1,y1,w1,h1,x2,y2,w2,h2,x3,y3,w3,h3,x4,y4,w4,h4);       
}
void calcIntersect(int x1,int y1,int w1,int h1,int x2,
 int y2,int w2,int h2,int x3,int y3,int w3,int h3,
 int& x4,int& y4,int& w4,int& h4)
{
   // a fancy algorithms which works with this bunch of dimensions, its scary!!
}

Dato che hai più oggetti hai bisogno di classe, allora avresti:

class Rectangle
{
    public int x,y,w,h;      
}
// in your main
static void Main()
{
    Rectangle r1,r2,r3, r4; //r4 for intersect
}

Ora invece di pensare alle dimensioni, pensiamo ai rettangoli come a un nuovo concetto! ...., posso calcolare l'intersezione di due rettangoli che è essa stessa un rettangolo e la stessa procedura mi dà l'intersezione di questo rettangolo con il terzo . Osservi che questo nuovo concetto rende più facile trovare la soluzione.

class Rectangle 
{
    public int x,y,w,h;
    Rectangle Intersect(Rectangle r)
    {
       // now the situation is much better 
    }
}
static void Main()
{
    Rectangle r1,r2,r3,r4;
    Rectangle temp = r1.Intersect(r2);
    r4 = r3.Intersect(temp);    
}
    
risposta data 25.12.2014 - 11:25
fonte
-6

Semplice: le classi statiche sono estremamente stupide. Se pensi di aver identificato un caso per una classe statica, allora fermati, perché non lo hai fatto. Potresti aver identificato uno spazio dei nomi.

Non ci sono classi statiche in OOP.

    
risposta data 25.12.2014 - 15:57
fonte

Leggi altre domande sui tag