VB.NET Qual è lo scopo di una class o di un modulo?

Salsa newbie qui … Così, ho cercato di trovare la risposta, ma non potevo.

Qual è lo scopo di avere una class o un modulo? Tutto ciò che ho letto cerca di dirmi di cosa si tratta, ma non per quello che è. Perché dovrei averne bisogno?

Tutto ciò che ho letto sembra fare supposizioni sulla persona che legge il tutorial, come se ne sapessi molto.

Un modulo è davvero molto simile a una semplice class contenente solo membri condivisi. In realtà, in C #, non esiste un tale costrutto come un “modulo”. Non puoi scrivere alcuna applicazione senza avere almeno un modulo o una class, quindi sospetto che la tua vera domanda non sia “perché usare classi e moduli”, ma piuttosto “perché usare più classi e moduli e quando è opportuno iniziarne una nuova” . Dato che i moduli e le classi sono essenzialmente la stessa cosa, mi concentrerò sul perché avresti più classi. Ci sono essenzialmente quattro ragioni principali per creare una nuova class:

  1. Memorizza i dati in articoli discreti
  2. Organizza il tuo codice
  3. Fornisci cuciture nel tuo codice
  4. Dividi il tuo codice in livelli e supporta i livelli n

Ora, esaminiamo ciascuno in modo più dettagliato:

Memorizza i dati in articoli discreti

Spesso è necessario memorizzare più dati su un singolo object e passare tali dati tra i metodi come un singolo object. Ad esempio, se si scrive un’applicazione che funziona con una persona, è probabile che si desideri memorizzare più dati sulla persona, come il nome, l’età e il titolo. Ovviamente è ansible memorizzare questi tre dati come tre variabili separate e passarli come parametri separati ai metodi, ad esempio:

 Public Sub DisplayPerson(name As String, age As Integer, title As String) Label1.Text = name Label2.Text = age.ToString() Label3.Text = title End Sub 

Tuttavia, è spesso più conveniente passare tutti i dati come un singolo object, ad esempio, potresti creare un MyPersonClass , come questo:

 Public Class MyPersonClass Public Name As String Public Age As Integer Public Title As String End Class 

E poi potresti passare tutti i dati relativi a una persona in un singolo parametro, in questo modo:

 Public Sub DisplayPerson(person As MyPersonClass) Label1.Text = person.Name Label2.Text = person.Age.ToString() Label3.Text = person.Title End Sub 

Facendolo in questo modo, in futuro sarà molto più facile modificare la tua persona. Ad esempio, se è necessario aggiungere la possibilità di memorizzare un’abilità per la persona e non aver inserito i dati della persona in una class, si dovrebbe andare in ogni posizione nel codice che passa i dati della persona e aggiungere il parametro aggiuntivo . In un progetto di grandi dimensioni, potrebbe essere molto difficile trovare tutti quei luoghi da risolvere, il che potrebbe portare a bug. Tuttavia, la necessità della class diventa ancora più evidente quando inizi a dover memorizzare un elenco di più persone. Ad esempio, se è necessario memorizzare i dati per 10 persone diverse, è necessario un elenco o una matrice di variabili, ad esempio:

 Dim names(9) As String Dim ages(9) As Integer Dim titles(9) As String 

Ovviamente, non è affatto scontato che i names(3) e l’ age(3) memorizzino i dati per la stessa persona. Questo è qualcosa che devi solo sapere, o devi scriverlo in un commento in modo da non dimenticare. Tuttavia, questo è molto più pulito e facile da fare quando si ha la class per memorizzare tutti i dati per una persona:

 Dim persons(9) As Person 

Ora, è del tutto ovvio che persons(3).Name e persons(3).Age siano entrambi dati per la stessa persona. In questo modo, è autodocumentante. Non è necessario alcun commento per chiarire la tua logica. Di conseguenza, di nuovo, il codice sarà meno incline ai bug.

Spesso, le classi conterranno non solo i dati per un determinato elemento, ma anche i metodi che agiscono su tali dati. Questo è un meccanismo conveniente. Ad esempio, potresti voler aggiungere un metodo GetDesciption alla class person, ad esempio:

 Public Class MyPersonClass Public Name As String Public Age As Integer Public Title As String Public Function GetDescription() As String Return Title & " " & Name End Function End Class 

