exupero's blog
RSSApps

Niche refactoring

In the previous post I wrote about using Clojure zippers to refactor code. That's been a handy tool to have in my toolbox because while IDEs can often refactor code, they're generally constrained to language-specific patterns or text-based custom transformations. Teams, projects, and libraries, however, can have their own idioms that are hard to encode in an IDE or auto-formatter. Here are a few times I've written custom refactors using zippers.

Convert if statements to ternary expressions

Branches of if statements tend to accumulate code, so whenever an if looks like this:

let variable;
if (condition) {
  variable = some_value;
} else {
  variable = some_other_value;
}

I like to nip the branches in the bud to avoid more complex, even branchier code, so I'll often turn statements like the above into an equivalent ternary:

const variable = condition ? some_value : some_other_value

That's a language-specific transformation, but teams I've worked on have had preferences on how to format that syntax (split clauses onto separate lines?) and how far to go with it (include else if branches as nested ternaries?), details that could possibly be provided by a combination of generic refactoring and auto-formatter, though I don't recall finding any at the time.

Convert React component functions into classes

One library-specific refactor I've written turned React function components into class components, in order to add lifecycle methods (this was before the introduction of React hooks). The refactoring logic didn't do much, just found the full body of the function and wrapped it in a render method of a class. It might also have saved the constructor's props argument as an instance attribute.

Refactor Ramda forms

One team I worked on used Ramda heavily, and I wrote refactors to transform basic JavaScript property access to use Ramda's prop, propOr, path, and pathOr functions, as well as to turn calls like R.map(x, y) into the start of a functionally composed pipeline of the form R.pipe(R.map(x))(y).

Change Java annotations

In an earlier post I mentioned refactoring Java and Kotlin annotations, which I did as part of an upgrade of Swagger to OpenAPI 3. Rewriting the annotations involved more than just swapping a few annotation names. Fields on the annotations also needed to be renamed, and long string values had to be re-line-wrapped.

If you have suggestions for how to manage team-, library-, and project-specific refactoring needs, please email me.