| layout | title | parent | nav_order |
|---|---|---|---|
default |
Chapter 3: Refactoring & Optimization |
Continue Tutorial |
3 |
Welcome to the art of code improvement! While Continue excels at generating new code, its true power shines when refactoring and optimizing existing code. This chapter explores how Continue can help you modernize legacy code, improve performance, and maintain code quality.
Most teams struggle here because the hard part is not writing more code, but deciding clear boundaries for order, items, user so behavior stays predictable as complexity grows.
In practical terms, this chapter helps you avoid three common failures:
- coupling core logic too tightly to one implementation path
- missing the handoff boundaries between setup, execution, and validation
- shipping changes without clear rollback or observability strategy
After working through this chapter, you should be able to reason about Chapter 3: Refactoring & Optimization as an operating subsystem inside Continue Tutorial: Open-Source AI Coding Agents for IDE and CLI, with explicit contracts for inputs, state transitions, and outputs.
Use the implementation notes around total, Continue, item as your checklist when adapting these patterns to your own repository.
Continue can analyze your code and suggest improvements:
// Original problematic code
function processUsers(users) {
var result = [];
for (var i = 0; i < users.length; i++) {
if (users[i].active) {
result.push({
name: users[i].name,
email: users[i].email
});
}
}
return result;
}
// Continue suggests: "Refactor to use modern JavaScript features"
// Suggested improvement:
function processUsers(users) {
return users
.filter(user => user.active)
.map(user => ({
name: user.name,
email: user.email
}));
}# Continue identifies: "Inefficient list concatenation in loop"
# Original:
result = []
for item in items:
result = result + [item * 2] # Inefficient!
# Suggested optimization:
result = [item * 2 for item in items]// Original: Large, complex function
function processOrder(order) {
// Validate order
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
// Calculate total
let total = 0;
for (let item of order.items) {
total += item.price * item.quantity;
}
// Apply discount
if (order.discountCode) {
total = total * 0.9; // 10% discount
}
// Save to database
database.save(order);
return { orderId: order.id, total };
}
// Continue suggests decomposition:
function validateOrder(order) {
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
}
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
function applyDiscount(total, discountCode) {
return discountCode ? total * 0.9 : total;
}
function processOrder(order) {
validateOrder(order);
let total = calculateTotal(order.items);
total = applyDiscount(total, order.discountCode);
database.save(order);
return { orderId: order.id, total };
}// Original: Promise chains
function fetchUserData(userId) {
return api.getUser(userId)
.then(user => {
return api.getUserPosts(user.id)
.then(posts => {
return api.getUserComments(user.id)
.then(comments => {
return { user, posts, comments };
});
});
})
.catch(error => {
console.error('Error fetching user data:', error);
throw error;
});
}
// Continue suggests: "Modernize to async/await"
async function fetchUserData(userId) {
try {
const user = await api.getUser(userId);
const [posts, comments] = await Promise.all([
api.getUserPosts(user.id),
api.getUserComments(user.id)
]);
return { user, posts, comments };
} catch (error) {
console.error('Error fetching user data:', error);
throw error;
}
}# Continue suggests: "Add comprehensive error handling"
# Original:
def divide_numbers(a, b):
return a / b
# Enhanced version:
def divide_numbers(a, b):
try:
if b == 0:
raise ValueError("Cannot divide by zero")
if not isinstance(a, (int, float)) or not isinstance(b, (int, float)):
raise TypeError("Both arguments must be numbers")
return a / b
except ZeroDivisionError:
raise ValueError("Cannot divide by zero")
except TypeError as e:
raise TypeError(f"Invalid input types: {e}")
except Exception as e:
raise RuntimeError(f"Unexpected error during division: {e}")# Continue identifies: "O(n²) complexity can be optimized"
# Original inefficient code:
def has_duplicates(items):
for i in range(len(items)):
for j in range(i + 1, len(items)):
if items[i] == items[j]:
return True
return False
# Suggested optimization:
def has_duplicates(items):
return len(items) != len(set(items))// Continue suggests: "Optimize memory usage with generators"
function processLargeFile(filePath) {
const data = fs.readFileSync(filePath, 'utf8'); // Loads entire file into memory
const lines = data.split('\n');
return lines.map(line => processLine(line));
}
// Optimized version:
function* processLargeFile(filePath) {
const fileStream = fs.createReadStream(filePath, 'utf8');
let buffer = '';
for await (const chunk of fileStream) {
buffer += chunk;
const lines = buffer.split('\n');
buffer = lines.pop(); // Keep incomplete line
for (const line of lines) {
yield processLine(line);
}
}
// Process remaining buffer
if (buffer) {
yield processLine(buffer);
}
}# Continue suggests: "Optimize database queries with select_related"
# Original with N+1 queries:
def get_posts_with_authors():
posts = Post.objects.all()
result = []
for post in posts:
result.append({
'title': post.title,
'author_name': post.author.name, # Additional query per post!
'content': post.content
})
return result
# Optimized version:
def get_posts_with_authors():
posts = Post.objects.select_related('author').all()
return [{
'title': post.title,
'author_name': post.author.name, # No additional query!
'content': post.content
} for post in posts]// Continue suggests: "Improve variable naming for clarity"
const x = 10; // Unclear
const y = 20; // Unclear
// Better names:
const width = 10;
const height = 20;# Continue identifies: "Replace magic numbers with constants"
def calculate_price(quantity, item_type):
if item_type == 1: # What does 1 mean?
return quantity * 10.99
elif item_type == 2: # What does 2 mean?
return quantity * 15.50
# Improved version:
STANDARD_ITEM_PRICE = 10.99
PREMIUM_ITEM_PRICE = 15.50
ITEM_TYPE_STANDARD = 1
ITEM_TYPE_PREMIUM = 2
def calculate_price(quantity, item_type):
if item_type == ITEM_TYPE_STANDARD:
return quantity * STANDARD_ITEM_PRICE
elif item_type == ITEM_TYPE_PREMIUM:
return quantity * PREMIUM_ITEM_PRICE# Continue suggests: "Add comprehensive docstring"
def process_payment(amount, card_number, expiry_date):
# Missing documentation!
pass
# Enhanced version:
def process_payment(amount, card_number, expiry_date):
"""
Process a credit card payment.
Args:
amount (float): Payment amount in dollars
card_number (str): Credit card number (16 digits)
expiry_date (str): Expiry date in MM/YY format
Returns:
dict: Payment result with transaction ID and status
Raises:
ValueError: If payment details are invalid
PaymentError: If payment processing fails
Example:
>>> result = process_payment(99.99, "4111111111111111", "12/25")
>>> result['status']
'approved'
"""
pass// Continue suggests: "Separate business logic from presentation"
class UserManager {
constructor() {
this.users = [];
this.ui = new UserInterface();
}
addUser(userData) {
// Business logic mixed with UI
const user = this.validateUser(userData);
this.users.push(user);
this.ui.showSuccessMessage('User added successfully!');
this.ui.refreshUserList(this.users);
}
}
// Refactored version:
class UserService {
constructor(userRepository) {
this.userRepository = userRepository;
}
addUser(userData) {
const user = this.validateUser(userData);
return this.userRepository.save(user);
}
validateUser(userData) {
// Business logic only
if (!userData.name || !userData.email) {
throw new ValidationError('Name and email are required');
}
return { ...userData, id: generateId() };
}
}
class UserController {
constructor(userService, userView) {
this.userService = userService;
this.userView = userView;
}
async addUser(userData) {
try {
const user = await this.userService.addUser(userData);
this.userView.showSuccessMessage('User added successfully!');
this.userView.refreshUserList();
} catch (error) {
this.userView.showErrorMessage(error.message);
}
}
}# Continue suggests: "Implement dependency injection for testability"
class EmailService:
def __init__(self):
self.smtp_server = "smtp.gmail.com" # Hardcoded dependency
def send_email(self, to, subject, body):
# Implementation...
# Refactored version:
class EmailService:
def __init__(self, smtp_client=None):
self.smtp_client = smtp_client or SMTPLibClient("smtp.gmail.com")
def send_email(self, to, subject, body):
return self.smtp_client.send(to, subject, body)
# Usage:
email_service = EmailService(SMTPLibClient("smtp.company.com"))
# Now easily testable with mock SMTP client# Continue suggests: "Add missing test cases"
def is_valid_email(email):
return '@' in email and '.' in email
# Suggested comprehensive tests:
def test_is_valid_email():
# Valid emails
assert is_valid_email("user@example.com")
assert is_valid_email("test.email+tag@domain.co.uk")
# Invalid emails
assert not is_valid_email("invalid-email")
assert not is_valid_email("@domain.com")
assert not is_valid_email("user@")
assert not is_valid_email("")
assert not is_valid_email(None)// Continue suggests: "Add mocks for external dependencies"
const axios = require('axios');
class APIService {
async fetchData(endpoint) {
const response = await axios.get(endpoint);
return response.data;
}
}
// Suggested test with mocks:
const MockAdapter = require('axios-mock-adapter');
describe('APIService', () => {
let mock;
let apiService;
beforeEach(() => {
mock = new MockAdapter(axios);
apiService = new APIService();
});
afterEach(() => {
mock.restore();
});
it('should fetch data successfully', async () => {
const mockData = { id: 1, name: 'Test' };
mock.onGet('/api/data').reply(200, mockData);
const result = await apiService.fetchData('/api/data');
expect(result).toEqual(mockData);
});
});# In Continue chat, use refactoring commands:
/refactor - Suggest general refactoring improvements
/improve - Optimize performance
/modernize - Update to modern language features
/simplify - Reduce code complexity
/extract - Extract methods or variables
/rename - Suggest better naming
/document - Add documentation// Continue can refactor entire files or directories
// Select multiple files and use:
/refactor file - Apply refactoring to specific file
/refactor project - Analyze entire project for improvements
/refactor pattern - Refactor code following specific patterns- Make small, focused changes
- Test after each refactoring
- Commit frequently
- Use feature flags for risky changes
- Ensure refactored code maintains same functionality
- Keep comprehensive test suite
- Use automated tests to verify changes
- Generate before/after comparisons
- Document refactoring rationale
- Get team approval for architectural changes
- Benchmark before and after refactoring
- Monitor for regressions
- Set performance budgets
- Follow established coding standards
- Maintain consistent patterns across codebase
- Update team documentation
# Before: Long method with multiple responsibilities
def process_order(order):
# Validate order
if not order.items: raise ValueError("No items")
# Calculate total
total = sum(item.price * item.quantity for item in order.items)
# Apply tax
tax = total * 0.08
total += tax
# Save order
db.save(order)
# After: Extracted methods
def validate_order(order):
if not order.items:
raise ValueError("No items")
def calculate_total(order):
return sum(item.price * item.quantity for item in order.items)
def apply_tax(total, tax_rate=0.08):
return total * (1 + tax_rate)
def process_order(order):
validate_order(order)
total = calculate_total(order)
total = apply_tax(total)
db.save(order)// Before: Complex conditional logic
class PaymentProcessor {
process(payment) {
if (payment.type === 'credit_card') {
// Credit card processing logic
} else if (payment.type === 'paypal') {
// PayPal processing logic
} else if (payment.type === 'bank_transfer') {
// Bank transfer processing logic
}
}
}
// After: Polymorphic approach
class PaymentProcessor {
process(payment) {
const processor = this.getProcessor(payment.type);
return processor.process(payment);
}
getProcessor(type) {
const processors = {
credit_card: new CreditCardProcessor(),
paypal: new PayPalProcessor(),
bank_transfer: new BankTransferProcessor()
};
return processors[type];
}
}# Continue can suggest monitoring these metrics:
def calculate_code_metrics(code):
return {
'complexity': calculate_cyclomatic_complexity(code),
'maintainability': calculate_maintainability_index(code),
'duplication': calculate_code_duplication(code),
'test_coverage': calculate_test_coverage(code)
}// Before/after performance comparison
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite();
suite
.add('Original Implementation', () => {
// Original code
})
.add('Refactored Implementation', () => {
// Refactored code
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run();Excellent! You've learned how Continue can transform your code through intelligent refactoring and optimization. The ability to analyze existing code and suggest improvements is incredibly powerful for maintaining high-quality codebases.
In Chapter 4: Documentation & Comments, we'll explore how Continue can help you create comprehensive documentation and improve code readability through intelligent commenting.
Ready to document your code like a pro? Let's continue to Chapter 4: Documentation & Comments!
Generated by AI Codebase Knowledge Builder
Under the hood, Chapter 3: Refactoring & Optimization usually follows a repeatable control path:
- Context bootstrap: initialize runtime config and prerequisites for
order. - Input normalization: shape incoming data so
itemsreceives stable contracts. - Core execution: run the main logic branch and propagate intermediate state through
user. - Policy and safety checks: enforce limits, auth scopes, and failure boundaries.
- Output composition: return canonical result payloads for downstream consumers.
- Operational telemetry: emit logs/metrics needed for debugging and performance tuning.
When debugging, walk this sequence in order and confirm each stage has explicit success/failure conditions.
Use the following upstream sources to verify implementation details while reading this chapter:
- Continue Repository
Why it matters: authoritative reference on
Continue Repository(github.com). - Continue Docs
Why it matters: authoritative reference on
Continue Docs(docs.continue.dev). - Continue Releases
Why it matters: authoritative reference on
Continue Releases(github.com).
Suggested trace strategy:
- search upstream code for
orderanditemsto map concrete implementation paths - compare docs claims against actual runtime/config code before reusing patterns in production