Quindi puoi usarlo in questo modo:

 For Each person As MyPersonClass In persons MessageBox.Show("Hello " & person.GetDescription()) Next 

Che, come sono sicuro che sarete d’accordo, è molto più pulito e più facile di fare qualcosa del genere:

 For i As Integer = 0 To 9 MessageBox.Show("Hello " & GetPersonDescription(title(i), names(i))) Next 

Ora diciamo che vuoi memorizzare più nickname per ogni persona. Come si può facilmente vedere, persons(3).Nicknames(0) è molto più semplice di un pazzo array bidimensionale, come nicknames(3)(0) . E cosa succede se hai bisogno di memorizzare più dati su ogni nickname? Come puoi vedere, non usare le lezioni si complicherebbe molto velocemente.

Organizza il tuo codice

Quando scrivi un programma lungo, può diventare molto caotico molto rapidamente e portare a codice molto buggato se non organizzi correttamente il tuo codice. L’arma più importante che hai in questa battaglia contro spaghetti code è creare più classi. Idealmente, ogni class conterrà solo i metodi che sono logicamente correlati l’uno con l’altro. Ogni nuovo tipo di funzionalità dovrebbe essere suddiviso in una nuova class ben denominata. In un grande progetto, queste classi dovrebbero essere ulteriormente organizzate in spazi dei nomi separati, ma se non li dividi almeno in classi, farai davvero un casino. Ad esempio, diciamo che hai tutti i seguenti metodi tutti gettati nello stesso modulo:

  • GetPersonDescription
  • GetProductDescription
  • FirePerson
  • SellProduct

Sono sicuro che saresti d’accordo, che è molto più facile seguire il codice se questi metodi sono stati suddivisi in classi separate, come ad esempio:

  • Person
    • GetDescription
    • Fire
  • Product
    • GetDescription
    • Sell

E questo è solo un esempio molto, molto semplice. Quando si dispone di migliaia di metodi e variabili che si occupano di molti articoli diversi e di diversi tipi di articoli, sono sicuro che si può facilmente immaginare perché le classi siano importanti per aiutare a organizzare e ad auto-documentare il codice.

Fornisci giunture nel tuo codice

Questo potrebbe essere un po ‘più avanzato, ma è molto importante, quindi proverò a tentare di spiegarlo in termini semplici. Supponiamo che tu crei una class trace-logger che scrive le voci del registro in un file di log di traccia. Per esempio:

 Public Class TraceLogger Public Sub LogEntry(text As String) ' Append the time-stamp to the text ' Write the text to the file End Sub End Class 

Ora, diciamo che vuoi che la class del logger sia in grado di scrivere su un file o su un database. A questo punto diventa ovvio che scrivere la voce di log sul file è in realtà un tipo separato di logica che dovrebbe essere sempre nella sua class, quindi puoi suddividerlo in una class separata, come questa:

 Public Class TextFileLogWriter Public Sub WriteEntry(text As String) ' Write to file End Sub End Class 

Ora puoi creare un’interfaccia comune e condividerla tra due classi diverse. Entrambe le classi gestiranno le voci del registro di scrittura, ma ognuna eseguirà la funzionalità in modi completamente diversi:

 Public Interface ILogWriter Sub WriteEntry(text As String) End Interface Public Class TextFileLogWriter Implements ILogWriter Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry ' Write to file End Sub End Class Public Class DatabaseLogWriter Implements ILogWriter Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry ' Write to database End Sub End Class 

Ora che hai infranto quella logica di accesso ai dati nelle sue classi, puoi rifattorizzare la tua class di logger in questo modo:

 Public Class TraceLogger Public Sub New(writer As ILogWriter) _writer = writer End Sub Private _writer As ILogWriter Public Sub LogEntry(text As String) ' Append the time-stamp to the text _writer.WriteEntry(text) End Sub End Class 

Ora puoi riutilizzare la class TraceLogger in molte altre situazioni senza dover mai toccare quella class. Ad esempio, puoi assegnargli un object ILogWriter che scrive le voci nel registro eventi di Windows, o in un foglio di calcolo o persino in un’email, il tutto senza mai toccare la class TraceLogger originale. Questo è ansible perché hai creato una sequenza nella tua logica tra la formattazione delle voci e la scrittura delle voci.

