Writing Easier Code Comments with ChatGPT
Tags: chatgpt, coding, beginners, programming
Published: 2024-03-10 14:39:20

In my journey with Playwright, I've discovered how ChatGPT can transform the often tedious task of writing code documentation and comments. This article, part of my series on exploring Playwright, aims to demonstrate just how ChatGPT streamlines this process, making it not only manageable but also efficient. By walking through a Playwright code example, I'll show how leveraging AI can elevate the quality of your code comments, ensuring your work is accessible and understandable to all. Join me as we delve into the benefits of integrating ChatGPT into our coding practices.

## The Value of Good Documentation

Good documentation is more than a best practice—it's a cornerstone of effective software development. Statistics from a GitHub survey highlight that 93% of developers consider poorly documented software a significant problem, directly impacting productivity and code quality. Well-documented code, complemented by thorough comments, ensures clarity and accessibility, allowing anyone to understand the work without consulting the original author. This habit not only facilitates smoother transitions and onboarding but also reduces the time spent deciphering code, proving essential in fast-paced development environments where direct communication might not always be possible. Personally, I strongly advocate for enriching code comments with links to resources or code snippets that inspired my solutions, enhancing the educational value of the documentation. This approach not only aids in understanding but also serves as a valuable resource for learning and navigating the codebase more effectively.

## Getting Started with ChatGPT for Documentation

To initiate using ChatGPT for generating documentation and comments, consider these prompt types:

- **Function Explanation Prompt**: "Describe the function and usage of this code:" followed by your code. Keywords like "function," "purpose," and "usage" guide ChatGPT to focus on the practical application and significance of the code.

- **Comment Generation Prompt**: "Add comments to this code snippet explaining its logic and any parameters it uses:" followed by the code. Keywords such as "add," "comment," "logic," and "parameters" signal ChatGPT to craft a concise explanation suitable for inline documentation.

- **Explain Code**: "Could you add good comments to explain the code to someone who hasn't built it?" Use keywords like "explain," "comments," and "code" to guide ChatGPT in creating clear, informative annotations for the code, making it understandable for someone unfamiliar with its creation.

Each prompt should be clear and direct, incorporating keywords relevant to the information you seek, such as "explain," "describe," "functionality," and "purpose."

## Practical Examples
In the upcoming section, we'll dive into two prompt types using the same code snippets to showcase how ChatGPT can vary its assistance in documenting code and generating comments. This comparative approach will illuminate the versatility and efficiency of AI in enhancing our coding practices, giving us a sneak peek into the evolving world of automated documentation. Full Chat see [here](https://chat.openai.com/share/8d7afece-3bff-45ff-ade8-c8c34264effe).

Original Code Snippet

```typescript
import { BrowserContext, Page, test as baseTest, chromium } from '@playwright/test';
import path from 'path';
import Landing from '../pages/landing';

export const test = baseTest.extend<{
  context: BrowserContext;
  extensionId: string;
  page: Page;
  landing: Landing;
}>({
  // parts of the setup for the persistent context from https://playwright.dev/docs/chrome-extensions#testing
  context: async ({}, use) => {
    const extPath = path.join(__dirname, '../../build');
    const context = await chromium.launchPersistentContext('', {
      args: [`--disable-extensions-except=${extPath}`, `--load-extension=${extPath}`],
    });
    await context.grantPermissions(['clipboard-read', 'clipboard-write']);
    await use(context);
  },
  extensionId: async ({ context }, use) => {
    let [background] = context.serviceWorkers();
    if (!background) background = await context.waitForEvent('serviceworker');

    const extId = background.url().split('/')[2];
    await use(extId);
  },
  page: async ({ context }, use) => {
    await use(context.pages()[0]);
  },
  landing: async ({ page }, use) => {
    await use(new Landing(page));
  },
});

export const { expect } = baseTest;
```

