DEV Community

Cover image for Jeg forstår det simpelthen ikke
Andreas Barbesgaard
Andreas Barbesgaard

Posted on

Jeg forstår det simpelthen ikke

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(); 
Enter fullscreen mode Exit fullscreen mode

Jeg brugte denne metode flittigt i min kode.

Når jeg startede en metode op så skrev jeg

Debug.WriteLine("MethodName");
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

… 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]
Enter fullscreen mode Exit fullscreen mode

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.

Image description

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");
   }
Enter fullscreen mode Exit fullscreen mode

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");
}
Enter fullscreen mode Exit fullscreen mode

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)); 
}
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

… 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));
Enter fullscreen mode Exit fullscreen mode

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)