$ sudo teach IT

You’ve probably used code autocompletion or copied snippets from Stack Overflow. But with LLMs, coding moves to a new level. Now you can:

  • Generate a function from a task description
  • Write tests automatically
  • Review a pull request on the fly
  • Explain complex code as if to a junior

In this lesson, you’ll learn to give clear technical prompts and to use an LLM inside your editor — with GitHub Copilot, Continue, or the ChatGPT API.

📘 What You’ll Learn

  • How to correctly ask an LLM to generate or refactor code
  • How to write prompts for automated tests
  • How to conduct reviews via a prompt
  • How to explain someone else’s code in plain language
  • How to build a CLI interface based on prompt chains

📚 Key Terms

  • Refactoring — changing code structure without altering behavior. Improves readability and maintainability.
  • Prompt-chain — a chain of requests where the result of one step is used as input for the next (example: first generate code, then tests).
  • Pull request (PR) — a proposal to make changes to a GitHub repository, usually including code, a description, and discussion.
  • Continue.dev — a VS Code extension that integrates a GPT model locally or via API, letting you converse with code in the editor.
  • Copilot — a GitHub tool powered by OpenAI that offers code completion and generation right as you type.

🧱 Code Generation and Refactoring

Working with code via prompts is one of the most obvious and useful LLM use cases. The model can generate a function scaffold, help structure code, add checks, and then rewrite it to be more readable.

🧪 Prompt for generation:

Write a Python function that checks whether a string is a palindrome. Add a docstring and type annotations.

📌 Tips for code generation:

  • Specify the language: Python, JavaScript, Go — syntax and style depend on it.
  • Clarify the paradigm: “OOP style,” “using functional patterns.”
  • Add constraints:
    • “no loops,”
    • “O(n) complexity,”
    • “do not use third-party libraries.”
  • Output format:
    • return or print?
    • Answer as JSON?
    • Do you need logging?

📎 Analogy: You’re the architect describing what to build and from what, and the LLM is the experienced builder creating a turnkey draft. The more precise the spec, the fewer reworks.

🧹 Prompt for refactoring:

Rewrite the code below to improve readability and avoid duplication. Use modern ES6 practices.

📌 Refactoring tips:

  • Specify the goal: readability, performance, modularity.
  • Specify the style: “in the spirit of the Airbnb guide,” “as declarative as possible.”
  • Clarify whether to split code into functions or extract constants.
  • Ask the model to explain the changes — useful for learning.

📎 Analogy: You write a draft and hand it to an editor. They don’t change the meaning, but remove repetition, improve style, and format the text. Same with code — behavior stays, structure gets clearer.

📌 Before and After Examples

Before (duplication and poor readability):

function greet(user) {
  if (user === 'admin') {
    console.log('Welcome, admin!');
  } else if (user === 'guest') {
    console.log('Welcome, guest!');
  } else {
    console.log('Welcome, user!');
  }
}

After (ES6 refactor):

function greet(user) {
  const roles = {
    admin: 'Welcome, admin!',
    guest: 'Welcome, guest!',
  };
  console.log(roles[user] || 'Welcome, user!');
}

💡 Why this matters

  • Generation — quickly creates templates, especially for routine tasks.
  • Refactoring — saves time “cleaning up” someone else’s or legacy code.
  • Combination — generate first, then refactor — in 2 steps you can reach excellent code.

🧠 Combo prompt:

Generate a JavaScript function to sort an array of numbers (without using .sort()), then rewrite it in ES6 functional style with comments.

That’s a full scenario for a mid+ developer, checking generation, refactoring, and explanation.

🧪 Auto-Generating Tests

An LLM can significantly speed up writing tests, especially when:

  • you’ve just written a function and want to ensure it works,
  • you need to cover edge cases but fear missing something,
  • you want a quick test skeleton to refine manually later.

📌 The key idea: you describe what to test and which framework — and the LLM writes the tests.

🧾 Sample prompt:

Write unit tests for the function get_user_age(user_dict) that retrieves age from a dict. Use PyTest. Consider edge cases and erroneous input.

✅ What an LLM outputs:

import pytest
from my_module import get_user_age

def test_valid_age():
    assert get_user_age({"name": "Alice", "age": 30}) == 30

def test_missing_age():
    with pytest.raises(KeyError):
        get_user_age({"name": "Bob"})

def test_invalid_type():
    with pytest.raises(TypeError):
        get_user_age("not a dict")

📌 Prompt recommendations:

  • Specify the framework: PyTest, Jest, JUnit, Mocha — template differs.
  • Use phrasing like “cover edge cases” — the LLM will propose:
    • empty inputs,
    • incorrect types,
    • boundary values.
  • Clarify test format:
    • AAA: Arrange → Act → Assert
    • table-driven: tests via iterating arrays of inputs/outputs.
  • Add: “comment each test” — for learning or review.

🤖 Pros of auto-generation:

  • Speed — 10 tests in 10 seconds.
  • Typical coverage — standard checks (null, type errors, invalid keys).
  • Convenience — run immediately to see which cases you missed.

