> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Comment driven Development

> Explains comment-driven development using descriptive comments to generate scaffolding, validation, data pipelines, and tests, then review and refine generated code for correctness.

In this lesson, we explore comment-driven development: writing concise, descriptive comments to generate scaffolding — classes, validation, data-processing pipelines, and unit tests — then refining and validating the generated outputs. This workflow accelerates development for repetitive boilerplate while keeping you focused on high-value algorithmic and edge-case logic.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/DEYrDKSldd3lYPoS/images/GitHub-Copilot-in-Action/Core-Features/Comment-driven-Development/comment-driven-development-demo-slide.jpg?fit=max&auto=format&n=DEYrDKSldd3lYPoS&q=85&s=595f8d085a2021c7b9305cf4afcddc0e" alt="A presentation slide with the title &#x22;Comment-driven development&#x22; on the left and the word &#x22;Demo&#x22; highlighted on a dark curved shape on the right. A small copyright notice &#x22;© Copyright KodeKloud&#x22; appears in the bottom left." width="1920" height="1080" data-path="images/GitHub-Copilot-in-Action/Core-Features/Comment-driven-Development/comment-driven-development-demo-slide.jpg" />
</Frame>

Use comment-driven generation to create initial scaffolding quickly, then review and harden the produced code.

<Callout icon="lightbulb" color="#1CB2FE">
  Use comment-driven generation to create initial scaffolding quickly, but manually verify validation, edge cases, and algorithmic details afterwards.
</Callout>

## What this example includes (quick overview)

| Component                     | Purpose                                               | Key features                                                                                               |
| ----------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `Employee` class              | Demonstrates typed attributes with runtime validation | `name`, `age`, `salary` properties with setters that validate types and ranges                             |
| `process_stock_data`          | Process market data for simple analytics and signals  | Handles missing data, clips outliers, computes `SMA_50`, `SMA_200`, `daily_return`, `volatility`, `signal` |
| `validate_trading_parameters` | Lightweight pre-trade validation utility              | Ensures `price`, `volume`, and `symbol` have correct types and positive values                             |
| Tests (`pytest`)              | Example unit tests generated from the code context    | Checks structure and basic behavior of the processing function and validators                              |

## Full example: implementation (main.py)

The following consolidated example demonstrates a realistic scaffold that you might generate from well-formed comments. It keeps type hints, validation logic, and a stock-data processing method suitable for prototyping.

```python theme={null}
# main.py
from typing import Any
import pandas as pd
import numpy as np


class Employee:
    def __init__(self, name: str, age: int, salary: float) -> None:
        self.name = name
        self.age = age
        self.salary = salary

    @property
    def name(self) -> str:
        return self._name

    @name.setter
    def name(self, value: str) -> None:
        if not isinstance(value, str):
            raise TypeError("Name must be a string")
        if not value:
            raise ValueError("Name must not be empty")
        self._name = value

    @property
    def age(self) -> int:
        return self._age

    @age.setter
    def age(self, value: int) -> None:
        if not isinstance(value, int):
            raise TypeError("Age must be an integer")
        if value < 0:
            raise ValueError("Age must be non-negative")
        self._age = value

    @property
    def salary(self) -> float:
        return self._salary

    @salary.setter
    def salary(self, value: float) -> None:
        if not isinstance(value, (int, float)):
            raise TypeError("Salary must be a number")
        if value < 0:
            raise ValueError("Salary must be non-negative")
        self._salary = float(value)

    def process_stock_data(self, data: pd.DataFrame) -> pd.DataFrame:
        """
        Calculate moving averages, volatility, and trading signals.
        Handle missing data and outliers in a conservative, example manner.
        - Expects a DataFrame with a 'Close' column.
        - Adds columns: 'SMA_50', 'SMA_200', 'daily_return', 'volatility', 'signal'
        """
        if "Close" not in data.columns:
            raise KeyError("DataFrame must contain a 'Close' column")

        df = data.copy()

        # Handle missing data: forward-fill then drop remaining NaNs
        df["Close"] = df["Close"].ffill()
        df = df.dropna(subset=["Close"])

        # Calculate returns
        df["daily_return"] = df["Close"].pct_change()

        # Handle outliers in returns by clipping to mean +/- 3*std
        ret_mean = df["daily_return"].mean(skipna=True)
        ret_std = df["daily_return"].std(skipna=True)
        if pd.notna(ret_std) and ret_std != 0:
            lower = ret_mean - 3 * ret_std
            upper = ret_mean + 3 * ret_std
            df["daily_return"] = df["daily_return"].clip(lower, upper)

        # Calculate volatility and moving averages (examples: windows 50 and 200)
        df["volatility"] = df["daily_return"].rolling(window=50, min_periods=1).std()
        df["SMA_50"] = df["Close"].rolling(window=50, min_periods=1).mean()
        df["SMA_200"] = df["Close"].rolling(window=200, min_periods=1).mean()

        # Trading signal: 1 when short MA > long MA, -1 when short MA < long MA, else 0
        df["signal"] = np.where(df["SMA_50"] > df["SMA_200"], 1, np.where(df["SMA_50"] < df["SMA_200"], -1, 0))

        return df


def validate_trading_parameters(price: float, volume: int, symbol: str) -> bool:
    """Validate trading parameters before order execution"""
    if not isinstance(price, (int, float)):
        raise TypeError("Price must be a number")
    if not isinstance(volume, int):
        raise TypeError("Volume must be an integer")
    if not isinstance(symbol, str):
        raise TypeError("Symbol must be a string")

    if price <= 0:
        raise ValueError("Price must be positive")
    if volume <= 0:
        raise ValueError("Volume must be positive")

    return True


if __name__ == "__main__":
    employee = Employee("Alice", 30, 50000)
    print(employee.name)
    print(employee.age)
    print(employee.salary)
```

