Skip to content

Refactoring Patterns

Mo Abualruz edited this page Dec 5, 2025 · 1 revision

Refactoring Patterns Guide

Status: ✅ Complete

Last Updated: December 5, 2025


Overview

Refactoring patterns are reusable templates for common code transformations. They enable consistent refactoring across projects and can be customized for specific contexts.

Pattern Basics

What is a Pattern?

A refactoring pattern is a reusable template that defines:

  • Name: Unique identifier for the pattern
  • Description: What the pattern does
  • Template: Pattern with placeholders
  • Parameters: Customizable values
  • Scope: Global or project-specific

Pattern Scope

  • Global: Available across all projects
  • Project: Available only within a specific project

Creating Patterns

Basic Pattern Structure

use ricecoder_refactoring::RefactoringPattern;

let pattern = RefactoringPattern {
    name: "rename_function".to_string(),
    description: "Rename a function".to_string(),
    template: "fn {{old_name}}() {} -> fn {{new_name}}() {}".to_string(),
    parameters: vec![
        PatternParameter {
            name: "old_name".to_string(),
            placeholder: "{{old_name}}".to_string(),
            description: "Old function name".to_string(),
        },
        PatternParameter {
            name: "new_name".to_string(),
            placeholder: "{{new_name}}".to_string(),
            description: "New function name".to_string(),
        },
    ],
    scope: PatternScope::Global,
};

Pattern Parameters

Parameters are customizable values in patterns:

pub struct PatternParameter {
    pub name: String,                    // Parameter name
    pub placeholder: String,             // {{placeholder}} in template
    pub description: String,             // Parameter description
}

Using Patterns

Applying a Pattern

use ricecoder_refactoring::PatternStore;
use std::collections::HashMap;

let store = PatternStore::new();
let pattern = store.get_pattern("rename_function")?;

let mut params = HashMap::new();
params.insert("old_name".to_string(), "foo".to_string());
params.insert("new_name".to_string(), "bar".to_string());

let app = PatternApplication {
    pattern,
    parameters: params,
};

let result = app.apply("fn foo() {}")?;
println!("Result: {}", result);

Listing Patterns

let store = PatternStore::new();
let patterns = store.list_patterns();

for pattern in patterns {
    println!("Pattern: {}", pattern.name);
    println!("Description: {}", pattern.description);
}

Common Patterns

Rename Function

Rename a function across the codebase:

name: rename_function
description: Rename a function
template: "fn {{old_name}}() -> fn {{new_name}}()"
parameters:
  - name: old_name
    placeholder: "{{old_name}}"
    description: "Old function name"
  - name: new_name
    placeholder: "{{new_name}}"
    description: "New function name"
scope: Global

Extract Method

Extract code into a separate method:

name: extract_method
description: Extract code into a separate method
template: |
  // Before
  {{code_block}}
  
  // After
  self.extracted_method()
parameters:
  - name: code_block
    placeholder: "{{code_block}}"
    description: "Code to extract"
scope: Global

Rename Variable

Rename a variable:

name: rename_variable
description: Rename a variable
template: "let {{old_name}} = -> let {{new_name}} ="
parameters:
  - name: old_name
    placeholder: "{{old_name}}"
    description: "Old variable name"
  - name: new_name
    placeholder: "{{new_name}}"
    description: "New variable name"
scope: Global

Rename Class

Rename a class:

name: rename_class
description: Rename a class
template: "class {{old_name}} -> class {{new_name}}"
parameters:
  - name: old_name
    placeholder: "{{old_name}}"
    description: "Old class name"
  - name: new_name
    placeholder: "{{new_name}}"
    description: "New class name"
scope: Global

Add Parameter

Add a parameter to a function:

name: add_parameter
description: Add a parameter to a function
template: "fn {{function_name}}({{old_params}}) -> fn {{function_name}}({{old_params}}, {{new_param}})"
parameters:
  - name: function_name
    placeholder: "{{function_name}}"
    description: "Function name"
  - name: old_params
    placeholder: "{{old_params}}"
    description: "Existing parameters"
  - name: new_param
    placeholder: "{{new_param}}"
    description: "New parameter"
scope: Global

Pattern Storage

Global Patterns

Global patterns are stored in:

~/.ricecoder/refactoring/patterns/

Project Patterns

Project patterns are stored in:

./.agent/refactoring/patterns/

Pattern Export/Import

Exporting Patterns

use ricecoder_refactoring::PatternExporter;

let exporter = PatternExporter::new();
let pattern = store.get_pattern("rename_function")?;
let yaml = exporter.export(&pattern)?;
println!("{}", yaml);

Importing Patterns

use ricecoder_refactoring::PatternExporter;

let exporter = PatternExporter::new();
let yaml = std::fs::read_to_string("pattern.yaml")?;
let pattern = exporter.import(&yaml)?;
store.save_pattern(pattern)?;

Pattern Validation

Patterns are validated before use:

use ricecoder_refactoring::PatternValidator;

let validator = PatternValidator::new();
validator.validate(&pattern)?;

Validation checks:

  • Pattern name is not empty
  • Template is not empty
  • All placeholders have corresponding parameters
  • Parameter names are unique
  • Scope is valid

Pattern Composition

Patterns can be composed to create more complex transformations:

let pattern1 = store.get_pattern("rename_function")?;
let pattern2 = store.get_pattern("add_parameter")?;

// Apply pattern1 first
let result1 = apply_pattern(&pattern1, code)?;

// Then apply pattern2
let result2 = apply_pattern(&pattern2, &result1)?;

Best Practices

1. Use Descriptive Names

# Good
name: rename_function_to_camel_case

# Bad
name: rename

2. Document Parameters

parameters:
  - name: old_name
    placeholder: "{{old_name}}"
    description: "The current function name to be renamed"  # Good

3. Keep Patterns Simple

# Good - single responsibility
name: rename_function
template: "fn {{old_name}} -> fn {{new_name}}"

# Bad - too complex
name: rename_and_add_parameter
template: "fn {{old_name}}({{old_params}}) -> fn {{new_name}}({{old_params}}, {{new_param}})"

4. Use Consistent Placeholders

# Good - consistent naming
parameters:
  - name: old_name
    placeholder: "{{old_name}}"
  - name: new_name
    placeholder: "{{new_name}}"

# Bad - inconsistent naming
parameters:
  - name: old_name
    placeholder: "{{oldName}}"
  - name: new_name
    placeholder: "{{newName}}"

5. Test Patterns

#[test]
fn test_rename_function_pattern() {
    let pattern = get_pattern("rename_function");
    let mut params = HashMap::new();
    params.insert("old_name".to_string(), "foo".to_string());
    params.insert("new_name".to_string(), "bar".to_string());
    
    let app = PatternApplication { pattern, parameters: params };
    let result = app.apply("fn foo() {}").unwrap();
    
    assert!(result.contains("bar"));
    assert!(!result.contains("foo"));
}

Troubleshooting

Pattern Not Found

  1. Check pattern name is correct
  2. Verify pattern is stored in correct location
  3. Check pattern scope (global vs project)
  4. Review pattern list to see available patterns

Pattern Application Failed

  1. Verify all required parameters are provided
  2. Check parameter values are correct
  3. Validate pattern syntax
  4. Review error message for details

Pattern Validation Failed

  1. Check pattern name is not empty
  2. Verify template is not empty
  3. Ensure all placeholders have parameters
  4. Check parameter names are unique

See Also


Last updated: December 5, 2025

Clone this wiki locally