⚠️ Cons:

  • Poor awareness of side effects.

    The LLM won’t always check whether state changes (e.g., database).

  • No performance or security checks.

  • Redundancy: sometimes 5 near-duplicate tests add little value.

🧠 Using It Together with Code Generation

A powerful approach is to generate code and tests together. This lets you:

  • see how the model interprets your task,
  • automatically verify logic correctness,
  • find bugs faster and refine requirements.

💡 Combo prompt:

Write a function get_user_age(dict), then a set of PyTest tests covering edge cases.

📌 Why useful:

  • You get two artifacts at once: function and tests.
  • You can run tests immediately to verify behavior.
  • Easier to catch overlooked cases — especially for MVPs or learning.

🔍 Example model output:

# Function
def get_user_age(user_data):
    if not isinstance(user_data, dict):
        raise TypeError("Input must be a dictionary.")
    return user_data["age"]

# PyTest tests
import pytest

def test_valid_age():
    assert get_user_age({"name": "Alice", "age": 25}) == 25

def test_missing_age():
    with pytest.raises(KeyError):
        get_user_age({"name": "Bob"})

def test_invalid_input_type():
    with pytest.raises(TypeError):
        get_user_age("not a dict")

📎 Analogy: chef and taster in one

A chef cooks and immediately tastes. They instantly spot where it’s too salty, where a side is missing, and fix it on the spot.

The combo prompt does the same: first create, then test. It’s a more mature way to work with LLMs.

📌 Where it’s especially useful:

  • 👶 Education — students see one prompt influences both logic and verification.
  • 🚀 Fast MVPs — speed matters, production errors are unacceptable.
  • 🧪 Testing new features — result + check at once.
  • 🤖 Automated code generation — generate a function, save it, and run the test pipeline.

🔍 Code Review via LLM

One of the most useful, underrated cases: using an LLM as a helper in code review. Especially relevant when:

  • you work solo and lack a second pair of eyes,
  • the team is large and reviews take long,
  • you want a self-check before sending a PR.

📌 Principles of a good review prompt:

  1. Provide full context:
    • code (diff or full file),
    • PR description (what changed and why),
    • links to docs, task, or bug report.
  2. Split review into stages:
    • 1️⃣ Describe what this PR does
    • 2️⃣ Find possible problems or improvements
    • 3️⃣ Suggest alternatives
  3. Clarify focus:
    • style checks (PEP8, ESLint, Prettier),
    • performance (nested loops, complexity),
    • security (injections, validation, XSS).

🧪 Sample request:

Here’s a pull request:

Changes:
- Added PDF generation function
- Connected new library reportlab
- Updated report rendering logic

Here’s the code diff: [paste diff]

Analyze:
1. Does the code follow Python style?
2. Any performance or security issues?
3. What improvements can be made?

🧰 Helpful tools:

  • Continue.dev — embed review right in VS Code; ask the LLM “analyze this file.”
  • GitHub Copilot Chat — in-editor question: “what’s wrong with this piece of code?”

✅ Especially useful when:

  • 🧪 Before team review — catch obvious bugs early.
  • 🏗 With legacy code — get refactoring hints.
  • 🧑‍🏫 In education — students get explanations of why this is better.

🔄 Tips:

  • Use a “mentor + engineer” tone — ask not just for a list of errors, but for reasoned solutions.
  • Don’t stop at one prompt — add follow-ups: “Can you simplify this function?”, “Is there a way to extract this into a utility?”

💡 Explaining Someone Else’s Code

Explain this code to a junior developer. Avoid jargon, use analogies.

📌 Tips:

  • Specify the explanation level: “for a beginner,” “as for a student,” “for a manager.”
  • You can add “Provide a real-life analogy.”

📎 Example:

def is_even(n):
   return n % 2 == 0

Explanation:

The function checks whether a number divides by 2 with no remainder — then it’s even. It’s like splitting apples evenly between two people — if none is left over, the number is even.

🧨 Common Mistakes

  • 📉 “Make me a bot” — too broad a request
  • 🔄 Inconsistent chain: one step doesn’t pass data to the next
  • 🧩 Mixing tasks: generation and tests in one prompt — harder to debug

❓ FAQs

Q: How is Copilot different from ChatGPT?

A: Copilot is in-flow autocompletion; ChatGPT is prompt-based generation. Together — powerful.

Q: How do I avoid “hallucinations” in code?

A: Clarify the task, constrain context, ask for examples.

Q: Can I trust an LLM’s review?

A: As a first iteration — yes. Final decisions should be human.

📌 Summary

Today you learned:

  • How to use LLMs for generation, tests, and code review
  • How to formulate technical prompts correctly
  • How to explain code even if it isn’t yours
  • How to create a CLI assistant based on a prompt-chain

👉 These skills save hours of routine, improve code quality, and make working with LLMs practical, not magical.

На следующий урок