Domanda

Sto leggendo molto su buone e cattive pratiche nella progettazione di OOP. È bello sapere che il tuo design è cattivo o buono. Ma come si passa dal cattivo al buon design? Ho diviso l'interfaccia (xaml) e codebehind dalla principale classe businesslogic. L'ultima classe sta diventando grande. Ho provato a suddividerlo in classi più piccole, ma ora sono bloccato. Qualche idea su come dividere le classi di grandi dimensioni? La classe principale ha 1 elenco di dati di diversi tipi. Sto facendo calcoli sul totale, ma anche sui singoli tipi. Ho dei metodi per eseguire questi calcoli che vengono chiamati dagli eventi gestiti nel codebehind. Qualche idea su dove andare da qui?

Informazioni aggiuntive:

Siamo già circa 6 mesi in questo progetto. Ho lavorato con laguages ??orientati agli oggetti per anni (prima c ++, java e ora c #), ma mai su un grande progetto come questo. Credo che abbiamo fatto delle svolte sbagliate all'inizio e penso che dobbiamo correggerle. Al momento non posso specificare alcun dettaglio su questo progetto. Ordinerò uno o due libri sul design. Se separo tutte le classi, come le rimetto insieme? Forse è ancora meglio continuare così fino alla prima versione e parti ricostruite dopo, per una seconda versione?

È stato utile?

Soluzione

  

La classe principale ha 1 elenco di dati di   tipi diversi. sto facendo   calcoli sul totale, ma anche su   i singoli tipi. Ho dei metodi   per eseguire questi calcoli quali   vengono richiamati dagli eventi gestiti in   codebehind. Qualche idea da dove andare   qui?

Se ci sono molti calcoli basati sul contenuto dell'elenco, hai preso in considerazione l'idea di spostare le operazioni in una classe di elenco personalizzata? Lo stesso vale per le operazioni sui tipi specifici, forse potrebbero vivere all'interno dei tipi?

In termini di esecuzione di operazioni simili ma diverse su tipi diversi, considera l'utilizzo del modello di stato ( vedere questo come un sostituto delle istruzioni switch) che consente di trattare le entità in modo uniforme.

Un sacco di OOP consiste nel gettare via un approccio "top down" / micromanagement e considerare un approccio "bottom up" / autosufficiente. Vale la pena ricordare che nessuno dei due approcci è "corretto". in isolamento. Creare un codice mantenibile significa trovare un equilibrio ragionevole che richiede molto pensiero e di solito si sviluppa attraverso l'esperienza.

Altri suggerimenti

Esercitati e leggi. Ripeti :)

Alcuni libri consigliati:

  • Clean Code di Robert C Martin
  • GoF Design Patterns
  • Refactoring di Martin Fowler

Personalmente mi è piaciuto anche Head First Design Patterns, ma lo stile potrebbe non essere adatto a tutti. C'è un libro simile chiamato C # 3.0 Design Patterns (vedi ora.com). Ha più o meno le stesse cose, ma in un modo più tradizionale.

Consiglio vivamente di raccogliere Codice completo . È un ottimo libro che offre tonnellate di buoni consigli su domande come la tua.

Per darti una risposta rapida alla tua domanda su come dividere le classi di grandi dimensioni, ecco una buona regola empirica: rendere la tua classe responsabile di una cosa e una sola cosa. Quando inizi a pensare in questo modo, puoi rapidamente identificare il codice che non appartiene. Se qualcosa non appartiene, includilo in una nuova classe e usalo dalla tua classe originale.

Modifica: porta questo pensiero al metodo " " anche a livello - rendi i tuoi metodi responsabili di una cosa e solo una cosa. Aiuta a scomporre i metodi di grandi dimensioni (> 50 righe) molto rapidamente in blocchi di codice riutilizzabili.

Cambia il modo in cui pensi agli oggetti. Ogni oggetto dovrebbe avere una responsabilità molto specifica. Se hai una classe di nome qualcosa di generico, come " MainBusinessLogic " probabilmente stai facendo qualcosa di sbagliato.

