Como se ha señalado, hay dos escuelas de pensamiento sobre esto.
1) Declarar todo en la parte superior de las funciones porque el año es 1987.
2) Declarar el más cercano al primer uso y en el menor alcance posible.
¡Mi respuesta a esto es HACER AMBOS! Dejame explicar:
Para funciones largas, 1) hace que la refactorización sea muy difícil. Si trabaja en una base de código donde los desarrolladores están en contra de la idea de las subrutinas, tendrá 50 declaraciones de variables al comienzo de la función y algunas de ellas podrían ser una "i" para un ciclo for que parte inferior de la función.
Por lo tanto, desarrollé declaración de TEPT a partir de esto e intenté hacer la opción 2) religiosamente.
Regresé a la opción uno por una cosa: funciones cortas. Si sus funciones son lo suficientemente cortas, tendrá pocas variables locales y, dado que la función es corta, si las coloca en la parte superior de la función, aún estarán cerca del primer uso.
Además, el antipatrón de "declarar y establecer en NULL" cuando desea declarar en la parte superior pero no ha realizado algunos cálculos necesarios para la inicialización se resuelve porque las cosas que necesita inicializar probablemente se recibirán como argumentos.
Así que ahora pienso que debería declarar en la parte superior de las funciones y lo más cerca posible del primer uso. ¡Por lo tanto! Y la forma de hacerlo es con subrutinas bien divididas.
Pero si está trabajando en una función larga, ponga las cosas más cercanas al primer uso porque de esa manera será más fácil extraer métodos.
Mi receta es esta Para todas las variables locales, tome la variable y mueva su declaración al final, compile, luego mueva la declaración justo antes del error de compilación. Ese es el primer uso. Haga esto para todas las variables locales.
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
Ahora, defina un bloque de alcance que comience antes de la declaración y mueva el final hasta que el programa compile
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
Esto no se compila porque hay más código que usa foo. Podemos notar que el compilador pudo pasar por el código que usa bar porque no usa foo. En este punto, hay dos opciones. La mecánica es simplemente mover el "}" hacia abajo hasta que se compile, y la otra opción es inspeccionar el código y determinar si el orden se puede cambiar a:
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
Si se puede cambiar el orden, eso es probablemente lo que desea porque acorta la vida útil de los valores temporales.
Otra cosa a tener en cuenta es que el valor de foo necesita ser preservado entre los bloques de código que lo usan, o podría ser un foo diferente en ambos. Por ejemplo
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
Estas situaciones necesitan más que mi procedimiento. El desarrollador tendrá que analizar el código para determinar qué hacer.
Pero el primer paso es encontrar el primer uso. Puede hacerlo visualmente, pero a veces es más fácil eliminar la declaración, intentar compilar y volver a colocarla por encima del primer uso. Si ese primer uso está dentro de una declaración if, colóquelo allí y verifique si se compila. El compilador identificará otros usos. Intente hacer un bloque de alcance que abarque ambos usos.
Una vez realizada esta parte mecánica, se hace más fácil analizar dónde están los datos. Si se usa una variable en un bloque de gran alcance, analice la situación y vea si solo está usando la misma variable para dos cosas diferentes (como una "i" que se usa para dos para bucles). Si los usos no están relacionados, cree nuevas variables para cada uno de estos usos no relacionados.