Coding Standards & Best Practices¶
JavaScript/Node.js Standards¶
Code Style¶
- Indentation: 4 spaces (as per existing code)
- Quotes: Single quotes for strings
- Semicolons: Not required (existing code doesn't use them)
- Line length: Keep reasonable, no hard limit
- Naming conventions:
- camelCase for variables and functions
- PascalCase for classes
- UPPER_SNAKE_CASE for constants
- Prefix private methods with underscore:
_validateAnswers()
Modern JavaScript¶
// ✅ Good - Use const by default
const answers = await this.prompt([...]);
// ✅ Good - Use arrow functions
const choices = (answers) => {
return answers.framework === 'sklearn' ? ['pkl', 'joblib'] : ['json'];
};
// ✅ Good - Use template literals
const message = `⚠️ ${framework} not implemented yet.`;
// ✅ Good - Use destructuring
const { framework, modelServer, deployTarget } = this.answers;
// ✅ Good - Use async/await
async prompting() {
const answers = await this.prompt([...]);
}
// ❌ Avoid - var keyword
var x = 5;
// ❌ Avoid - string concatenation
const message = '⚠️ ' + framework + ' not implemented yet.';
Yeoman Generator Patterns¶
Prompt Organization¶
Group related prompts into phases with clear console output:
console.log('\n📋 Project Configuration');
const projectAnswers = await this.prompt([...]);
console.log('\n🔧 Core Configuration');
const coreAnswers = await this.prompt([...]);
Conditional Prompts¶
Use when function for conditional prompts:
{
type: 'list',
name: 'modelFormat',
message: 'Model format?',
choices: (answers) => {
if (answers.framework === 'sklearn') {
return ['pkl', 'joblib'];
}
return ['json'];
},
when: answers => answers.framework !== 'transformers'
}
Answer Merging¶
Combine phase answers using spread operator:
Template Best Practices¶
EJS Syntax¶
<%# Comments - not rendered %>
<%= variable %> <%# Escaped output %>
<%- variable %> <%# Unescaped output %>
<% if (condition) { %>
Content
<% } %>
<% if (framework === 'sklearn') { %>
sklearn-specific content
<% } else if (framework === 'xgboost') { %>
xgboost-specific content
<% } %>
Shell Script Templates¶
#!/bin/bash
# Use template variables for configuration
PROJECT_NAME="<%= projectName %>"
REGION="<%= awsRegion %>"
# Include error handling
set -e
# Add helpful output
echo "Building <%= projectName %>..."
Python Templates¶
# Use proper imports
import os
import json
from typing import Optional, Dict, Any
# Use type hints
def load_model(model_path: str) -> Any:
"""Load model from path."""
pass
# Use f-strings for formatting
print(f"Loading model from {model_path}")
Error Handling¶
Generator Errors¶
// Use env.error for validation failures
if (!this.SUPPORTED_OPTIONS.frameworks.includes(framework)) {
this.env.error(`⚠️ ${framework} not implemented yet.`);
}
// Provide helpful error messages
if (!modelPath) {
this.env.error('Model path is required. Please provide a valid path.');
}
Template Errors¶
# In Python templates, use proper exception handling
try:
model = load_model(model_path)
except FileNotFoundError:
raise ValueError(f"Model not found at {model_path}")
except Exception as e:
raise RuntimeError(f"Failed to load model: {str(e)}")
Testing Standards¶
Generator Tests¶
const helpers = require('yeoman-test');
const assert = require('yeoman-assert');
describe('generator-ml-container-creator:app', () => {
it('creates expected files', async () => {
await helpers.run(path.join(__dirname, '../generators/app'))
.withPrompts({
projectName: 'test-project',
framework: 'sklearn',
modelFormat: 'pkl'
});
assert.file(['Dockerfile', 'requirements.txt']);
});
});
Test Organization¶
- One test file per generator
- Group related tests with
describeblocks - Use descriptive test names
- Test both success and failure cases
Documentation Standards¶
Code Comments¶
// Use comments to explain WHY, not WHAT
// Phase 1: Project Configuration
// Collect basic project info before framework-specific questions
// Document complex logic
// Transformers don't need traditional model handlers
// because they use vLLM/SGLang's built-in serving
if (this.answers.framework === 'transformers') {
ignorePatterns.push('**/code/model_handler.py');
}
JSDoc for Public Methods¶
/**
* Validates user answers against supported options.
* Throws error if unsupported configuration is detected.
* @private
*/
_validateAnswers() {
// implementation
}
README Updates¶
- Keep README in sync with features
- Include examples for new configurations
- Update troubleshooting section for common issues
- Document breaking changes
Git Commit Messages¶
Follow conventional commits format:
feat: add FastAPI support for sklearn models
fix: correct model path in transformer templates
docs: update README with new framework options
test: add tests for xgboost model formats
refactor: simplify prompt logic in core configuration
chore: update dependencies to latest versions
Security Best Practices¶
Dependency Management¶
- Run
npm auditregularly - Use
overridesin package.json for security patches - Keep Node.js and npm updated
- Review dependency changes in PRs
Template Security¶
// ❌ Don't include secrets in templates
const API_KEY = "hardcoded-key";
// ✅ Use environment variables
const API_KEY = process.env.API_KEY;
// ❌ Don't commit AWS credentials
AWS_ACCESS_KEY_ID=AKIA...
// ✅ Use IAM roles and AWS CLI profiles
Input Validation¶
// Validate user input
if (!projectName.match(/^[a-z0-9-]+$/)) {
this.env.error('Project name must contain only lowercase letters, numbers, and hyphens');
}
Performance Considerations¶
Template Processing¶
- Keep templates simple and focused
- Avoid complex logic in templates
- Use generator logic for complex decisions
- Cache computed values in
this.answers
File Operations¶
// ✅ Good - Single copyTpl call with ignore patterns
this.fs.copyTpl(
this.templatePath('**/*'),
this.destinationPath(),
this.answers,
{},
{ globOptions: { ignore: ignorePatterns } }
);
// ❌ Avoid - Multiple copyTpl calls
this.fs.copyTpl(this.templatePath('Dockerfile'), ...);
this.fs.copyTpl(this.templatePath('code/**'), ...);
Maintenance Guidelines¶
Adding New Features¶
- Check if it fits existing patterns
- Update SUPPORTED_OPTIONS constant
- Add prompts in logical phase
- Create/modify templates
- Update validation
- Add tests
- Update documentation
Deprecating Features¶
- Add deprecation warning in prompts
- Update documentation
- Keep backward compatibility for one major version
- Remove in next major version
Code Review Checklist¶
- Follows existing code style
- Includes tests
- Updates documentation
- Passes ESLint
- Passes security audit
- Works with all supported configurations
- Includes helpful error messages