Skip to main content

1.6 - Code Comments and Readability

Writing code that works is important, but writing code that other developers (and your future self) can understand is equally crucial. In this section, we'll explore how to use comments effectively and follow best practices for code readability.

The Importance of Readable Code

Imagine you're playing a game where you need to decipher cryptic messages. It might be fun as a game, but when you're trying to fix a bug or add a feature to existing code, cryptic code is frustrating and time-consuming to work with.

Well-written, readable code:

  • Is easier to debug and maintain
  • Facilitates collaboration with other developers
  • Reduces the likelihood of introducing bugs during modifications
  • Makes your codebase more professional and sustainable

Types of Comments in C#

C# supports three types of comments:

1. Single-line Comments

Single-line comments start with // and continue until the end of the line:

// This is a single-line comment
int score = 100; // This comment is at the end of a line of code

Use single-line comments for brief explanations or notes about the code.

2. Multi-line Comments

Multi-line comments start with /* and end with */. Everything between these markers is treated as a comment, even if it spans multiple lines:

/* This is a multi-line comment.
It can span multiple lines.
The compiler ignores everything between the opening and closing markers. */

int health = 100; /* This is also a multi-line comment,
though it's used inline with code */

Use multi-line comments for longer explanations or when you need to temporarily disable blocks of code during development (though modern IDEs offer better ways to do this).

3. XML Documentation Comments

XML documentation comments start with /// and are used to generate documentation for your code. They use XML tags to structure the documentation:

/// <summary>
/// Calculates damage based on attack power and defense.
/// </summary>
/// <param name="attackPower">The attacker's power level</param>
/// <param name="defense">The defender's defense level</param>
/// <returns>The amount of damage dealt</returns>
public int CalculateDamage(int attackPower, int defense)
{
return Math.Max(0, attackPower - defense);
}

XML documentation comments are especially useful in Unity because they appear as tooltips in the Inspector when you hover over public fields and methods.

Common XML tags include:

  • <summary>: A description of the method or class
  • <param>: Description of a parameter
  • <returns>: Description of the return value
  • <exception>: Documents exceptions that might be thrown
  • <remarks>: Additional information

Best Practices for Using Comments

Do:

  1. Explain "why" rather than "what": The code itself shows what it does; comments should explain why it's done that way.

    // BAD: Increment score by 10
    score += 10;

    // GOOD: Add bonus points for collecting a rare item
    score += 10;
  2. Comment complex algorithms or non-obvious solutions:

    // Using binary search to find the item in the sorted inventory
    // This is O(log n) complexity instead of O(n) for a linear search
    int index = Array.BinarySearch(inventory, itemToFind);
  3. Use comments to mark TODO items or potential improvements:

    // TODO: Implement difficulty scaling based on player level
    // FIXME: This calculation doesn't account for critical hits
  4. Document public APIs with XML comments:

    /// <summary>
    /// Applies damage to the character and checks if they are defeated.
    /// </summary>
    /// <param name="damageAmount">Amount of damage to apply</param>
    /// <returns>True if the character is defeated, false otherwise</returns>
    public bool TakeDamage(int damageAmount)
    {
    // Implementation...
    }

Don't:

  1. Don't state the obvious:

    // BAD: Declare a variable to store the player's health
    int playerHealth = 100;
  2. Don't leave commented-out code in production:

    // BAD: Leaving old implementations in the code
    // Old way:
    // for (int i = 0; i < enemies.Length; i++)
    // {
    // enemies[i].Attack();
    // }

    // New way:
    foreach (Enemy enemy in enemies)
    {
    enemy.Attack();
    }
  3. Don't write misleading or outdated comments:

    // BAD: Comment doesn't match the code
    // Calculate total damage including critical multiplier
    int damage = attackPower - defense; // No critical multiplier here!

Beyond Comments: Self-Documenting Code

While comments are useful, the best code is often "self-documenting"—written so clearly that it needs minimal explanation. Here are some techniques:

1. Use Descriptive Names

Choose meaningful names for variables, methods, and classes:

// Poor naming
int x = GetY(z);

