During our work as software developers, we have seen and used comments many times. Usually, they are green lines of text telling us all kinds of things. The use of code comments can be a bit tricky and during my time as a C# teacher I have answered this question many times: What is the use of code comments?
The Basic Idea
There are many scenarios to think of where you might want to use code comments. But to do it right is not that easy. The idea of using comments is to clarify or give information about the code. Comments are not shown to the end users and are mostly used by developers. They don’t change the code and can’t be used to make code act differently. It’s purely for information purposes only.
A few scenarios where you want to use comments
- Mark a specific piece of code that needs attention.
 - Tell your other team members not to change the line of code. Otherwise, the method might break.
 - Add a to-do, so you don’t forget to change or add something.
 - Explain in detail what a method does.
 
These are just a few that come to mind. If I would combine that and use it in a class, it would look a bit like this:
// A class for all kind of movie activities, like get, delete, add, and more.
internal class MovieService
{
    private readonly List<Movie> _movies = new()
    {
        new Movie{ Id = 1, Rating = 10, Title = "Shrek"},
        new Movie{ Id = 2, Rating = 2, Title = "The Green Latern"},
        new Movie{ Id = 3, Rating = 7, Title = "The Matrix"},
        new Movie{ Id = 4, Rating = 4, Title = "Inception"},
        new Movie{ Id = 5, Rating = 8, Title = "The Avengers"},
    };
    // Gets all the movies from the list and orders them by title before returning
    public IEnumerable<Movie> GetAll()
    {
        // Return the movies and order by title
        return _movies.OrderBy(x => x.Title);
    }
    // Find and returns the movie by the given id, which is an int
    public Movie? Get(int id)
    {
        // Return and find the movie by the id, or null if not found.
        return _movies?.SingleOrDefault(x => x.Id == id);
    }
    // Checks if the title is filled, adds the unique id to the movie, 
    // adds the movie to the list of movies.
    public void Insert(Movie movie)
    {
        // If the title is incorrect, give an exception
        if (string.IsNullOrEmpty(movie.Title))
            throw new Exception("Title is required.");
        // ToDo: Check if rating is 0 or higher
        movie.Id = _movies.Max(x => x.Id) + 1; // Get the max id and add 1
        _movies.Add(movie); // Add the movie
    }
    // Deletes a movie by the given id, which is an int.
    public void Delete(int id)
    {
        // Get the movie from the list by calling get()
        Movie? toDelete = Get(id);
        // If movie is found, delete it.
        if (toDelete != null)
            _movies.Remove(toDelete);
    }
}
Maybe I have gone berserk on this simple class, but trust me when I say this happens. I saw something like this once:
// This method returns true
public bool ReturnTrue()
{
    // 1 equals 1, so it's true
    return 1 == 1;
}
Better
I hope you agree with me that both examples are a bit exaggerated. The second method is unnecessary. It would be better to remove it and change the method that uses this comment.
The first example does have some valid comments. Like explaining what the method does or what (and why) certain actions are taken. But, in my opinion, it’s more comment than actual code. I like to see my code and not comments.
All the first example’s comments are easily fixed using other tools and techniques. All the comments above a method or class, explaining the working of the code and contents, can be moved to a summary. A summary can be moved to an interface.
The ‘ToDo’ is a bit different. If it’s just one I tend to just leave it there. But chances are you might forget it. Most of the time a ToDo is something small. Why not do it as soon as you are in the code? Most standard reply I get:
“It’s out of scope with my work item on the scrum board“
Then make another work item so you can fix it later. This way you will see it later on the board and even your team members can fix it.
If you write good code you don’t have to explain them. Take line 44 of the first example. “Get the movie from the list by calling Get()”… Duh, I can see that on line 45. Code can be read as a language (hence programming language). If you write good code it’s self-explanatory. The same goes for the names of the methods: make them so others understand what the method is about.
If I would “fix” the first example it would look like this:
internal class MovieService: IMovieService
{
    private readonly List<Movie> _movies = new()
    {
        new Movie{ Id = 1, Rating = 10, Title = "Shrek"},
        new Movie{ Id = 2, Rating = 2, Title = "The Green Latern"},
        new Movie{ Id = 3, Rating = 7, Title = "The Matrix"},
        new Movie{ Id = 4, Rating = 4, Title = "Inception"},
        new Movie{ Id = 5, Rating = 8, Title = "The Avengers"},
    };
    public IEnumerable<Movie> GetAll()
    {
        return _movies.OrderBy(x => x.Title);
    }
    public Movie? Get(int id)
    {
        return _movies?.SingleOrDefault(x => x.Id == id);
    }
    public void Insert(Movie movie)
    {
        if (string.IsNullOrEmpty(movie.Title))
            throw new Exception("Title is required.");
        movie.Id = _movies.Max(x => x.Id) + 1;
        _movies.Add(movie);
    }
    public void Delete(int id)
    {
        Movie? toDelete = Get(id);
        if (toDelete != null)
            _movies.Remove(toDelete);
    }
}
This feels good; I see code!
Summaries
Imagine you create a library that will be used by other developers. It will contain some classes and methods. Each has its own functionality. However other developers don’t have access to the source code. So how do they know what the methods are about? Summaries.
I already mentioned them earlier and with the better version of the MovieService class (the one without the comments), I moved the descriptions of the methods and class to an interface. The interface looks like this:
/// <summary>
///  A class for all kind of movie activities, like get, delete, add, and more.
/// </summary>
internal interface IMovieService
{
    /// <summary>
    /// Gets all the movies from the list and orders them by title before returning
    /// </summary>
    /// <returns>A <see cref="List">list</see> with movies, ordered by Title.</returns>
    IEnumerable<Movie> GetAll();
 
