Op til eksamen på 1. år af datamatikeruddannelsen havde jeg tankerne kørende rundt i mit hoved, fordi jeg ikke havde nogen idé om, hvad der foregik i min kode, når jeg trykkede på start. Jeg vidste, at når jeg trykkede på knappen, så kørte programmet, og på magisk vis kunne min computer forstå den kode, jeg havde skrevet, og variablerne, jeg havde erklæret, samt ændre dem løbende. Men hvordan?
Jeg havde brug for et program eller en løsning, der gjorde, at jeg kunne se den kode, jeg havde skrevet, aktiveret, når jeg interagerede med de forskellige elementer i mit system. Det var ikke nok for min forståelse at se bilen køre; jeg ville se, hvordan motoren så ud, når den startede, når jeg trykkede på bremsen, og når jeg accelererede.
Jeg søgte på nettet efter en løsning og fandt ud af, at C# har en umiddelbart god løsning til dette formål:
Debug.WriteLine();
Jeg brugte denne metode flittigt i min kode.
Når jeg startede en metode op så skrev jeg
Debug.WriteLine("MethodName");
Det fungerede fint. Men strukturen i de beskeder, jeg modtog, var ofte meget simpel og kunne se således ud:
Metode1 start
variable1 = 1
Metode1 Slut
Og hvis du forestiller dig en ordentlig røvfuld metoder der sparker i gang, blev dette ikke lettere at læse.
Jeg manglede struktur i mit kodes debug-output. Derfor valgte jeg, lige inden eksamen, hurtigt at sammensætte et bibliotek, der senere kom til at hedde Debugland (mere om det senere).
Dette gjordre at min debug log kom til at se sådan ud:
[Metode1]
- Initiated
- The Variable Sovs has been declared with a value of Hollandaise
[/Metode1]
… og ved flere metoder, så koden sådan ud:
[Metode1]
- Initiated
- The Variable Sovs has been declared with a value of Hollandaise
[Metode2]
- Initiated
- The Variable tilbehør has been declared with a value of fritter
[/Metode2]
[/Metode1]
Denne struktur fungerede super godt for min forståelse af, hvad der skete, når jeg interagerede med mit system. Jeg fik svar på de spørgsmål, jeg havde til min kode, om hvad der præcist skete, når forskellige processer blev aktiveret under "kølerhjelmen" af systemet.
Det eneste problem ved implementeringen af Debugland i ens kode er, at det kan fylde ret meget. Når det er sagt, har det været guld værd for min forståelse af, hvad der sker under runtime.
Debugland
Som jeg lovede tidligere er her en lille præsentation af det bibliotek jeg lavede.
Udfordring
Jeg manglede en stuktur i den måde jeg fik vist de beskeder som jeg fik tilbage fra systemet når jeg kørte programmet.
Løsning
Lav en "wrapper" til C#'s Debug, som omslutter sprogets output i en mere struktureret form.
Kode kode kode
Det hele starter med MethodInitiated metoden fra biblioteket
[Conditional("DEBUG")]
public static void MethodInitiated(string methodName)
{
// Store the initial Debug.IndentLevel
int initialIndentLevel = Debug.IndentLevel;
// Writes the name of the method to the debug window for the initial level
Debug.WriteLine($"[{methodName}]");
// Enter the loop starting from 1 to initialIndentLevel (including 0)
for (int i = 1; i <= initialIndentLevel; i++)
{
// Adjusts the Debug.IndentLevel for each iteration
Debug.IndentLevel = i;
}
// After the loop, reset Debug.IndentLevel to the initial value
Debug.IndentLevel = initialIndentLevel + 1;
Debug.WriteLine($"{(char)26} initiated");
}
Denne sætter indenteringen for resten af koden og skriver at metoden, som man gerne vil vide mere om, er "initiated".
Det er dog vigtigt her at man altid for afsluttet med MethodTerminated metoden, da indenteringen ikke vil forløbe korrekt.
[Conditional("DEBUG")]
public static void MethodTerminated(string methodName)
{
// Gets the initial IndentLevel
Debug.IndentLevel += 0;
// unindents
Debug.Unindent();
// Writes the name of the method to the debug window.
Debug.WriteLine($"[/{methodName}]\n");
}
Og for mig var dette hele hulmen for at kunne få fornemmelsen af hvilken metode der aktiverede i en anden metode, som ændrede en variabel der gjorde gud ved hvad.
En Implementering af dette kunne for eksempel se sådan ud:
public void Metode1(int number)
{
Debugger.MethodInitiated(nameof(Metode1));
Debugger.MethodParameter($"{number}");
int a = 1;
Debugger.Variable("a",$"{a}");
Debugger.MethodTerminated(nameof(Metode1));
}
Rigtig mange linjer skal til for at man får fornemmelsen af hvad der sker. Men dette gav mig syn for sagen og jeg bruger ikke nær så mangler linjer mere.
Dette vil give følgende output, hvis vi siger at metoden aktiveres på følgende måde Metode1(1)
[Metode1]
- Initiated
- Parameter value was: 1
- The Variable a declared with the value of 1
[/Metode1]
Dette har været et uundværlig redskab for mig i arbejdet med forståelsen af hvad der sker når kode aktiveres
Nyt i Debugland
I den nyeste implementering er jeg gået til hvordan man får præsentereret fejl i C#. For mig er det nærmest latin.
Error reading the file. ---> System.IO.FileNotFoundException: Could not find file 'nonexistentfile.txt'.
at System.IO.FileSystem.OpenFile(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.ReadAllText(String path)
at Program.Main(String[] args) in C:\path\to\your\file.cs:line 10
… altså, hvis jeg kigger efter kan jeg da godt forså det. Men det er jo det. Jeg skal se efter. Jeg vil bare gerne have en lyn hurtig besked om hvad fejlen er, hvor den er og hvordan den eventuelt kan løses.
Jeg er kommet frem til følgende struktur:
1 | Exception Occurred in ---> [TestExceptionMethod]
2 | Time Stamp: 10/21/2024 8:51:16 AM
3 |
4 | Message: Test exception occurred
5 | Source: TestProject
6 | Target Site: Void LogException_Should_Format_Exception_Details_Correctly()
9 | Inner Exception:
- | Message: Inner exception occurred
- | Source:
- | Target Site:
14| Method: at TestProject.DebuggerTests.LogException_Should_Format_Exception_Details_Correctly()
15| File Path: /home/andreas/Documents/Projects/Debugland/TestProject/DebuggerTests.cs
16| Line Number: 45
17| throw new Exception(exceptionMessage, new Exception(innerExceptionMessage));
Dette er work in progress og er ikke langt op i repo endnu.
Mit arbejde med Debugland har været en rejse mod bedre forståelse af, hvad der sker under overfladen, når kode udføres. Ved at implementere en struktureret tilgang til debug-output har jeg ikke blot opnået indsigt i mine metoder og variabler, men også fået mere tillid til min evne til at identificere og rette fejl.
I takt med at jeg udvikler Debugland videre, håber jeg at kunne dele dette værktøj med andre, der står over for lignende udfordringer. En klar og struktureret måde at se, hvad der sker i koden, kan være afgørende for læring og fejlfinding, især for dem, der er tidligt i deres programmeringsrejse.
Jeg ser frem til at fortsætte med at forbedre Debugland og gøre det til en endnu mere værdifuld ressource for både mig selv og mine medudviklere. Med dette værktøj kan jeg lettere navigere i kompleksiteten af programmering og få det fulde udbytte af mine kodeskrivningsfærdigheder.
Tak fordi du læste med, og jeg håber, at mine erfaringer kan inspirere dig til at udforske og forbedre din egen tilgang til debugging og kodeforståelse.
link til Debugland
https://abarbesgaard.github.io/Debugland/
Top comments (0)