“Siempre se cierra”.
The hard-nosed sales mantra from Glengarry Glen Ross became shorthand for relentless improvement. In the same spirit (but with much less swearing), a good engineer should Siempre se refuerzaAquí está el porqué.
To Clean or Not to Clean
It’s generally agreed that clean code is easier to understand, cheaper to maintain, and much more extensible. At its core, refactoring is cleaning up existing code without altering its perceived functionality.
Una objeción común al refactoring es que no hay tiempo para hacerlo realmente.Los equipos lo ven como un lujo.El anhelo implacable por nuevas características simplemente no permite el refactoring, especialmente porque el refactoring no cambia nada desde un punto de vista externo.
But clean code makes your life easier. Clean code pays for itself and slows the accumulation of technical debt.
Así que sneak it in.
That’s right. I’m suggesting a slight bit of subterfuge. A little misdirection even. Why not clean up a few things in every pull request?
Be Vigilant
A good engineer has a vision of where the codebase should be heading. It might take a while to get there, but you know the messy parts, the backlog, the roadmap, the technical debt, the security holes, and the documentation gaps.
As you go about your regular feature development, be on the lookout for refactorings that can advance your larger agenda. Like one of those hyper-observant TV show detectives surveying a crime scene, pay close attention to all the code you stumble across.
When you notice a code smell or something slightly off near your current focus, alarm bells should go off: “¡No dejes pasar esta oportunidad!”Tómese unos minutos y arregle ahora, antes de que la inspiración se desvanezca.
Don’t say it’s not your problem. Don’t pretend you can unsee it. Just roll up your sleeves and get it done.
Un ejemplo sencillo
Refactoring no significa necesariamente cambiar miles de líneas de código. Puede ser sólo un pequeño pedazo de código aquí y allá. Estos pequeños micro-refactorings se suman con el tiempo. De hecho, cuanto más se adhiere al hábito de la limpieza constante, menos tendrá que hacer grandes refactorings en el futuro.
Para ilustrar el micro-refactoring, echemos un vistazo a un ejemplo de "método de extracción" Golang.
Let’s say you are tackling a feature that requires knowing how many days it has been since a user last logged in. You notice an existing method that determines if a user is dormant by using that same information:
func IsDormant(user User, asOf time.Time) bool {
days := int(asOf.Sub(user.LastLogin).Hours() / 24)
return days >= 8
}
You want to re-use the last login calculation instead of copying and pasting it, so you take the internal variable, days
, and extracting it into a separate method, DaysSinceLastLogin
:
func IsDormant(user User, asOf time.Time) bool {
return DaysSinceLastLogin(user, asOf) >= 8
}
func DaysSinceLastLogin(user User, asOf time.Time) int {
return int(asOf.Sub(user.LastLogin).Hours() / 24)
}
This allows the last login logic to be tested and reused. If you write a unit test, you’ll spot an edge case that should be handled (a potential panic if a user has never logged in).
It also makes future enhancements easier. For example, it might make sense to make IsDormant
and DaysSinceLastLogin
methods on the User
struct instead of being standalone. Likewise, consider replacing the hard-coded value 8
Algo más descriptivo comoDormantDaysThreshold
.
Este es un ejemplo simple, solo unas pocas líneas de código. Pero esa es la belleza. Muestra que un pequeño refactoring puede agregar valor al revelar un posible bug y apuntar hacia futuras mejoras.
Para aprender más sobre el arte del refactoring y ver todas las pequeñas maneras de mejorar su código, consulte los recursos en línea como el catálogo de refactoring del libro de Martin Fowler o el Refactoring Guru.
Recuperación de catálogoRefactoring GuruUna reflexión reflejada
Tener una visión para su base de código es fácil. Saber cómo conseguirlo es más difícil. Detectar oportunidades de refactoring requiere práctica. Una forma de comenzar es considerar qué categorías de refactoring son necesarias para transformar su código.
Here are some common refactoring themes to think about:
🧹 Remove DuplicationColapse copia y pega la lógica en una sola función.
Extract Shared Utility or Library — Move common logic out of per-service implementations. Normalize integrations (e.g., all services use the same auth client).
🧱 Add Common Infrastructure— Introducir la observabilidad (logging, tracing, métricas). Centralizar el manejo de errores o retries.
⚙️ Make Code More Testable — Break apart tightly coupled logic. Extract interfaces so dependencies can be mocked or stubbed.
🔄 Prepare for a Feature Change- Condiciones complejas o lógica anclada.Reorganizar archivos o clases para adaptarse a nuevas responsabilidades.
🏗️ Support a New ArchitectureIntroducir patrones impulsados por eventos, inyección de dependencia o procesamiento asínctico.
Reduce Cognitive Load — Split giant files or classes into logical, focused units.
🔐 Improve Security or Compliance — Centralize access control logic. Refactor insecure patterns (e.g., manual SQL concatenation → parameterized queries).
🚀 Improve Performance — Replace naive algorithms with optimized ones. Reduce memory churn or unnecessary computation in hot paths.
Ease Onboarding or Handoff— Código de refactor que solo “Pat” entiende en algo legible por el equipo. Introduce docs/comments/test coverage como parte de la limpieza estructural.
El 20%
Some might object that surely not all refactorings can be snuck in. I’ll grant you that. Let’s apply the 80–20 rule and stipulate that 20% of refactorings need to be done on the up-and-up.
These should be an easier sell, however, because when you get to the point where you need a full, honest-to-goodness refactor, it is most definitely going to be in service of some larger goal.
For example, before working on a performance improvement ticket, you first need to add tracing and metrics so you can develop a finer picture of current performance and identify hotspots.
Refactoring Starts with Testing
It is probably self-evident, but I must point out that refactoring is much easier (and less nerve-racking) if your codebase has an accompanying suite of tests that pass before and after the refactoring. Having tests is also valuable for a Un montón de otras razones. If your project doesn’t have strong testing, then add some tests first to unlock future refactorings.
Code Review Considerations
Mi consejo en este artículo va en contra de la guía estándar para no mezclar el trabajo de refactoring con el desarrollo regular de características. La objeción es que hace que sea más difícil para el equipo hacer revisiones de código si se incluyen cambios no relacionados.
Una buena regla del pulgar para cualquier solicitud de arrastre es limitarlo a 500 líneas de cambios de código.Una segunda regla del pulgar es que los cambios de refactoring auxiliares no deben ser más del 20% del PR.
When you do have dedicated refactoring PRs, keep it focused and around this size. Sometimes a PR has to be greater than 500 lines of code, especially when working on a repo-wide refactor. In those cases, coordinate well with your colleagues to prepare them for the change and to minimize merge conflicts.
Make Every Commit Count
Every time you touch the codebase, you have a choice: leave it a little better, or leave it a little worse. Refactoring doesn’t have to be a grand event. Small improvements (extracting methods, renaming confusing variables, breaking apart long methods, etc.) add up over time. They prevent technical debt from piling up and make future changes easier and safer.
If you see something, fix something.
Always be refactoring!