Esercizio - Esaminare e testare un'applicazione console C# usando dati di esempio
In questo esercizio si esaminerà e testerà il codice nel progetto Starter, si isolerà e risolverà un problema di logica e quindi si verificherà che l'applicazione aggiornata funzioni come previsto.
Durante l'esercizio verranno completate le attività seguenti:
Revisione del codice: esaminare il contenuto del file Program.cs.
Program.cs include le sezioni di codice seguenti:
- Istruzioni di primo livello: le istruzioni di primo livello simulano una serie di transazioni usando una matrice di
testDatao un numero maggiore di transazioni generate in modo casuale. - LoadTillEachMorning: il metodo
LoadTillEachMorningviene usato per configurare la cassa del registratore di cassa con un numero predefinito di banconote di ogni taglio. - MakeChange: il metodo
MakeChangeviene usato per gestire il denaro in cassa durante le transazioni di acquisto. - LogTillStatus: il metodo
LogTillStatusviene usato per visualizzare il numero di banconote di ogni taglio attualmente presenti in cassa. - TillAmountSummary: il metodo
TillAmountSummaryviene usato per visualizzare un messaggio che mostra l'importo del contante disponibile in cassa.
- Istruzioni di primo livello: le istruzioni di primo livello simulano una serie di transazioni usando una matrice di
Test iniziale: verificare che
MakeChangecalcoli correttamente il saldo di cassa quando viene usata la matricetestDataper simulare le transazioni.Debug del codice: isolare e correggere un problema di logica esposto quando si usano dati generati in modo casuale.
Test di verifica: eseguire un test di verifica sul codice sviluppato in questo esercizio.
Esaminare il contenuto del file Program.cs
In questa attività si completerà una procedura dettagliata del codice del progetto Starter. Il file Program.cs contiene un'applicazione che simula le condizioni per le transazioni giornaliere. L'applicazione chiama il metodo MakeChange per gestire il denaro in cassa durante ogni transazione. Altri metodi vengono usati per inizializzare la cassa e generare messaggi di segnalazione.
Assicurarsi che la cartella GuidedProject sia aperta in Visual Studio Code.
Nella visualizzazione EXPLORER espandere le cartelle GuidedProject e Starter.
La cartella Starter contiene l'applicazione di esempio per questo modulo di progetto guidato.
Aprire il file Program.cs nell'editor di Visual Studio Code.
Nel menu Visualizza selezionare Riquadro comandi.
Al prompt dei comandi immettere .net: g e quindi selezionare .NET: Generare asset per la compilazione e il debug.
Al prompt Selezionare il progetto da avviare specificare il progetto Starter.
Il file launch.json creato includerà una configurazione per il progetto Starter.
Soffermarsi qualche istante a esaminare le istruzioni di primo livello per questa applicazione:
/* This application manages transactions at a store check-out line. The check-out line has a cash register, and the register has a cash till that is prepared with a number of bills each morning. The till includes bills of four denominations: $1, $5, $10, and $20. The till is used to provide the customer with change during the transaction. The item cost is a randomly generated number between 2 and 49. The customer offers payment based on an algorithm that determines a number of bills in each denomination. Each day, the cash till is loaded at the start of the day. As transactions occur, the cash till is managed in a method named MakeChange (customer payments go in and the change returned to the customer comes out). A separate "safety check" calculation that's used to verify the amount of money in the till is performed in the "main program". This safety check is used to ensure that logic in the MakeChange method is working as expected. */ string? readResult = null; bool useTestData = true; Console.Clear(); int[] cashTill = new int[] { 0, 0, 0, 0 }; int registerCheckTillTotal = 0; // registerDailyStartingCash: $1 x 50, $5 x 20, $10 x 10, $20 x 5 => ($350 total) int[,] registerDailyStartingCash = new int[,] { { 1, 50 }, { 5, 20 }, { 10, 10 }, { 20, 5 } }; int[] testData = new int[] { 6, 10, 17, 20, 31, 36, 40, 41 }; int testCounter = 0; LoadTillEachMorning(registerDailyStartingCash, cashTill); registerCheckTillTotal = registerDailyStartingCash[0, 0] * registerDailyStartingCash[0, 1] + registerDailyStartingCash[1, 0] * registerDailyStartingCash[1, 1] + registerDailyStartingCash[2, 0] * registerDailyStartingCash[2, 1] + registerDailyStartingCash[3, 0] * registerDailyStartingCash[3, 1]; // display the number of bills of each denomination currently in the till LogTillStatus(cashTill); // display a message showing the amount of cash in the till Console.WriteLine(TillAmountSummary(cashTill)); // display the expected registerDailyStartingCash total Console.WriteLine($"Expected till value: {registerCheckTillTotal}\n\r"); var valueGenerator = new Random((int)DateTime.Now.Ticks); int transactions = 10; if (useTestData) { transactions = testData.Length; } while (transactions > 0) { transactions -= 1; int itemCost = valueGenerator.Next(2, 20); if (useTestData) { itemCost = testData[testCounter]; testCounter += 1; } int paymentOnes = itemCost % 2; // value is 1 when itemCost is odd, value is 0 when itemCost is even int paymentFives = (itemCost % 10 > 7) ? 1 : 0; // value is 1 when itemCost ends with 8 or 9, otherwise value is 0 int paymentTens = (itemCost % 20 > 13) ? 1 : 0; // value is 1 when 13 < itemCost < 20 OR 33 < itemCost < 40, otherwise value is 0 int paymentTwenties = (itemCost < 20) ? 1 : 2; // value is 1 when itemCost < 20, otherwise value is 2 // display messages describing the current transaction Console.WriteLine($"Customer is making a ${itemCost} purchase"); Console.WriteLine($"\t Using {paymentTwenties} twenty dollar bills"); Console.WriteLine($"\t Using {paymentTens} ten dollar bills"); Console.WriteLine($"\t Using {paymentFives} five dollar bills"); Console.WriteLine($"\t Using {paymentOnes} one dollar bills"); // MakeChange manages the transaction and updates the till string transactionMessage = MakeChange(itemCost, cashTill, paymentTwenties, paymentTens, paymentFives, paymentOnes); // Backup Calculation - each transaction adds current "itemCost" to the till if (transactionMessage == "transaction succeeded") { Console.WriteLine($"Transaction successfully completed."); registerCheckTillTotal += itemCost; } else { Console.WriteLine($"Transaction unsuccessful: {transactionMessage}"); } Console.WriteLine(TillAmountSummary(cashTill)); Console.WriteLine($"Expected till value: {registerCheckTillTotal}\n\r"); Console.WriteLine(); } Console.WriteLine("Press the Enter key to exit"); do { readResult = Console.ReadLine(); } while (readResult == null);Il codice delle istruzioni di primo livello completa le attività seguenti:
- Configura i dati dell'applicazione e le variabili di ambiente usati per testare il metodo
MakeChange. - Chiama i metodi
LoadTillEachMorning(),LogTillStatus()eTillAmountSummary()per preparare il saldo di cassa e stampare i messaggi di stato sulla console. - Usa un ciclo
whileper simulare una serie di transazioni. - Chiama il metodo
MakeChangedall'interno del blocco di codice del ciclowhile. - Segnala lo stato del denaro in cassa dopo ogni transazione.
Nota
Le istruzioni di primo livello includono un'istruzione
Console.ReadLine(). Il filelaunch.jsondeve essere aggiornato prima del debug.- Configura i dati dell'applicazione e le variabili di ambiente usati per testare il metodo
Dedicare qualche minuto all'esame del metodo
LoadTillEachMorning().static void LoadTillEachMorning(int[,] registerDailyStartingCash, int[] cashTill) { cashTill[0] = registerDailyStartingCash[0, 1]; cashTill[1] = registerDailyStartingCash[1, 1]; cashTill[2] = registerDailyStartingCash[2, 1]; cashTill[3] = registerDailyStartingCash[3, 1]; }Dedicare qualche altro istante all'esame del metodo
MakeChange().static string MakeChange(int cost, int[] cashTill, int twenties, int tens = 0, int fives = 0, int ones = 0) { string transactionMessage = ""; cashTill[3] += twenties; cashTill[2] += tens; cashTill[1] += fives; cashTill[0] += ones; int amountPaid = twenties * 20 + tens * 10 + fives * 5 + ones; int changeNeeded = amountPaid - cost; if (changeNeeded < 0) transactionMessage = "Not enough money provided."; Console.WriteLine("Cashier Returns:"); while ((changeNeeded > 19) && (cashTill[3] > 0)) { cashTill[3]--; changeNeeded -= 20; Console.WriteLine("\t A twenty"); } while ((changeNeeded > 9) && (cashTill[2] > 0)) { cashTill[2]--; changeNeeded -= 10; Console.WriteLine("\t A ten"); } while ((changeNeeded > 4) && (cashTill[1] > 0)) { cashTill[2]--; changeNeeded -= 5; Console.WriteLine("\t A five"); } while ((changeNeeded > 0) && (cashTill[0] > 0)) { cashTill[0]--; changeNeeded--; Console.WriteLine("\t A one"); } if (changeNeeded > 0) transactionMessage = "Can't make change. Do you have anything smaller?"; if (transactionMessage == "") transactionMessage = "transaction succeeded"; return transactionMessage; }Il metodo
MakeChangegestisce il denaro in cassa durante ogni transazione di acquisto. Il processo di transazione si basa sulle risorse e sulle condizioni seguenti:Transazione in contanti: il metodo
MakeChangeaccetta un pagamento in contanti dal cliente e quindi determina il numero di banconote di ogni taglio da dare di resto al cliente.MakeChangedeve prima assicurarsi che il cliente abbia fornito abbastanza denaro per pagare la transazione. Se l'importo è sufficiente, il processo di restituzione del resto inizia con la banconota di taglio più grande fino a quella di taglio più piccolo. In ogni fase,MakeChangeverifica che il taglio corrente sia inferiore all'importo del resto dovuto.MakeChangeverifica inoltre che in cassa sia disponibile una banconota del taglio richiesto prima di aggiungerla al resto da dare al cliente.Parametri di input: il metodo
MakeChangeusa i parametri di input seguenti:- Un valore integer che rappresenta il costo dell'articolo acquistato:
itemCost - Una matrice integer che contiene il numero di banconote in cassa per ogni taglio:
cashTill - Il pagamento effettuato dal cliente, in cui è specificato separatamente il numero di banconote per ogni taglio:
paymentTwenties,paymentTens,paymentFives,paymentOnes
- Un valore integer che rappresenta il costo dell'articolo acquistato:
Contanti disponibili in cassa: le banconote consegnate dal cliente per il pagamento devono essere incluse nelle banconote di ogni taglio disponibili per dare il resto.
Resto dovuto al cliente: il resto dovuto al cliente viene calcolato sottraendo il costo dell'articolo all'importo pagato dal cliente.
Pagamento insufficiente: se il cliente non ha fornito denaro sufficiente,
MakeChangerestituisce un messaggio descrittivo e la transazione viene annullata.Cassa insufficiente: se il denaro in cassa non è sufficiente per dare il resto esatto,
MakeChangerestituisce un messaggio descrittivo e la transazione viene annullata.
Dedicare qualche minuto all'esame del metodo
LogTillStatus().static void LogTillStatus(int[] cashTill) { Console.WriteLine("The till currently has:"); Console.WriteLine($"{cashTill[3] * 20} in twenties"); Console.WriteLine($"{cashTill[2] * 10} in tens"); Console.WriteLine($"{cashTill[1] * 5} in fives"); Console.WriteLine($"{cashTill[0]} in ones"); Console.WriteLine(); }Il metodo
LogTillStatususa la matricecashTillper riportare il contenuto corrente della cassa.Dedicare qualche minuto all'esame del metodo
TillAmountSummary().static string TillAmountSummary(int[] cashTill) { return $"The till has {cashTill[3] * 20 + cashTill[2] * 10 + cashTill[1] * 5 + cashTill[0]} dollars"; }Il metodo
TillAmountSummaryusa la matricecashTillper calcolare il saldo corrente disponibile in cassa.
A questo punto, la revisione del progetto di codice esistente è completata.
Verificare che MakeChange gestisca il denaro correttamente quando si usa la matrice testData
In questa attività si simuleranno le transazioni usando la matrice testData e si verificherà che MakeChange calcoli correttamente il saldo di cassa.
Nel menu Esegui di Visual Studio Code selezionare Avvia debug.
Si noti che viene restituito un errore
IOException.La CONSOLE DI DEBUG non supporta i metodi
Console.Clear()oConsole.ReadLine(). È necessario aggiornare il file launch.json prima del debug.Sulla barra degli strumenti Debug selezionare Arresta.
Usare la visualizzazione EXPLORER per aprire il file launch.json.
Nel file launch.json aggiornare l'attributo
consolenel modo seguente:// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console":"integratedTerminal",Il valore predefinito per l'attributo
consoleèinternalConsole, che è allineato al pannello CONSOLE DI DEBUG. Sfortunatamente, il pannello CONSOLE DI DEBUG non supporta alcuni metodi della console. L'impostazioneintegratedTerminalè allineata al pannello TERMINALE, che supporta l'input e l'output della console.Salvare le modifiche apportate al file launch.json.
Nel menu Esegui di Visual Studio Code selezionare Avvia debug.
Esaminare l'output generato dall'applicazione nel pannello TERMINALE.
Passare dal pannello CONSOLE DI DEBUG al pannello TERMINALE per esaminare l'output.
Si noti che
MakeChangecalcola correttamente il saldo di cassa quando viene usata la matricetestDataper simulare le transazioni.Nella parte inferiore dell'output riportato dovrebbero essere elencate le righe seguenti:
The till has 551 dollars Expected till value: 551 Press the Enter key to exitSi noti che il valore di cassa riportato e quello previsto sono entrambi 551.
Per uscire dall'applicazione, premere INVIO.
Identificare e risolvere i problemi di logica
In questa attività si useranno le transazioni simulate per esporre un problema di logica del codice e quindi si useranno gli strumenti del debugger di Visual Studio Code per isolare e risolvere il problema.
Per eseguire il codice usando transazioni generate in modo casuale, modificare il valore assegnato a
useTestDataspecificandofalse.È possibile trovare la variabile
useTestDatanella parte superiore delle istruzioni di primo livello.Salvare il file Program.cs e quindi eseguire l'applicazione nel debugger.
Esaminare l'output nel pannello TERMINALE.
Si noti la discrepanza nel saldo di cassa.
Il saldo di cassa finale calcolato da
MakeChangee il saldo gestito nelle istruzioni di primo livello sono riportati nella parte inferiore dell'output. Ad esempio:Transaction successfully completed. The till has 379 dollars Expected till value: 434 Press the Enter key to exitNota
L'applicazione genera in modo casuale il costo degli articoli di acquisto. Pertanto, i valori di cassa riportati nell'output sono diversi.
Per uscire dall'applicazione, premere INVIO.
Chiudere il pannello TERMINALE.
Eseguono il debug del codice
In questa attività si useranno gli strumenti del debugger di Visual Studio Code per isolare e quindi risolvere il problema di logica.
Verso la fine delle istruzioni di primo livello individuare la riga di codice seguente:
Console.WriteLine();Impostare un punto di interruzione sulla riga di codice selezionata.
Nel menu Esegui di Visual Studio Code selezionare Avvia debug.
Si noti che l'esecuzione del codice viene sospesa in corrispondenza del punto di interruzione.
Sulla barra degli strumenti Controlli di debug selezionare Esegui istruzione.
Esaminare l'output nel pannello TERMINALE.
Se il valore di cassa riportato e quello previsto sono uguali, selezionare Continua sulla barra degli strumenti Controlli di debug.
Ripetere il passaggio precedente finché non viene visualizzata una discrepanza tra il valore di cassa riportato e quello previsto.
Quando viene visualizzata una discrepanza, soffermarsi qualche istante a esaminare i dettagli della transazione.
Si noti che l'importo del denaro ricevuto e quello del resto consegnato sono corretti, ma in cassa mancano cinque dollari.
Questa carenza suggerisce che la matrice
cashTillnon viene aggiornata correttamente, anche se sono riportati i dati corretti.Arrestare la sessione di debug e chiudere il pannello TERMINALE.
Scorrere fino alla fine del metodo
MakeChange.Le istruzioni
whileusate per "dare il resto" si trovano alla fine del metodoMakeChange.Esaminare i blocchi di codice dell'istruzione
whileusati per dare il resto.Dal momento che in cassa mancano cinque dollari, il problema è presumibilmente dovuto al blocco di codice
whileusato per restituire le banconote da cinque dollari.Si noti il codice seguente:
while ((changeNeeded > 4) && (cashTill[1] > 0)) { cashTill[2]--; changeNeeded -= 5; Console.WriteLine("\t A five"); }La matrice
cashTill[]viene usata per archiviare il numero di banconote di ogni taglio attualmente disponibili. L'elemento di matrice1viene usato per gestire il numero di banconote da cinque dollari in cassa. L'espressione nell'istruzionewhilefa riferimento acashTill[1]in modo corretto. Tuttavia, l'istruzione all'interno del blocco di codice decrementacashTill[2]anzichécashTill[1]. Se si specifica un valore di indice2, dalla cassa risulta rimossa una banconota da dieci dollari invece che da cinque.Aggiornare il blocco di codice
whilecome indicato di seguito:while ((changeNeeded > 4) && (cashTill[1] > 0)) { cashTill[1]--; changeNeeded -= 5; Console.WriteLine("\t A five"); }Salvare il file Program.cs.
Controlla il tuo lavoro
In questa attività si eseguirà l'applicazione e si verificherà che il codice aggiornato funzioni come previsto.
Nel menu Esegui di Visual Studio Code selezionare Rimuovi tutti i punti di interruzione.
Nel menu Esegui selezionare Avvia debug.
Esaminare l'output nel pannello TERMINALE.
Verificare che il valore di cassa riportato equivalga al valore di cassa previsto:
Il saldo di cassa finale calcolato da
MakeChangee il saldo gestito nelle istruzioni di primo livello sono riportati nella parte inferiore dell'output. Ad esempio:Transaction successfully completed. The till has 452 dollars Expected till value: 452 Press the Enter key to exitL'applicazione genera in modo casuale il costo degli articoli di acquisto. Pertanto, i valori di cassa riportati nell'output sono diversi. Se i due valori sono uguali, il problema di logica è stato risolto.