La formattazione non interessa come vengono registrate le voci. Tutto ciò che importa è come formattare le voci. Quando ha bisogno di scrivere e di entrare, chiede semplicemente a un object writer separato di fare quella parte del lavoro. Come e ciò che lo scrittore fa internamente è irrilevante. Allo stesso modo, lo scrittore non si preoccupa di come viene formattata la voce, si aspetta solo che tutto ciò che viene passato ad essa sia una voce valida già formattata che deve essere registrata.

Come avrai notato, non solo TraceLogger ora riutilizzabile per scrivere su qualsiasi tipo di registro, ma anche, gli scrittori sono riutilizzabili per scrivere qualsiasi tipo di registro per quei tipi di registri. È ansible riutilizzare DatabaseLogWriter , ad esempio, per scrivere sia i registri di traccia che i registri delle eccezioni.

A Little Rant Riguardo all’iniezione di dipendenza

Semplicemente, umorami, un po ‘, mentre faccio questa risposta un po’ più a lungo con uno sproloquio su qualcosa di importante per me … Nell’ultimo esempio, ho usato una tecnica chiamata dependency injection (DI). Si chiama injection dependency perché l’object writer è una dipendenza della class logger e tale object dipendenza viene iniettato nella class logger tramite il costruttore. Potresti realizzare qualcosa di simile senza l’iniezione di dipendenza facendo qualcosa del genere:

 Public Class TraceLogger Public Sub New(mode As LoggerModeEnum) If mode = LoggerModeEnum.TextFile Then _writer = New TextFileLogWriter() Else _writer = New DatabaseLogWriter() End If End Sub Private _writer As ILogWriter Public Sub LogEntry(text As String) ' Append the time-stamp to the text _writer.WriteEntry(text) End Sub End Class 

Tuttavia, come puoi vedere, se lo fai in questo modo, ora dovrai modificare quella class di logger ogni volta che crei un nuovo tipo di writer. E poi, solo per creare un logger, devi avere riferimenti ogni diverso tipo di scrittore. Quando scrivi codice in questo modo, molto presto, ogni volta che includi una lezione, devi improvvisamente fare riferimento al mondo intero solo per fare un compito semplice.

Un’altra alternativa all’approccio dipendenza per l’iniezione sarebbe l’utilizzo dell’ereditarietà per creare più classi TraceLogger , una per tipo di autore:

 Public MustInherit Class TraceLogger Public Sub New() _writer = NewLogWriter() End Sub Private _writer As ILogWriter Protected MustOverride Sub NewLogWriter() Public Sub LogEntry(text As String) ' Append the time-stamp to the text _writer.WriteEntry(text) End Sub End Class Public Class TextFileTraceLogger Inherits TraceLogger Protected Overrides Sub NewLogWriter() _Return New TextFileLogWriter() End Sub End Class Public Class DatabaseTraceLogger Inherits TraceLogger Protected Overrides Sub NewLogWriter() _Return New DatabaseLogWriter() End Sub End Class 

Così facendo con l’ereditarietà, è meglio dell’approccio enumerazione di modalità, perché non è necessario fare riferimento a tutta la logica del database solo per accedere a un file di testo, ma, a mio parere, l’iniezione di dipendenza è più pulita e più flessibile .

Torna a un riepilogo delle giunzioni logiche

Quindi, in sintesi, le giunture nella tua logica sono importanti per la riusabilità, la flessibilità e l’intercambiabilità del tuo codice. Nei piccoli progetti, queste cose non sono della massima importanza, ma man mano che i progetti crescono, avere delle giunture chiare può diventare critico.

Un altro grande vantaggio della creazione di cuciture è che rende il codice più stabile e verificabile. Una volta che sai che TraceLogger funziona, c’è un grande vantaggio di poterlo estendere per usi futuri, come scrivere registri su un foglio di calcolo, senza dover toccare la class TraceLogger effettiva. Se non devi toccarlo, non rischi di introdurre nuovi bug e potenzialmente compromettere il resto del codice che già lo utilizza. Inoltre, diventa molto più semplice testare ogni parte del codice in isolamento. Ad esempio, se si desidera testare la class TraceLogger , è ansible, per il test, utilizzare un object writer falso che registra solo la memoria, la console o qualcosa del genere.

