Elegance in code is tricky to define, but for me a good heuristic is "how easily could I codemod this?" Similar: does it lead to good Copilot suggestions?
When you start a greenfield project, AI allows you to ship at the speed of thought. However, as your project grows in size, your code may not evolve as quickly as you would like. It doesn't have to be this way. Andrew and I would love to refer to such code as "elegant," which has a straightforward definition.
The term "codemod" refers to a tool that assists developers in making systematic changes to their source code. A codebase becomes more "codemodable" when it is structured in a way that allows for these automated modifications to be performed easily and reliably. With that, fleet-wide modernization becomes possible, and that’s crucial especially as the size of codebases grows exponentially thanks to AI.
Here are some factors that can make code more or less amenable to codemodding:
Consistency
If the code follows consistent patterns and styles, it's easier to apply a codemod because the tool can predictably identify the parts that need changes.
More codemodable: Functions and methods follow a consistent naming convention, making it easier to target them.
1function calculateTotal() { /*...*/ }2function calculateDiscount() { /*...*/ }
1function calcTotal() { /*...*/ }2function getDiscountAmount() { /*...*/ }
Complexity
Simpler, less complex code with fewer dependencies is typically easier to modify with a codemod.
More codemodable: Simple, single-purpose functions.
1def add(a, b):2 return a + b
Less codemodable: Nested functions with complex logic.
1def calculate(a, b, option):2 if option == 'add':3 def add(x, y):4 return x + y5 return add(a, b)6 # More complex logic...
Test Coverage
Having a comprehensive suite of tests allows developers to ensure that the codemod has not broken any existing functionality.
More codemodable: Code accompanied by tests.
1function add(a, b) { return a + b; }2console.assert(add(2, 2) === 4);
Less codemodable: Code with no tests.
1function add(a, b) { return a + b; }
Modularity
Code that is modular and composed of small, single-responsibility functions or classes is easier to target with codemods because changes can be isolated to specific modules without affecting others.
More codemodable: Code organized in modules or classes.
1class Calculator {2 add(a: number, b: number) { return a + b; }3}
Less codemodable: All logic in a single file or function.
1function calculate(a: number, b: number, op: string) {2 if (op === 'add') { return a + b; }3 // More operations...4}
API Stability
If the code relies on APIs that are stable and backward compatible, codemods can be written with the confidence that the API contract won't change unexpectedly.
More codemodable: Using well-established libraries or APIs.
1import requests2response = requests.get('<https://api.example.com/data>')
Less codemodable: Using custom, frequently changing APIs.
1import myCustomApi2response = myCustomApi.get('<https://api.example.com/data>')
Abstraction Level
Code that operates at a higher level of abstraction may be easier to codemod because changes can be made at the abstraction level rather than having to account for many low-level details.
More codemodable: High-level abstractions.
1public interface IShape {2 void Draw();3}
Less codemodable: Low-level, detailed implementations.
1public class Circle {2 // Complex drawing logic involving graphics primitives3}
Making code more "codemodable" often involves cleaning up and refactoring the codebase to improve these aspects, which not only facilitates the use of codemods but generally leads to a cleaner, more maintainable, and more robust codebase.
Start migrating in seconds
Save days of manual work by running automation recipes to automate framework upgrades, right from your CLI, IDE or web app.