    /// <summary>
    /// Find and returns the movie by the given id, which is an int.
    /// </summary>
    /// <param name="id">The unique identitifier of the movie which should be returned.</param>
    /// <returns>A single <see cref="Movie">movie</see> or NULL when not found.</returns>
    Movie? Get(int id);
    /// <summary>
    /// Adds a movie to the data source.
    /// </summary>
    /// <param name="movie">The <see cref="Movie">movie</see> to add</param>
    /// <exception cref="Exception">When the title is empty or NULL.</exception>
    void Insert(Movie movie);
    /// <summary>
    /// Deletes an existing movie from the data source.
    /// </summary>
    /// <param name="id">The unique identitifier of the movie which should be deleted.</param>
    void Delete(int id);
}
Summaries are comments that can be used for documentation. If you compile this to a DLL and another developer uses that DLL he/she can see the summaries when initializing and using your class. Some applications can extract those summaries and generate some sort of PDF as a manual if you wrote the summaries correctly.
The Triple-A
The only comment you could use is with unit testing. Here we use the so-called triple-A, which is not the roadside assistant. It stands for:
- Arrange
 - Act
 - Assert
 
And also in that order. It means you define the area where you arrange the unit test (prepare everything), act on the actual code you want to test, and where you use assertions to check if the test was successful, or not.
The following example is a unit test used in the tutorial Azure Computer Vision – Convert image to text.
public class ReceiptReaderTests
{
    [Theory]
    [InlineData("Images/Receipt1.jpg", "Rp197.200")]
    [InlineData("Images/Receipt2.jpg", "$56.73")]
    public async void Should_ReadReceipt(string image, string expected)
    {
        // Arrange
        ReceiptReader reader = new();
        // Act
        string result = await reader.Read(image);
        // Assert
        Assert.Contains(expected, result);
    }
}
Here you can see the different sections of the unit test.
Unnecessary Labeling
Have you ever been in a store where they label everything like crazy? Imagine you see a strawberry with a label on it that says ‘Strawberry’? Sounds silly, right? Do not do unnecessary labeling.

Although it sounds logical, this happens a lot in code. If the name is correct you don’t have to explain it with a label or a comment. Let’s take a look at a method:
internal class MovieService
{
    // This deletes the movie
    public void Delete(int id)
    {
        Movie? toDelete = Get(id);
        if (toDelete != null)
            _movies.Remove(toDelete);
    }
}
The name of the method doesn’t need an explanation, and yet it has one. I am in the MovieService class, which indicates all the methods in the class do something with movies. Delete indicates something will be deleted. Since I am still in the MovieService I can assume the delete will delete a movie. The comment “This deletes the movie” is worthless here.
If I would use this class and method somewhere in my application it looks like this:
MovieService movieService = new(); movieService.Delete(1);
Sometimes an explanation is needed. Take a look at the following code.
internal class MovieService
{
    // This deleted the movie. Vairable is the ID of the movie to be deleted
    public void MakeItHappen(int variable)
    {
        Movie? toDelete = Get(variable);
        if (toDelete != null)
            _movies.Remove(toDelete);
    }
}
Now I am going to initialize and use it again:
MovieService movieService = new(); movieService.MakeItHappen(1);
I have no idea what this method does. Yeah, something with movies. But “MakeItHappen”? Make what happen? And what is variable? Oh, wait! It’s in the comment.
It would be better to give the method and the variable a better name so everyone knows.
Using unlogical names and a bad explanation in the comment or summary can be disastrous. Before you know it people use something in a way they aren’t supposed to use.

Conclusion On The Use Of Code Comments
It’s not that I hate comments, not at all. It’s just that if you are not careful your code, the thing you need the most, can be overrun by green lines. Most of the comments I have seen in my career are redundant or just meaningless (1 equals 1, so it’s true).
The use of code comments can be a personal decision. Some people love it, some don’t, and then there are the people that are in the middle. But sometimes it also gives you a good laugh.
														