Dividi il tuo codice in livelli e supporta N-Tiers

Una volta organizzato correttamente il codice in classi separate, in cui ogni class è responsabile solo per un tipo di attività, è ansible iniziare a raggruppare le classi in livelli . I livelli sono solo un’organizzazione di alto livello del tuo codice. Non c’è nulla di specifico nella lingua che rende tecnicamente un livello. Dal momento che non c’è nulla direttamente nella lingua che chiarisca dove inizia e finisce ogni livello, la gente spesso mette tutte le classi per ogni livello in spazi dei nomi separati. Quindi, ad esempio, potresti avere spazi dei nomi che assomigliano a questo (dove ogni spazio dei nomi è un livello separato):

  • MyProduct.Presentation
  • MyProduct.Business
  • MyProduct.DataAccess

In genere, si desidera sempre avere almeno due livelli nel codice: la presentazione o il livello dell’interfaccia utente e il livello della business logic. Se l’applicazione esegue un accesso ai dati, in genere viene inserita anche nel proprio livello. Ogni strato dovrebbe essere, per quanto ansible, indipendente e intercambiabile. Quindi, ad esempio, se la nostra class TraceLogger nell’esempio precedente si trova in un livello aziendale, dovrebbe essere riutilizzabile da qualsiasi tipo di interfaccia utente.

Gli strati si espandono su tutti gli argomenti precedenti fornendo ulteriore organizzazione, autodocumentazione, riusabilità e stabilità. Tuttavia, un altro vantaggio importante per i livelli è che diventa molto più facile suddividere l’applicazione in più livelli. Ad esempio, se è necessario spostare la logica aziendale e di accesso ai dati in un servizio Web, sarà molto semplice farlo se si è già scritto il codice in modo pulito in livelli definiti. Se, tuttavia, tutta questa logica è mescasting e interdipendente, allora sarà un incubo tentare di infrangere solo l’accesso ai dati e la logica aziendale in un progetto separato.

La fine di quello che ho da dire

In breve, non è mai necessario creare più di una class o modulo. Sarà sempre ansible scrivere l’intera applicazione in una singola class o modulo. Interi sistemi operativi e suite di software sono stati sviluppati, dopotutto, prima che i linguaggi orientati agli oggetti venissero inventati. Tuttavia, c’è un motivo per cui le lingue di programmazione orientata agli oggetti (OOP) sono così popolari. Per molti progetti, l’orientamento all’object è estremamente vantaggioso.

Una class è il meccanismo per incapsulare lo stato (dati) e il comportamento (metodi).

È necessario utilizzare le classi se si desidera avere qualsiasi tipo di astrazione nel codice: modi per organizzare il codice per l’utilizzo.

Non averli significa che il tuo codice è dappertutto e degenererà in qualcosa che è difficile da modificare e mantenere.

La forma più elementare che un programma per computer può prendere è chiamata procedura : si scrive un elenco di istruzioni (linee di codice) che il computer deve eseguire e quindi si esce dal programma.

Molti programmi per computer, tuttavia, sono progettati per funzionare indipendentemente dal singolo clic su “Esegui” ogni volta che è necessario. È questo concetto di riutilizzo del codice che è centrale nella maggior parte delle discussioni sulla scrittura di software. Un modulo consente di memorizzare il codice in un contenitore e fare riferimento ad esso in altre parti del programma.

Una class è un concetto più generale attraverso la programmazione orientata agli oggetti, che consente di definire una “cosa” e quindi crearla più volte mentre il programma è in esecuzione.

Supponi di voler creare un gioco Virtual Pet in Visual Basic. Permetti all’utente di aggiungere tanti animali quanti ne vogliono e inizi a capire che tenerne traccia è molto complicato. Usando le classi questo diventa davvero facile …

 Class PetDog Private _id As Integer Public Name As String Public Breed As String Public Sub Bark() Console.WriteLine(Name + " says Woof!") End Sub End Class 

