Why i stopped writing comments

For many years i put a lot of time on writing comments in my code. Most good code articles advised "you must comment your code" so i followed it. It made sense and many times poor code would benefit from comments.

This is a piece of code that i would consider good (it's not real but it's closely based on real code):

function processEvents() {
    // get al dinner events that will happen in the next month.
    // If they are confirmed send a reminder, if not cancel it.
    // If an event has no invitees it means that no invitee has confirmed
    // so should be cancelled too
    const month = '07'
    const dinnerEvents = events.filter((event) => {
        return event.type === 'dinner' && event.month === month
    })

    dinnerEvents.map((event) => {
        if (event.confirmed) {
            sendReminder(event)
        } else {
            cancelEvent(event)
        }

        if (event.invitees.filter((invitee) => invitee.confirmed).length === 0) {
            cancelEvent(event)
        }
    })
}

From the code (and comments) you can see it's a simple method that would process a list of events and it would cancel some of them and send invitations for others. The code is, in my opinion, fairly understandable but that's not a guarantee that it would stay that way: we need to rely on the comments to understand the details of when an event would be cancelled for instance, and as those requirements change we know the comments will sooner or later become obsolete.

So some time ago i stopped considering code like that good and i started taking an extra step: after writing some code and making it work, i would write comments to clarify the code to myself, just like in the previous example. Then, the crucial step, i would refactor my code until the comments become redundant!

This is what i would consider now good code

const getDinnerEventsForNextMonth = (event) => {
    const nextMonth = '07'
    return event.type === 'dinner' && event.month === nextMonth
}

function shouldCancelEvent(event: CalendarEvent) {
    const hasConfirmedInvitees = getConfirmedInvitees(event).length > 0
    return !event.confirmed || !hasConfirmedInvitees
}

function getConfirmedInvitees(event: CalendarEvent) {
    return event.invitees.filter((invitee) => invitee.confirmed)
}

function main() {
    const dinnerEvents = events.filter(getDinnerEventsForNextMonth)

    dinnerEvents.map((event) => {
        if (shouldCancelEvent(event)) {
            cancelEvent(event)
        } else {
            sendReminder(event)
        }
    })
}

The code does the same but for me it has much more clear intent: as i read the main function it i can understand what event is processing and what are the actions that it can take on each event without having to deal with the implementation details. If i care about when an event should be cancelled i can step into that method. I get more information, always up-to-date, without any comments!

Whenever you're writing comments, it pays off to ask yourself can i write the code in a way so i don't need this comment?