Ottimo punto di partenza: leggi Object Thinking di David West & # 8217; s

Questo è solo un addendum ad alcuni ottimi suggerimenti sui libri qui.

Meglio ottengo in OO, più mi sembra di ridurre le dimensioni dell'oggetto. Non è che vado per oggetti di piccole dimensioni o altro, ma sembra che stia accadendo.

Mantenendoli piccoli, con una sola responsabilità, semplici da usare e da capire - tutti fondamentali. Ogni oggetto dovrebbe essere il più vicino possibile a prova di proiettile, controllare i parametri e non consentire mai l'oggetto in uno stato non valido. Definire chiaramente tutti gli stati validi nella documentazione.

Ogni volta che crei una classe, crea un test per quella classe. Non solo verifica il tuo codice, ma ti costringe a consumare il tuo design. Pensa sempre alla tua classe da quella "vista esterna". Assicurati di non chiedere troppo alla persona che usa la tua classe e tutto ciò che stai chiedendo a lui dovrebbe essere documentato nell'interfaccia. Spesso lancio semplicemente una main principale in una classe se non esiste un framework di test disponibile - fornisce un esempio di come utilizzare il codice proprio lì nello stesso file.

Nella programmazione, quasi tutto il mio tempo è passato a cercare di capire cosa facesse qualcun altro. Se fossi in grado di pubblicare codice utilizzando API note o ben documentate, il mio lavoro sarebbe banale e le pianificazioni significativamente più brevi.

Design-first può essere difficile. Considera l'abilità di codifica simile all'abilità sportiva. Molti di noi giocano nei nostri passi carrai, alcuni giocano nelle squadre sportive locali. Fare un buon progetto iniziale su un progetto complicato è compito di un giocatore della lega nazionale, sono uno su un milione. Accetta questo e pianifica il cambiamento: le iterazioni sono tuo amico. (A proposito, molti di noi PENSANO di essere facilmente a livello statale. Non lo siamo).

Oltre alla raccomandazione di Brian di Clean Code di Robert C Martin , potresti voler leggere su " Uncle Bob's " Principi SOLID di progettazione orientata agli oggetti .

Puoi sentirlo parlare dei Principi SOLID su Hanselminutes Podcast 145 e pulire il podcast 145 codice su .NET Rocks! Mostra # 388 . C'è anche altro con lui su .NET Rocks! Mostra # 410 , ma ciò di cui parla non è realmente correlato alla tua domanda, l'ho appena inclusa nel caso in cui ti siano piaciuti i primi due.

Dei tre podcast ho preferito gli Hanselminutes.

Refactoring di Martin Fowler è un libro eccellente su come cambiare il progettazione del tuo software senza romperlo.

Design Patterns funziona in modo simile agli algoritmi ma ti dice come combinare oggetti per svolgere varie attività utili.

Infine Martin Fowler ha una varietà di utili modelli di progettazione per le applicazioni. Ad esempio Vista passiva

Il di Michael Feathers dovrebbe funzionare efficacemente con il codice legacy " sii molto bravo, ma confesso che non l'ho letto da solo.

Lo stesso vale per " Refactoring to Patterns. "

Ho scoperto che lavorare su un 'incarico' complesso senza aiuto e poi vedere come qualcun altro è stata una grande esperienza di apprendimento per me.

Un compito in particolare era la creazione di un programma simile a una banca in cui dovevamo tenere traccia delle transazioni ed essere in grado di calcolare gli interessi maturati e cose del genere. È stato davvero il mio primo programma OOP e davvero eccezionale per la sua complessità. Diventa troppo confuso (per un principiante) per farlo in uno stile lineare senza fare errori.

Posso solo dire cosa funziona per me e non ho davvero trovato nessuno che lavori allo stesso modo, quindi non sono sicuro che ti aiuterà molto.

Fondamentalmente, il mio approccio è quello di avere il minor numero possibile di lezioni, ma non meno.