Una volta che hai scritto questo codice, consentire all’utente di aggiungere un altro cane al loro zoo di coccole diventa così semplice:

 Dim Dog1 As New PetDog() Dim Dog2 As New PetDog() 

Ora puoi interagire con Dog1 e Dog2 indipendentemente l’ uno dall’altro, nonostante tu possa definirlo solo una volta nel tuo codice.

 Dog1.Name = "Fido" Dog2.Breed = "Poodle" Dog1.Bark() 

Il frammento di cui sopra avrebbe stampato “Fido dice Woof!”.

Spero possa aiutare 🙂

Se stai per creare il tuo tipo personalizzato e successivamente creare oggetti di quel tipo, usa una class.

Se hai a che fare con le classi di qualcun altro – e devi implementare alcune funzionalità veloci e sporche per migliorarle – usa i moduli.

Gli sviluppatori di C # potrebbero mostrare una faccia acida ora, perché useresti i metodi condivisi di una class condivisa invece di un modulo in C #, in definitiva perché C # non ha moduli. Quindi useresti le classi in entrambi i casi in C #. E dovresti fare lo stesso in VB.NET, davvero. Ti dà preoccupazione per la separazione dei nomi, quindi la tua intelligenza è più organizzata. Con i moduli, tutti i tuoi metodi pubblici di tutti i moduli sono nel secchio globale dei metodi – più confusione da affrontare.

L’unico buon uso per i moduli in VB.NET è quando si scrivono i metodi di estensione.

Classi, moduli e codice- “Moduli” sono tutti i tipi di moduli in VB.

I moduli sono solo contenitori denominati per il codice e tutto il codice deve essere in una sorta di modulo. Nel modo più semplice, sono un modo per organizzare le routine in gruppi significativi.

I più elementari, i cosiddetti “Modules” (o “moduli di codice” come venivano chiamati una volta per distinguerli dal concetto più generale di moduli) forniscono poco più di quello, oltre a un modo per dichiarare variabili che vivono al di fuori di qualsiasi una singola routine e non andare via quando si esce dalla routine, e un modo semplice per associare quale codice / modulo / i sono in quale file sorgente.

Le classi sono un tipo di modulo più potente (*) che può essere “Istanziato”, il che significa semplicemente che puoi trattarli come un tipo di dati, creare più copie di essi con valori / contenuti diversi, assegnarli a variabili, passarli da e verso funzioni e altri metodi, ecc. Queste copie o “istanze” sono più comunemente chiamate “Oggetti”.

I moduli sono solo un tipo speciale di Classe che si integra auto-magicamente con componenti e controlli visivi per aiutarti a creare un’interfaccia grafica utente.

(* – Si noti che oggi questo viene insegnato al contrario: le classi sono il concetto generale e i codici mdo-VB sono solo una class specializzata molto limitata chiamata “Singleton”. Ma sia storicamente che nella tradizione di Basic, era Moduli molto prima delle lezioni.)

Sembra che tu abbia familiarità con un certo livello di scripting, ma non necessariamente programmazione orientata agli oggetti.

La ragione per usare classi o moduli (che sono entrambi gli oggetti) è che le funzioni simili consentono il riutilizzo del codice, gli oggetti consentono il riutilizzo.

Oltre alla riutilizzabilità, hanno il vantaggio di poter contenere sia dati (proprietà) che funzioni. Ad esempio, una class Person può avere proprietà come nome, data di nascita, ecc. E un metodo per calcolare la loro età.

In questo modo, ogni volta che avevi una nuova persona, dovresti creare una nuova istanza di quella persona e sarebbe facile calcolare la loro età (in base al compleanno e alla data corrente).

In alternativa, puoi fare tutto ciò allo stesso modo scrivendo una funzione per calcolare l’età e creare un array per ogni persona, quindi chiamare la tua funzione di calcolo dell’età passando l’array per età, ma non avresti lo stesso livello di riusabilità .

Per trovare articoli utili, potresti google per le introduzioni alla programmazione orientata agli oggetti.

In parole semplici, una class o un modulo per me in programmazione viene utilizzato per non dare un modulo a molto script quando viene caricato. Quindi abbiamo bisogno di ridurli in classi e moduli.