Tendrás que resolver la pereza por tu cuenta. Para mí, un buen estímulo es “Si sigo siendo perezoso, perderé mi trabajo”.
Hay algunos pasos que puede seguir para simplificar su código:
- Refactorizar funciones complejas en simples. Cada función puede tener un nivel de anidamiento como máximo. Ejemplo:
// Original
función foo (x, y) {
mientras (x> 0) {
while (y> 0) {
y–;
}
X-;
}
}
// Refactor
barra de funciones (y) {
while (y> 0) {
y–;
}
devuelve y;
}
función foo (x, y) {
mientras (x> 0) {
y = barra (y);
X-;
}
}
- Mantenga su código seco. Cada vez que te das cuenta de que te has repetido, mueve el código repetido a una función separada:
// Original
función foo (x, n) {
si (x> 100) {
n = n + x;
n = n / 2;
devuelve n;
}
}
barra de funciones (y, n) {
si (y <20 && n == 5) {
n = n + y;
n = n * 2; // ¡No es una repetición exacta!
devuelve n;
}
}
// Refactor
función baz (value1, value2, shouldDivide) {
dejar total = valor1 + valor2;
volver debería dividir? total / 2: total * 2;
}
función foo (x, n) {
si (x> 100) {
devuelve baz (x, n, verdadero);
}
}
barra de funciones (y, n) {
si (y <20 && n == 5) {
devuelve baz (y, n);
}
}
Nota: es normal repetir el código. Eso es parte del proceso. A menudo no sabes que tendrás que repetirlo al principio, por lo que inicialmente no lo haces para su propia función. Si solo existe foo (), tiene sentido poner el código que necesita dentro. Pero, más adelante, cuando escriba bar () y se encuentre repitiendo algo de código de foo (), se dará cuenta de que debe refactorizar.
También soy una persona perezosa, así que tengo que luchar contra la necesidad de dejar repeticiones en mi código, especialmente si es solo un par de líneas de cosas que no están SECAS, como en el ejemplo anterior. Simplemente tengo una regla dura para mí. Cualquier código que se registre debe estar SECO.
- Trabajo sobre nombres. Una buena denominación suele ser la clave para (a) hacer que su código sea legible y (b) saber si tiene un buen conocimiento de lo que está programando. Cuando me doy cuenta de que no puedo pensar en un buen nombre para una función, clase o archivo, eso generalmente significa que estoy confundido acerca de lo que está haciendo. Los buenos nombres deben describir exactamente lo que hace el código nombrado. (No cómo lo está haciendo. Lo que está haciendo.)
Cuando puedo pensar en un buen nombre, pero es un nombre largo y compuesto, como calculadatosAndDisplayIt (), eso suele ser un signo que necesito para refactorizarlo en múltiples funciones o clases: calcularData () y displayData ().
Tenga cuidado con los nombres vagos como DataManager y, como en mi ejemplo, arriba, calculaData (). ¿Qué está haciendo exactamente DataManager? ¿Qué tipo de cálculo está ocurriendo?
Muy a menudo tengo que renombrar funciones, clases y archivos. No tengas miedo de hacer esto. No seas perezoso al respecto. Si lo que hace el código cambia, es posible que necesite un nuevo nombre para describirlo. (Por supuesto, la excepción es el código API. No se puede simplemente cambiar el nombre de los módulos utilizados por otro código).
- Libere su código de valores “mágicos”:
// Malo
si (x <23789) {
…
}
// Bueno
const COST = 23789;
si (x …
}
No debes seguir servilmente ninguna de las reglas que he sugerido. Si tiene sentido tener múltiples niveles de anidamiento en una función, o si calcularData () realmente es la mejor descripción, está bien. Simplemente haga una elección inteligente, teniendo en cuenta la legibilidad y la capacidad de mantenimiento.
Aquí hay algunas reglas de oro.
- Si una función es más larga que diez líneas, desconfíe. Diez es arbitrario. Es el número que uso. Si escribo una función que es más larga que eso, no la refactorizo automáticamente. Pero verifico si hay alguna manera de simplificarlo. Las funciones más largas son difíciles de razonar.
- Si tiene que desplazarse en un archivo para leer todo el código, desconfíe. Mantener módulos tan pequeños a menudo es imposible, pero al menos intento comenzar a buscar códigos demasiado complejos cuando mis archivos se vuelven más largos de lo que puedo colocar en una pantalla.
Esto ha sido solo una descripción general con algunos consejos. Hay libros completos sobre refactorización que puedes y debes leer. Pero creo que si sigues las reglas anteriores, recorrerás un largo camino para hacer que tu código sea legible y mantenible, y serás menos afectado en las revisiones de códigos.
ACTUALIZACIÓN : El usuario-9780881916180275396 y yo tuvimos una buena discusión en los comentarios, y me gustaría resumirlo aquí. Su (muy buena) preocupación es que, si solo usamos un nivel de anidamiento en las funciones, los lectores del código tendrán que desplazarse en busca de las funciones llamadas dentro del anidado de un nivel:
función foo (x) {
mientras (x <1) {
barra (x)
}
}
Para entender lo que está pasando, debes buscar la barra (). Estoy de acuerdo en que eso no es lo ideal. Una mala solución es explicar con comentarios.
función foo (x) {
mientras (x <1) {
// barra todos los Xs
barra (x)
}
}
No soy un fanático de los comentarios, a menos que sea absolutamente necesario, porque es increíblemente fácil cambiar el código que está comentando y olvidarse de actualizar los comentarios, y las pruebas unitarias no le dirán que lo ha hecho.
función foo (x) {
mientras (x <1) {
// barra todos los Xs
qux (x)
}
}
La mejor solución es combinar dos de mis sugerencias: anidamiento superficial y buena denominación:
función foo (x) {
mientras (x <1) {
writeToLog (x)
}
}