Innanzitutto, l'unica volta che è necessario salvare le informazioni è se le ricevi al momento A e ne hai bisogno in un secondo momento B. Se le ottieni e le lavori contemporaneamente, potrebbe non essere necessario per memorizzarlo.

Secondo, cosa ci fai? Se lo stai ripetendo in alcuni modi semplificati, puoi pensarlo come un set di istruzioni e il programma che vi opera come interprete di un set di istruzioni. In tal caso, potresti voler effettivamente progettare un set di istruzioni in codice byte, con un interprete, e codificare le tue informazioni in quel set di istruzioni.

Terzo, con che frequenza cambiano le informazioni? Se alcune delle informazioni cambiano molto raramente, potresti essere in grado di utilizzare la valutazione parziale (ovvero la generazione di codice). Cioè, prendi le informazioni che cambiano di rado e le usi per generare un programma ad hoc che fa quello che il tuo programma complessivo farebbe con quelle informazioni, ma molto più velocemente. Il generatore di codice è facile da scrivere perché si occupa solo di parte delle informazioni di input, la parte che cambia lentamente.

Gran parte della struttura dei dati che vedo in questi giorni esiste per supportare l'interfaccia utente. Questo chiaramente non contiene oggetti a cui l'utente tiene, e idealmente non dovresti preoccupartene neanche. Quindi ho creato un DSL per le interfacce utente che nasconde tutto ciò che hoo-haw.

Se possibile, stai lontano dagli eventi e dalle notifiche, perché si verificano in momenti specifici e quindi rappresentano cambiamenti incrementali di stato. Dovrai essere fortemente preoccupato che possano essere lasciati cadere, duplicati o ordinati male. Spesso vengono utilizzati sulla teoria secondo cui un semplice stile di polling sarebbe "meno efficiente". quando in realtà accade spesso il contrario.

Quindi, quando vedo le persone coinvolte nella tecnologia delle classi e così via, di solito è perché stanno rendendo troppo grande una struttura di dati.

Solo la mia esca per il downvote ...

Consiglio a di lavorare in modo efficace con il codice legacy di Feather, disponibile e consultabile su Safari , oltre Refactoring . È pieno di capitoli utili ed empatici come Non ho molto tempo e devo cambiarlo e La mia applicazione non ha struttura.

Prospettive da considerare:

  1. Automatizzazione dei test di qualità del design: cerca strumenti che forniscano metriche sulla qualità del design, come controllo incrociato delle tue decisioni di progettazione.
  2. Testabilità del codice: qualcuno dei tuoi refactoring aiuta o ostacola lo sviluppo guidato da test, la scrittura di test di unità o la scrittura di test funzionali? Quanto sarà difficile testare grandi pezzi dell'architettura una volta integrati?
  3. Motivazione: come difendere queste decisioni, sia dal cinico CYA alla direzione sia, cosa ancora più importante, in modo che il vostro team creda nella riprogettazione. Puoi spiegare in modo semplice e coerente perché è stata apportata una modifica e tale spiegazione sarà facile da trovare tra 6 mesi?

Preferenze personali nella progettazione, in particolare refactoring:

  1. Classi per concetti - in caso di dubbio, se esiste un unico concetto chiaro, dovrebbe essere racchiuso in una classe piuttosto che implicito come comportamento in uno o metodi.
  2. Molte piccole cose comunicanti con responsabilità sono più facili da pensare e controllare. In caso di dubbi sul modo in cui un design si associa al mondo reale, torna al vecchio Responsibility-Driven- Design approccio per scrivere le responsabilità di ogni classe. Se lo trovi difficile, i tuoi concetti su ciò che fa ogni classe potrebbero essere confusi o stanno facendo troppo.
  3. Non aver paura delle cose grandi se sono regolari. A volte, ad esempio: molti gestori di eventi su GUI, avrai legittimamente delle classi con molti più metodi o proprietà di quanto le metriche raccomandino.

Prova a scrivere codice più testabile, questo da solo mi ha costretto a ricercare e implementare pratiche OOP / concetti di progettazione migliorati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top