First prompt type: **Could you add good comments to explain the code to someone who hasn't built it?**
```typescript
// Import necessary modules from Playwright for browser automation and testing, 
// as well as the 'path' module for handling file paths, and the 'Landing' class 
// from a local module, assumed to be a page object model representation of a landing page.
import { BrowserContext, Page, test as baseTest, chromium } from '@playwright/test';
import path from 'path';
import Landing from '../pages/landing';

// Extend the base test context provided by Playwright with additional properties 
// for browser context, extension ID, page, and a specific page object (landing page).
export const test = baseTest.extend<{
  context: BrowserContext;
  extensionId: string;
  page: Page;
  landing: Landing;
}>({
  // Async function to create and configure a browser context for testing a Chrome extension.
  // This setup is part of testing Chrome extensions as per Playwright's documentation.
  context: async ({}, use) => {
    // Resolve the path to the extension's build directory.
    const extPath = path.join(__dirname, '../../build');
    // Launch a persistent browser context with the extension loaded and certain extensions disabled,
    // specifying the path to the extension to load.
    const context = await chromium.launchPersistentContext('', {
      args: [`--disable-extensions-except=${extPath}`, `--load-extension=${extPath}`],
    });
    // Grant permissions necessary for the extension to interact with the clipboard.
    await context.grantPermissions(['clipboard-read', 'clipboard-write']);
    // Use the context in the test.
    await use(context);
  },
  // Async function to extract the extension ID from the service worker associated with the extension.
  // This ID is needed to interact with the extension in the tests.
  extensionId: async ({ context }, use) => {
    // Attempt to retrieve the service worker for the extension.
    let [background] = context.serviceWorkers();
    // If not immediately available, wait for the service worker to become available.
    if (!background) background = await context.waitForEvent('serviceworker');

    // Extract the extension ID from the service worker's URL.
    const extId = background.url().split('/')[2];
    // Use the extension ID in the test.
    await use(extId);
  },
  // Async function to provide the first page in the browser context to the test.
  page: async ({ context }, use) => {
    // Use the first page opened in the context.
    await use(context.pages()[0]);
  },
  // Async function to create and provide an instance of the Landing page object for the test.
  // This allows for easy interaction with the landing page's elements and functionality.
  landing: async ({ page }, use) => {
    // Instantiate the Landing page object with the page provided by the test context.
    await use(new Landing(page));
  },
});

// Export the 'expect' assertion library from baseTest to be used in tests.
// This allows for using expect statements for assertions in the tests.
export const { expect } = baseTest;
```

Second prompt type: **add comments to this code snippet explaining its logic and any parameters it uses**

```typescript
// Import necessary modules from Playwright for browser automation and testing,
// the 'path' module for working with file and directory paths, and a page model for a landing page.
import { BrowserContext, Page, test as baseTest, chromium } from '@playwright/test';
import path from 'path';
import Landing from '../pages/landing';

// Extend the base test with additional configurations specific to the testing needs,
// including a browser context, extension ID, page instance, and an instance of a landing page model.
export const test = baseTest.extend<{
  context: BrowserContext; // The browser context in which the test will run
  extensionId: string; // The ID of the Chrome extension being tested
  page: Page; // A page instance for navigating and interaction
  landing: Landing; // An instance of the landing page model for specific interactions
}>({
  // Configure the browser context for testing Chrome extensions,
  // including setting up the path to the extension and launching a browser instance with it.
  context: async ({}, use) => {
    const extPath = path.join(__dirname, '../../build'); // Determine the path to the extension's build directory
    // Launch a persistent browser context with the extension loaded, disabling other extensions
    const context = await chromium.launchPersistentContext('', {
      args: [`--disable-extensions-except=${extPath}`, `--load-extension=${extPath}`],
    });
    // Grant the browser context permissions to read and write to the clipboard
    await context.grantPermissions(['clipboard-read', 'clipboard-write']);
    // Pass the configured context to the test
    await use(context);
  },
  // Retrieve and provide the extension's ID to the test environment by examining the service worker's URL.
  extensionId: async ({ context }, use) => {
    // Attempt to retrieve the service worker associated with the extension
    let [background] = context.serviceWorkers();
    // If no service worker is immediately available, wait for it to appear
    if (!background) background = await context.waitForEvent('serviceworker');

    // Extract the extension's ID from the service worker's URL
    const extId = background.url().split('/')[2];
    // Provide the extension ID to the test
    await use(extId);
  },
  // Provide the first page opened in the browser context to the test for interaction
  page: async ({ context }, use) => {
    await use(context.pages()[0]);
  },
  // Instantiate and provide the Landing page model to the test, facilitating interaction with the landing page
  landing: async ({ page }, use) => {
    await use(new Landing(page));
  },
});

// Re-export the 'expect' assertion library from baseTest, allowing for assertion use within tests
export const { expect } = baseTest;
```
## Conclusion
In our journey through using ChatGPT for code documentation, we explored its capability to craft detailed comments with two different prompt types. This versatility underscores ChatGPT's adaptability to various documentation needs. A future prospect that holds promise is incorporating the OpenAI API into GitHub actions or commit hooks. This integration could revolutionize the way we ensure our code is consistently well-documented. Nonetheless, the importance of human oversight cannot be overstated. It's crucial to meticulously review AI-generated comments, making necessary adjustments to truly capture the essence of the code, optimizing the blend of AI efficiency with human precision. This balance is key to leveraging AI in enhancing our coding practices, paving the way for a future where code is not just functional but also comprehensively documented and easily understandable.