Over the past year, I’ve started heavily using AI tools like Cursor and ChatGPT in my everyday development workflow. They’re not a replacement for thinking, but I found them as excellent assistants for learning, debugging, refactoring, and accelerating implementation work.
In addition, I’ll soon start working with a company to train their developers on using AI tools in everyday development, as part of a Ruby on Rails training program. So I wanted to write down some common patterns I’ve observed in my own workflow, plus the patterns I’ve come across from other experienced developers and the ones I found online.
Btw, this is by no means an exhaustive list; if you know more patterns and best practices, I'd love to hear them. Also, I'm not sharing them as an AI expert / influencer, just a fellow practitioner and user of these tools.
- the usefulness of these tools depends directly on the quality of your prompts
- understand before you vibe
- verify your understanding
- make the model understand the related code
- plan and design incrementally
- refactor with explicit goals (perf / idiomatic / readability)
- Use them as rubber-ducks
The very first thing to know is that the usefulness of these tools depends directly on the quality of your prompts. Garbage in, garbage out. Vague input leads to vague output and hallucinations. Precise, context-rich prompts are far more likely to produce relevant, specific, and useful responses.
Understand before you vibe. Before asking ChatGPT or Cursor to implement a feature, I'll often use them to understand how related code works. I’ll give it a controller or model class and ask for a deep dive. "I want to understand how this {feature/function/class/module} works. Please analyze the relevant code and give me a detailed explanation."
Verify your understanding. Once I’ve got a good understanding of the related code, I proceed with building the feature. "Here’s my {understanding}. Is this correct? If not, what am I missing?"
Make the model understand the code it will be working on. I like to treat these tools as fellow developers. Before asking them to build a feature, ask them to do a deep-dive in the codebase to understand how the existing, related code works. Then ask them to summarize their understanding. Make sure you understand it and only then provide the feature specification and ask them for implementation.
Don’t ask vague questions like “Why isn’t my code working?”. Instead, structure the problem clearly. "Here is the {problem}. Here is the {code}. It should do {this}. Currently it’s doing {this}. Why?"
This helps the model reason through the bug more effectively. If a function should return a particular output for a specific input, say so explicitly. The clarity and understanding benefits both you and the model. "This function should return {this}, when the input is {this}. Implement / fix the function."
Plan and design incrementally, don't one-shot it. When working on a new feature, I usually start with this: "I’m building {feature}. Here are the {requirements}. First, give me high-level implementation strategy. Then we’ll implement it step-by-step."
Once I have that, I work through the implementation step-by-step, either myself or with Cursor generating suggestions inline. For large or complex features, the best practice is to break them into smaller subproblems first. Once the plan is clear, you can feed each part into Cursor and implement iteratively.
Refactoring and code reviews. "Here’s the {function/class}. Refactor it for readability / performance / idiomatic Ruby/Go." The responses are not always perfect, but they often give new ideas or help me evaluate tradeoffs. Sometimes I’ll use ChatGPT to compare two versions of a function or summarize the differences.
When I encounter unfamiliar code or behavior, I write down my understanding and ask: "This is my {understanding}, Is this correct? If not, what am I missing?" This is useful for identifying gaps in my mental model, especially when dealing with metaprogramming, concurrency, or deep Rails internals.
To squeeze the most benefit and effectiveness out of these wonderful tools:
- Ask specific, structured questions
- Confirm understanding before implementing
- Break large problems into manageable chunks
- Treat them as code reviewers and rubber ducks
Remember the classic advice from Jeff Atwood (Coding Horror), creator of Stack Overflow, which equally applies to working with AI tools:
- Describe what’s happening in sufficient detail that we can follow along. Provide the necessary background for us to understand what’s going on, even if we aren’t experts in your particular area.
- Tell us why you need to know the answer. What led you here? Is it idle curiosity or is this somehow blocking you on a project? We don’t need your whole life story, just give us some context here.
- Share your research on your problem; what have you found so far? Why didn’t it work? And if you didn’t do any research… should you even be asking? If you’re inviting us to spend our valuable time helping you, it’s only fair that you put in a reasonable amount of your valuable time into crafting a decent question. Help us help you!
Same goes for AI. Help it to help you!
That's a wrap. I hope you found this article helpful and you learned something new.
As always, if you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I reply to all emails I get from developers, and I look forward to hearing from you.
If you'd like to receive future articles directly in your email, please subscribe to my blog. Your email is respected, never shared, rented, sold or spammed. If you're already a subscriber, thank you.