// Better naming
int playerScore = CalculateScore(playerActions);

2. Keep Methods Short and Focused

Each method should do one thing and do it well:

// Instead of one large method that does everything:
public void UpdateGameState()
{
CheckPlayerInput();
UpdateEnemyPositions();
CheckCollisions();
UpdateUI();
}

3. Use Enums for Magic Numbers

Replace "magic numbers" with named constants or enums:

// Poor practice
if (playerState == 0)
{
// Handle idle state
}

// Better practice
enum PlayerState { Idle, Walking, Running, Jumping }

if (playerState == PlayerState.Idle)
{
// Handle idle state
}

4. Follow Consistent Formatting

Consistent indentation, spacing, and brace placement make code easier to scan:

// Consistent formatting example
public void ProcessItems(List<Item> items)
{
foreach (Item item in items)
{
if (item.IsRare)
{
ProcessRareItem(item);
}
else
{
ProcessCommonItem(item);
}
}
}

C# Coding Conventions

Microsoft and the C# community have established coding conventions that most C# developers follow. Here are some key conventions:

  1. PascalCase for class names, method names, and public members:

    public class PlayerController
    {
    public void UpdatePosition() { }
    }
  2. camelCase for local variables and private fields:

    private int playerHealth;

    public void TakeDamage(int damageAmount)
    {
    int remainingHealth = playerHealth - damageAmount;
    }
  3. Prefix interfaces with "I":

    public interface IDestructible
    {
    void TakeDamage(int amount);
    }
  4. Use meaningful namespace names:

    namespace GameCompany.ProjectName.Gameplay
    {
    // Classes related to gameplay
    }

Practical Example: Commenting a Game Function

Let's look at a practical example of how to comment a function in a game context:

/// <summary>
/// Applies damage to an enemy and handles defeat logic.
/// </summary>
/// <param name="enemy">The enemy to damage</param>
/// <param name="damageAmount">Amount of damage to apply</param>
/// <param name="isCritical">Whether this is a critical hit</param>
/// <returns>True if the enemy was defeated, false otherwise</returns>
public bool DamageEnemy(Enemy enemy, int damageAmount, bool isCritical)
{
// Validate input parameters
if (enemy == null || damageAmount < 0)
{
return false;
}

// Apply critical hit multiplier if applicable
int actualDamage = damageAmount;
if (isCritical)
{
// Critical hits do 50% more damage
actualDamage = (int)(damageAmount * 1.5f);
}

// Apply damage reduction based on enemy armor
// Formula derived from game design document section 3.2
actualDamage -= enemy.ArmorValue / 2;

// Ensure minimum damage of 1
actualDamage = Math.Max(1, actualDamage);

// Apply the damage to the enemy
enemy.Health -= actualDamage;

// Check if enemy is defeated
bool isDefeated = enemy.Health <= 0;
if (isDefeated)
{
// TODO: Add special effects for enemy defeat
enemy.PlayDefeatAnimation();

// Award experience points to the player
player.AddExperience(enemy.ExperienceValue);
}

return isDefeated;
}

Notice how the comments explain the "why" behind certain decisions, document the damage formula's source, and mark areas for future improvement.

Conclusion

Good commenting and code readability practices are essential skills for any programmer. They make your code more maintainable, facilitate collaboration, and reduce the time spent debugging. As you continue your C# journey, strive to write code that is both functional and readable.

In Unity development, these practices become even more important as you collaborate with artists, designers, and other programmers who may need to understand and work with your code.

Unity Relevance

In Unity:

  • XML documentation comments appear as tooltips in the Inspector
  • Clear, well-commented code is essential when working with designers who may have less programming experience
  • Unity's component-based architecture makes well-named, focused methods particularly important
  • Many Unity projects are long-lived and maintained by changing teams, making readable code crucial

Now that you've completed Module 1, you have a solid understanding of what programming is, how C# fits into the .NET ecosystem, how to set up your development environment, and how to write basic C# programs with good commenting practices. In Module 2, we'll dive deeper into C# fundamentals, exploring variables, data types, and operators.