Files
managing-apps/.cursor/commands/optimize-current-code.md
2025-11-11 04:09:45 +07:00

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:

  1. LINQ Query Optimization

    • N+1 query problems
    • Inefficient ToList() calls
    • Missing AsNoTracking() for read-only queries
    • Complex queries that could be simplified
  2. Async/Await Patterns

    • Missing async/await for I/O operations
    • Blocking calls that should be async
    • Unnecessary async keywords
  3. Memory Management

    • Large object allocations
    • String concatenation in loops
    • Unnecessary object creation
    • Missing using statements for disposables
  4. Code Structure

    • Duplicate code
    • Long methods (>50 lines)
    • Complex conditional logic
    • Missing abstractions
    • Business logic in controllers
  5. Database Operations

    • Inefficient queries
    • Missing indexes (suggest)
    • Unnecessary data loading
    • Transaction management

For React Frontend (.tsx/.ts files):

Read and analyze the code for:

  1. 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)
  2. Data Fetching

    • Using useEffect() instead of TanStack Query
    • Missing loading states
    • Missing error boundaries
    • No data caching strategy
    • Redundant API calls
  3. Bundle Size

    • Large dependencies
    • Missing code splitting
    • Missing lazy loading
    • Unused imports
  4. Code Structure

    • Duplicate components
    • Complex component logic
    • Missing custom hooks
    • Props drilling
    • Inline styles/functions
  5. Type Safety

    • Missing TypeScript types
    • any types 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:

  1. Build solution:

    dotnet build src/Managing.sln
    
    • Ensure no compilation errors
    • Check for new warnings
  2. Run tests (if available):

    dotnet test src/Managing.sln
    
    • Verify all tests pass
    • Check for performance improvements
  3. Review changes:

    • Ensure business logic unchanged
    • Verify API contracts maintained
    • Check error handling preserved

For React Frontend:

  1. Check TypeScript:

    npm run type-check
    
    • Ensure no type errors
  2. Run linter:

    npm run lint
    
    • Fix any new linting issues
  3. Test component:

    npm run test:single test/path/to/component.test.tsx
    
    • Verify component behavior unchanged
  4. Check bundle size:

    • Look for improvements in bundle size
    • Verify lazy loading works
  5. 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

  1. Repository Pattern with Specification

    • Encapsulate query logic
    • Reusable query specifications
    • Better testability
  2. CQRS with MediatR

    • Separate read/write operations
    • Better performance tuning
    • Cleaner code organization
  3. Caching Strategy

    • In-memory cache for frequent reads
    • Distributed cache for scalability
    • Cache invalidation patterns
  4. Async Best Practices

    • Use async/await consistently
    • Avoid Task.Result or .Wait()
    • Use ConfigureAwait(false) in libraries

React Frontend Patterns

  1. Data Fetching Pattern

    • Always use TanStack Query
    • Implement proper error boundaries
    • Use suspense for loading states
  2. Component Composition

    • Split large components
    • Create reusable atoms/molecules
    • Use compound component pattern
  3. State Management

    • Keep state as local as possible
    • Use context sparingly
    • Consider Zustand for global state
  4. 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:

  1. Identify code type: React component (ProductList.tsx)
  2. Analyze code: Found useEffect for data fetching, no memoization
  3. Present plan:
    • Replace useEffect with TanStack Query
    • Add React.memo to child components
    • Extract custom hooks
  4. Apply optimizations (show diffs)
  5. Verify: Run type-check and tests
  6. Summary: " Optimized ProductList component - replaced useEffect with TanStack Query, memoized child components"

For C# backend:

  1. Identify code type: Service class with database operations
  2. Analyze code: Found N+1 query, missing AsNoTracking, business logic
  3. Present plan:
    • Fix N+1 with Include
    • Add AsNoTracking for read-only
    • Move business logic to domain
  4. Apply optimizations
  5. Verify: Build and test
  6. Summary: " Optimized OrderService - eliminated N+1 queries, added AsNoTracking, moved business logic to domain layer"