Example console output:

```bash theme={null}
$ python main.py
Alice
30
50000.0
```

## Example unit tests (test\_main.py)

Below is a compact pytest-based test module that checks structure and some basic expectations of the stock-processing pipeline and the trading parameter validator. Generated tests often focus on structure and obvious edge cases; review and extend them for numerical correctness and domain-specific behavior.

```python theme={null}
# test_main.py
import pandas as pd
import numpy as np
import pytest
import main


def test_process_stock_data_structure():
    # Short sample of closing prices (10 datapoints)
    data = pd.DataFrame({
        "Close": [100, 110, 120, 130, 140, 150, 160, 170, 180, 190]
    })
    emp = main.Employee("Alice", 30, 50000)
    processed = emp.process_stock_data(data)

    # Check expected columns exist
    for col in ["SMA_50", "SMA_200", "daily_return", "volatility", "signal"]:
        assert col in processed.columns

    # With only 10 rows, SMA_50 and SMA_200 will be present but many values will be computed using min_periods=1.
    # Ensure signal column contains only -1, 0, or 1
    assert set(processed["signal"].dropna().unique()).issubset({-1, 0, 1})


def test_validate_trading_parameters_valid():
    assert main.validate_trading_parameters(100.0, 10, "AAPL") is True


def test_validate_trading_parameters_invalid():
    with pytest.raises(TypeError):
        main.validate_trading_parameters("100", 10, "AAPL")
    with pytest.raises(ValueError):
        main.validate_trading_parameters(0, 10, "AAPL")
```

<Callout icon="warning" color="#FF6B6B">
  Generated code and tests are a starting point. Always inspect generated logic for correctness, numeric stability, and security issues before using in production.
</Callout>

## Best practices for comment-driven generation

* Write clear, concise comments describing the intended behavior and edge cases you care about (input shapes, allowed ranges, failure modes).
* Use generated code to scaffold structure and tests, but prioritize manual reviews for:
  * Validation logic (types and ranges)
  * Numerical stability (rolling windows, NaN handling, outlier treatment)
  * Performance-critical loops or IO
* Create targeted unit tests that assert domain-specific numerical expectations in addition to structural checks.
* Document assumptions directly in code docstrings so generated tests can pick up on them.

## Links and references

* pandas documentation: [https://pandas.pydata.org/docs/](https://pandas.pydata.org/docs/)
* numpy documentation: [https://numpy.org/doc/](https://numpy.org/doc/)
* pytest documentation: [https://docs.pytest.org/](https://docs.pytest.org/)

In the next lesson we'll apply comment-driven generation to build a fake data generator project for testing and prototyping.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/github-copilot-in-action/module/192b5dd0-981d-43ef-80e9-b4189b3877af/lesson/159f6e4d-16da-4bf2-9047-12d0bba43a28" />
</CardGroup>
