body by plants; thoughts by veganbeef
body by plants; thoughts by veganbeef

Subscribe to veganbeef

Subscribe to veganbeef
Share Dialog
Share Dialog


<100 subscribers
<100 subscribers
There’s a lot of writing out there on prompt engineering and model selection in pursuit of making AI agents smarter and more self-directed software engineers, but I’ve found that isn’t always enough to get consistently helpful results, especially when you’re trying to use AI to update older, more complex codebases alongside human engineers. The structure and style of your code can make a huge difference in how well AI can understand and intelligently extend it.
I’m not saying you need to go refactor everything right now, but if you’ve been feeling like your AI engineer is acting less like an expert and more like a junior intern, then gradually incorporating these ideas into your existing code will likely help.
The following code architecture and design guidelines are based on my personal experience using AI to edit existing projects and to clone and extend templates into new projects, ordered purely by my own raw gut feeling of how important they are:
Choose well-documented, mainstream technologies over custom solutions
Follow established approaches (MVC, Repository structures, React patterns) that AI recognizes
Use standard naming conventions for your language/framework
Stick to idiomatic code rather than clever implementations
Create many small, focused files (200-300 lines max)
Use nested directories that reflect logical relationships
Group by feature, not file type
One primary responsibility per file
src/
├── components/authentication/
│ ├── login-form.component.ts
│ └── registration-form.component.ts
├── services/user-management/
│ ├── user-profile.service.ts
│ └── user-preferences.service.ts
└── utils/validation/
├── email-validator.util.ts
└── password-strength-validator.util.ts
Use verbose, self-documenting names that explain purpose and context
Include units, types, and constraints when relevant
Don't worry about name length - clarity over brevity
// Good
const authenticatedUserWithPermissions = await fetchUser();
const isEmailAddressFormatValid = validateEmail(email);
const convertRawApiResponseToUserProfileData = (response) => { ... };
// Avoid
const user = await fetchUser();
const isValid = validateEmail(email);
const processData = (response) => { ... };
Add docstrings to all functions, classes, and complex logic
Include parameter types, return values, and usage examples
Document business logic and decision reasoning
Add inline comments for non-obvious code sections
/**
* Validates user email format and checks against blacklisted domains
* @param emailAddress - The email address to validate
* @param checkBlacklist - Whether to check against domain blacklist
* @returns True if email is valid and not blacklisted
* @example validateUserEmailAddress('user@example.com', true)
*/
export const validateUserEmailAddress = (
emailAddress: string,
checkBlacklist: boolean = true
): boolean => {
// Check basic email format first
const emailRegexPattern = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
if (!emailRegexPattern.test(emailAddress)) {
return false;
}
// Optional blacklist check for spam domains
if (checkBlacklist) {
return !isEmailDomainBlacklisted(emailAddress);
}
return true;
};
Extract all configuration into dedicated files, even if used in one place
Create utility functions for any logic that could be reused
Use clear, descriptive configuration objects
// config/database.config.ts
export const DATABASE_CONFIG = {
connectionTimeoutMs: 5000,
maxRetryAttempts: 3,
productionPoolSize: 20,
developmentPoolSize: 5
};
// utils/email-validation.util.ts
export const validateEmailAddressFormat = (email: string): boolean => {
// Implementation here
};
Use TypeScript or similar type systems for better AI understanding
Include README files in each major directory explaining purpose
Maintain consistent code formatting with automated tools
Use meaningful commit messages that explain the "why" not just "what"
Include unit tests with descriptive test names that explain expected behavior
You can of course use AI to implement these changes, but make sure to double check these types of changes, as mistakes here can be pernicious hard to find.
There’s a lot of writing out there on prompt engineering and model selection in pursuit of making AI agents smarter and more self-directed software engineers, but I’ve found that isn’t always enough to get consistently helpful results, especially when you’re trying to use AI to update older, more complex codebases alongside human engineers. The structure and style of your code can make a huge difference in how well AI can understand and intelligently extend it.
I’m not saying you need to go refactor everything right now, but if you’ve been feeling like your AI engineer is acting less like an expert and more like a junior intern, then gradually incorporating these ideas into your existing code will likely help.
The following code architecture and design guidelines are based on my personal experience using AI to edit existing projects and to clone and extend templates into new projects, ordered purely by my own raw gut feeling of how important they are:
Choose well-documented, mainstream technologies over custom solutions
Follow established approaches (MVC, Repository structures, React patterns) that AI recognizes
Use standard naming conventions for your language/framework
Stick to idiomatic code rather than clever implementations
Create many small, focused files (200-300 lines max)
Use nested directories that reflect logical relationships
Group by feature, not file type
One primary responsibility per file
src/
├── components/authentication/
│ ├── login-form.component.ts
│ └── registration-form.component.ts
├── services/user-management/
│ ├── user-profile.service.ts
│ └── user-preferences.service.ts
└── utils/validation/
├── email-validator.util.ts
└── password-strength-validator.util.ts
Use verbose, self-documenting names that explain purpose and context
Include units, types, and constraints when relevant
Don't worry about name length - clarity over brevity
// Good
const authenticatedUserWithPermissions = await fetchUser();
const isEmailAddressFormatValid = validateEmail(email);
const convertRawApiResponseToUserProfileData = (response) => { ... };
// Avoid
const user = await fetchUser();
const isValid = validateEmail(email);
const processData = (response) => { ... };
Add docstrings to all functions, classes, and complex logic
Include parameter types, return values, and usage examples
Document business logic and decision reasoning
Add inline comments for non-obvious code sections
/**
* Validates user email format and checks against blacklisted domains
* @param emailAddress - The email address to validate
* @param checkBlacklist - Whether to check against domain blacklist
* @returns True if email is valid and not blacklisted
* @example validateUserEmailAddress('user@example.com', true)
*/
export const validateUserEmailAddress = (
emailAddress: string,
checkBlacklist: boolean = true
): boolean => {
// Check basic email format first
const emailRegexPattern = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
if (!emailRegexPattern.test(emailAddress)) {
return false;
}
// Optional blacklist check for spam domains
if (checkBlacklist) {
return !isEmailDomainBlacklisted(emailAddress);
}
return true;
};
Extract all configuration into dedicated files, even if used in one place
Create utility functions for any logic that could be reused
Use clear, descriptive configuration objects
// config/database.config.ts
export const DATABASE_CONFIG = {
connectionTimeoutMs: 5000,
maxRetryAttempts: 3,
productionPoolSize: 20,
developmentPoolSize: 5
};
// utils/email-validation.util.ts
export const validateEmailAddressFormat = (email: string): boolean => {
// Implementation here
};
Use TypeScript or similar type systems for better AI understanding
Include README files in each major directory explaining purpose
Maintain consistent code formatting with automated tools
Use meaningful commit messages that explain the "why" not just "what"
Include unit tests with descriptive test names that explain expected behavior
You can of course use AI to implement these changes, but make sure to double check these types of changes, as mistakes here can be pernicious hard to find.
Designing AI-Compatible Code
If you feel like the quality of code suggestions from your AI agent of choice is inconsistent at best, it might be worth considering how easy it is for AI to understand your codebase -- check out this short guide I put together! https://paragraph.com/@veganbeef/designing-ai-compatible-code
do you guys also generate codebase summary/architecture design for AI?
wdym? there are some architecture design tips in the post that help with optimizing for AI, but it’s hard to be more detailed without knowing about the specific codebase in question
do you generate summary/architecture document for your codebase (any project ) and then include it in the context when you give a task?
Great tips. One small piece that I find superfluous is adding description to @params when already using descriptive symbol name. I used to do it because AI writes these redundant comments by default making me intuitively think it will help it *read* the code. After weeks of vibe-checking I don’t think it increases the efficiency of the output and ditched these comments altogether
Thank you for sharing
New insights from @veganbeef highlight that outdated code can hinder AI development. Tips for structured coding include using common libraries, modular file organization, descriptive naming, and strong documentation. Small incremental steps can lead to notably improved AI performance in codebases.
10 comments
Designing AI-Compatible Code
If you feel like the quality of code suggestions from your AI agent of choice is inconsistent at best, it might be worth considering how easy it is for AI to understand your codebase -- check out this short guide I put together! https://paragraph.com/@veganbeef/designing-ai-compatible-code
do you guys also generate codebase summary/architecture design for AI?
wdym? there are some architecture design tips in the post that help with optimizing for AI, but it’s hard to be more detailed without knowing about the specific codebase in question
do you generate summary/architecture document for your codebase (any project ) and then include it in the context when you give a task?
Great tips. One small piece that I find superfluous is adding description to @params when already using descriptive symbol name. I used to do it because AI writes these redundant comments by default making me intuitively think it will help it *read* the code. After weeks of vibe-checking I don’t think it increases the efficiency of the output and ditched these comments altogether
Thank you for sharing
This has the additional benefit of being better for human maintainers too!
True, tho humans are generally more capable of parsing “unreadable” code and not freaking out and suggesting some incomprehensible update 😂
New insights from @veganbeef highlight that outdated code can hinder AI development. Tips for structured coding include using common libraries, modular file organization, descriptive naming, and strong documentation. Small incremental steps can lead to notably improved AI performance in codebases.