Good refactoring vs. bad refactoring
What Counts as Refactoring
- Several commenters insist refactoring is, by definition, a structural change with no behavioral change; if behavior changes, it’s just “a change” or a feature/fix.
- Others use a looser definition that allows behavior changes when simplifying design and think the strict definition is impractical in everyday speech.
- One middle position: refactoring must preserve external behavior; internal behavior (e.g., removing implicit caching) can change if the contract stays the same.
Functional vs Imperative Styles
- Strong split on readability: some find
filter/mapchains more expressive and closer to how they conceptualize data transformations; others understand loops instantly and see FP chains as harder to debug. - Readability is widely acknowledged as reader-dependent and largely a function of familiarity, not inherent superiority.
- Performance concerns: FP chains can allocate more and traverse arrays multiple times; some have had to revert FP code to loops for speed. Others call this micro‑optimization unless profiling proves relevance.
- Debugging FP and heavy abstraction is cited as harder, especially with lazy evaluation; imperative code and simple loops are seen as easier to step through.
Object-Oriented Refactor Example
- Many argue the “OO refactor” in the article is not real OO, just a function wrapped in a class (named by verb/-or, doing work, not modeling a domain object).
- Alternative OO approach suggested: put
isAdult/formattedbehavior onUser(or related domain objects) and keep data + behavior together. - A long tangent debates whether “adult” is a property of the person, the jurisdiction, or their combination, illustrating how OO design can easily overcomplicate simple logic.
Consistency, Patterns, and Scope
- Some endorse “if you introduce a new pattern, consider applying it everywhere” to avoid long-lived inconsistency and confusing archeological layers.
- Others argue whole‑codebase rewrites are often infeasible; new patterns should be introduced incrementally, starting with new features and refactoring old code opportunistically.
- “Pattern” is discussed broadly, not just in the Gang of Four sense; inconsistency is seen as technical debt but sometimes a necessary trade-off while experimenting.
When and Why to Refactor
- Many say refactoring should almost always be in service of a concrete goal (feature, bugfix, performance, testability), not as a standalone beautification project.
- Several teams reportedly bar new hires from large refactors for a few months to avoid “I don’t like this style” churn before they understand context.
- Others push back, noting poor cultures misuse “no refactor” dogma to block necessary cleanup and that refactoring can help newcomers learn the code.
Code Size, Complexity, and Metrics
- One view: good refactors should reduce code size (e.g., gzipped LOC) and complexity; less code tends to mean fewer bugs.
- Counterview: size reduction is only a rough proxy; some beneficial refactors increase code volume (e.g., splitting classes, adding explicit types) but greatly improve comprehensibility and testability.
Critique of the Article and Tool Promotion
- Multiple commenters find the article shallow or confused: examples often change behavior, conflate refactoring with redesign, or attack FP while using FP-like constructs elsewhere.
- Some think it overemphasizes “inconsistency” and underexplains how to refactor safely.
- Several note or suspect it functions largely as marketing for an AI refactoring tool, which reduces trust in its technical depth.