16 KiB
optimize-current-code
When to Use
Use this command when you want to:
- Optimize performance of existing C# backend code
- Optimize React/TypeScript frontend code
- Improve code quality and maintainability
- Reduce technical debt
- Apply best practices to existing code
- Optimize database queries and API calls
- Improve bundle size and loading performance (frontend)
- Enhance memory usage and efficiency (backend)
Prerequisites
For C# Backend:
- .NET SDK installed (
dotnet --version) - Solution builds successfully
- Understanding of current code functionality
For React Frontend:
- Node.js and npm installed
- Dependencies installed (
npm install) - Application runs without errors
Execution Steps
Step 1: Identify Code Type and Scope
Determine what type of code needs optimization:
Ask user to confirm:
- Is this C# backend code or React frontend code?
- What specific file(s) or component(s) need optimization?
- Are there specific performance issues or goals?
If not specified:
- Analyze current file in editor
- Determine language/framework from file extension
- Proceed with appropriate optimization strategy
Step 2: Analyze Current Code
For C# Backend (.cs files):
Read and analyze the code for:
-
LINQ Query Optimization
- N+1 query problems
- Inefficient
ToList()calls - Missing
AsNoTracking()for read-only queries - Complex queries that could be simplified
-
Async/Await Patterns
- Missing
async/awaitfor I/O operations - Blocking calls that should be async
- Unnecessary
asynckeywords
- Missing
-
Memory Management
- Large object allocations
- String concatenation in loops
- Unnecessary object creation
- Missing
usingstatements for disposables
-
Code Structure
- Duplicate code
- Long methods (>50 lines)
- Complex conditional logic
- Missing abstractions
- Business logic in controllers
-
Database Operations
- Inefficient queries
- Missing indexes (suggest)
- Unnecessary data loading
- Transaction management
For React Frontend (.tsx/.ts files):
Read and analyze the code for:
-
Component Performance
- Unnecessary re-renders
- Missing
React.memo()for pure components - Missing
useMemo()for expensive calculations - Missing
useCallback()for callback props - Large components (>300 lines)
-
Data Fetching
- Using
useEffect()instead of TanStack Query - Missing loading states
- Missing error boundaries
- No data caching strategy
- Redundant API calls
- Using
-
Bundle Size
- Large dependencies
- Missing code splitting
- Missing lazy loading
- Unused imports
-
Code Structure
- Duplicate components
- Complex component logic
- Missing custom hooks
- Props drilling
- Inline styles/functions
-
Type Safety
- Missing TypeScript types
anytypes usage- Missing interface definitions
Step 3: Create Optimization Plan
Based on analysis, create prioritized optimization plan:
Priority 1 (Critical - Performance Impact):
- N+1 queries
- Memory leaks
- Blocking I/O operations
- Unnecessary re-renders
- Large bundle size issues
Priority 2 (High - Code Quality):
- Missing async/await
- Duplicate code
- Business logic in wrong layers
- Missing error handling
- Poor type safety
Priority 3 (Medium - Maintainability):
- Long methods/components
- Complex conditionals
- Missing abstractions
- Code organization
Present plan to user:
- Show identified issues
- Explain priority and impact
- Ask for confirmation to proceed
Step 4: Apply C# Backend Optimizations
Optimization 1: Fix N+1 Query Problems
Before:
var orders = await context.Orders.ToListAsync();
foreach (var order in orders)
{
order.Customer = await context.Customers.FindAsync(order.CustomerId);
}
After:
var orders = await context.Orders
.Include(o => o.Customer)
.ToListAsync();
Optimization 2: Add AsNoTracking for Read-Only Queries
Before:
public async Task<List<Product>> GetProductsAsync()
{
return await context.Products.ToListAsync();
}
After:
public async Task<List<Product>> GetProductsAsync()
{
return await context.Products
.AsNoTracking()
.ToListAsync();
}
Optimization 3: Move Business Logic from Controllers
Before (Controller):
[HttpPost]
public async Task<IActionResult> CreateOrder(OrderDto dto)
{
var order = new Order { /* mapping logic */ };
var total = 0m;
foreach (var item in dto.Items)
{
total += item.Price * item.Quantity;
}
order.Total = total;
await context.Orders.AddAsync(order);
await context.SaveChangesAsync();
return Ok(order);
}
After (Controller):
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderCommand command)
{
var result = await mediator.Send(command);
return Ok(result);
}
After (Service/Handler):
public class CreateOrderCommandHandler : IRequestHandler<CreateOrderCommand, OrderResult>
{
public async Task<OrderResult> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
{
var order = request.ToEntity();
order.CalculateTotal(); // Business logic in domain
await repository.AddAsync(order, cancellationToken);
return order.ToResult();
}
}
Optimization 4: Optimize String Operations
Before:
string result = "";
foreach (var item in items)
{
result += item.Name + ", ";
}
After:
var result = string.Join(", ", items.Select(i => i.Name));
Optimization 5: Improve LINQ Efficiency
Before:
var results = await context.Orders
.ToListAsync();
results = results.Where(o => o.Total > 100).ToList();
After:
var results = await context.Orders
.Where(o => o.Total > 100)
.ToListAsync();
Optimization 6: Add Caching for Expensive Operations
Before:
public async Task<List<Category>> GetCategoriesAsync()
{
return await context.Categories.ToListAsync();
}
After:
public async Task<List<Category>> GetCategoriesAsync()
{
var cacheKey = "all-categories";
if (cache.TryGetValue(cacheKey, out List<Category> categories))
{
return categories;
}
categories = await context.Categories
.AsNoTracking()
.ToListAsync();
cache.Set(cacheKey, categories, TimeSpan.FromMinutes(10));
return categories;
}
Step 5: Apply React Frontend Optimizations
Optimization 1: Replace useEffect with TanStack Query
Before:
function ProductList() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/products')
.then(res => res.json())
.then(data => {
setProducts(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <div>{products.map(p => <ProductCard key={p.id} {...p} />)}</div>;
}
After:
function ProductList() {
const { data: products, isLoading } = useQuery({
queryKey: ['products'],
queryFn: () => productsService.getAll()
});
if (isLoading) return <div>Loading...</div>;
return <div>{products?.map(p => <ProductCard key={p.id} {...p} />)}</div>;
}
Optimization 2: Memoize Expensive Calculations
Before:
function OrderSummary({ items }: { items: OrderItem[] }) {
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
const tax = total * 0.1;
const grandTotal = total + tax;
return <div>Total: ${grandTotal}</div>;
}
After:
function OrderSummary({ items }: { items: OrderItem[] }) {
const { total, tax, grandTotal } = useMemo(() => {
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
const tax = total * 0.1;
return { total, tax, grandTotal: total + tax };
}, [items]);
return <div>Total: ${grandTotal}</div>;
}
Optimization 3: Memoize Components
Before:
function ProductCard({ name, price, onAdd }: ProductCardProps) {
return (
<div className="card">
<h3>{name}</h3>
<p>${price}</p>
<button onClick={() => onAdd()}>Add</button>
</div>
);
}
After:
const ProductCard = React.memo(function ProductCard({ name, price, onAdd }: ProductCardProps) {
return (
<div className="card">
<h3>{name}</h3>
<p>${price}</p>
<button onClick={() => onAdd()}>Add</button>
</div>
);
});
Optimization 4: Use useCallback for Callbacks
Before:
function ProductList() {
const [cart, setCart] = useState([]);
return (
<div>
{products.map(p => (
<ProductCard
key={p.id}
{...p}
onAdd={() => setCart([...cart, p])}
/>
))}
</div>
);
}
After:
function ProductList() {
const [cart, setCart] = useState([]);
const handleAdd = useCallback((product: Product) => {
setCart(prev => [...prev, product]);
}, []);
return (
<div>
{products.map(p => (
<ProductCard
key={p.id}
{...p}
onAdd={() => handleAdd(p)}
/>
))}
</div>
);
}
Optimization 5: Extract Custom Hooks
Before:
function ProductList() {
const [products, setProducts] = useState([]);
const [filtered, setFiltered] = useState([]);
const [search, setSearch] = useState('');
useEffect(() => {
const results = products.filter(p =>
p.name.toLowerCase().includes(search.toLowerCase())
);
setFiltered(results);
}, [products, search]);
// render logic
}
After:
function useProductFilter(products: Product[], search: string) {
return useMemo(() =>
products.filter(p =>
p.name.toLowerCase().includes(search.toLowerCase())
),
[products, search]
);
}
function ProductList() {
const [search, setSearch] = useState('');
const { data: products } = useQuery(['products'], getProducts);
const filtered = useProductFilter(products ?? [], search);
// render logic
}
Optimization 6: Implement Code Splitting
Before:
import { HeavyComponent } from './HeavyComponent';
function App() {
return <HeavyComponent />;
}
After:
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
Optimization 7: Fix Type Safety
Before:
function processData(data: any) {
return data.map((item: any) => item.value);
}
After:
interface DataItem {
id: string;
value: number;
}
function processData(data: DataItem[]): number[] {
return data.map(item => item.value);
}
Step 6: Verify Optimizations
For C# Backend:
-
Build solution:
dotnet build src/Managing.sln- Ensure no compilation errors
- Check for new warnings
-
Run tests (if available):
dotnet test src/Managing.sln- Verify all tests pass
- Check for performance improvements
-
Review changes:
- Ensure business logic unchanged
- Verify API contracts maintained
- Check error handling preserved
For React Frontend:
-
Check TypeScript:
npm run type-check- Ensure no type errors
-
Run linter:
npm run lint- Fix any new linting issues
-
Test component:
npm run test:single test/path/to/component.test.tsx- Verify component behavior unchanged
-
Check bundle size:
- Look for improvements in bundle size
- Verify lazy loading works
-
Manual testing:
- Test component functionality
- Verify no regressions
- Check loading states
- Verify error handling
Step 7: Document Changes
Create summary of optimizations:
Changes made:
- List each optimization
- Show before/after metrics (if available)
- Explain impact of changes
Performance improvements:
- Query time reductions
- Memory usage improvements
- Bundle size reductions
- Render time improvements
Code quality improvements:
- Better type safety
- Reduced duplication
- Better separation of concerns
- Improved maintainability
Common Optimization Patterns
C# Backend Patterns
-
Repository Pattern with Specification
- Encapsulate query logic
- Reusable query specifications
- Better testability
-
CQRS with MediatR
- Separate read/write operations
- Better performance tuning
- Cleaner code organization
-
Caching Strategy
- In-memory cache for frequent reads
- Distributed cache for scalability
- Cache invalidation patterns
-
Async Best Practices
- Use
async/awaitconsistently - Avoid
Task.Resultor.Wait() - Use
ConfigureAwait(false)in libraries
- Use
React Frontend Patterns
-
Data Fetching Pattern
- Always use TanStack Query
- Implement proper error boundaries
- Use suspense for loading states
-
Component Composition
- Split large components
- Create reusable atoms/molecules
- Use compound component pattern
-
State Management
- Keep state as local as possible
- Use context sparingly
- Consider Zustand for global state
-
Performance Pattern
- Memoize expensive operations
- Use React.memo for pure components
- Implement virtualization for long lists
Error Handling
If build fails after C# optimization:
- Review changes carefully
- Check for type mismatches
- Verify async/await patterns correct
- Rollback if necessary
If types break after frontend optimization:
- Check interface definitions
- Verify generic types
- Update type imports
If tests fail after optimization:
- Review test expectations
- Update mocks if needed
- Verify behavior unchanged
If performance degrades:
- Review optimization approach
- Check for introduced inefficiencies
- Consider alternative approach
Important Notes
- ✅ Always test after optimization - Verify functionality unchanged
- ✅ Measure performance - Use profiling tools to verify improvements
- ✅ Keep it simple - Don't over-optimize premature code
- ✅ Follow patterns - Use established patterns from codebase
- ⚠️ Avoid premature optimization - Focus on actual bottlenecks
- ⚠️ Maintain readability - Don't sacrifice clarity for minor gains
- 📊 Profile first - Identify real performance issues before optimizing
- 🧪 Test thoroughly - Ensure no regressions introduced
- 📝 Document changes - Explain why optimizations were made
Example Execution
User input: /optimize-current-code
AI execution:
- Identify code type: React component (ProductList.tsx)
- Analyze code: Found useEffect for data fetching, no memoization
- Present plan:
- Replace useEffect with TanStack Query
- Add React.memo to child components
- Extract custom hooks
- Apply optimizations (show diffs)
- Verify: Run type-check and tests
- Summary: "✅ Optimized ProductList component - replaced useEffect with TanStack Query, memoized child components"
For C# backend:
- Identify code type: Service class with database operations
- Analyze code: Found N+1 query, missing AsNoTracking, business logic
- Present plan:
- Fix N+1 with Include
- Add AsNoTracking for read-only
- Move business logic to domain
- Apply optimizations
- Verify: Build and test
- Summary: "✅ Optimized OrderService - eliminated N+1 queries, added AsNoTracking, moved business logic to domain layer"