Parametrizar métodos vs variables globales

10

Tengo una pregunta muy simple que me ha estado persiguiendo por un tiempo cuando mi código comienza a crecer.

¿Deberían los parámetros ser reemplazados por variables globales cuando pasan por rutas largas de llamadas a funciones anidadas?

Entiendo que el entorno global puede hacer que el estado de un programa sea impredecible porque muchas funciones pueden modificar las variables compartidas, pero aún así, el espacio global hace las cosas tan fáciles.

Déjame explicarte:

functionA(){
   x = something
   functionB(x)
}
functionB(x){
   functionC(x)
}
functionC(x){
   finallyDoSomethingWithX(x)
}
finallyDoSomethingWithX(x){
  x += 1 //Very dummy example ignoring pass by value, not reference.
}

Reemplazado por:

globalX;
functionA(){
   globalX = something
   functionB()
}
...
...
...
finallyDoSomethingWithX(){
   globalX += 1
}

Creo que la segunda forma da tanta libertad para programar porque los parámetros pueden acumularse fácilmente y también pueden ser muy restrictivos a veces cuando se debe reutilizar el código, pero al mismo tiempo siento que la función perderá su modularidad cuando está relacionada con una variable en el entorno global, perdiendo también la reutilización cuando, por ejemplo, quiero operar finallyDoSomethingWithXcon otra variable diferente de tha globalX.

Creo que esto me está sucediendo porque en realidad no estoy usando patrones de diseño porque estoy programando en Javascript, que para mí se siente como un lenguaje de un solo script para todos los proyectos medianos.

¿Algún consejo? ¿patrones? Puedo ser más específico si es necesario.

AFP_555
fuente
55
Por lo general, si está pasando variables muy profundamente, no ha dividido el problema correctamente. En cuanto a las variables globales que conducen el estado en otras partes del sistema, evítelo como la peste. Es imposible administrarlo en cierto punto, y encontrará que las cosas se rompen al azar porque algún estado está mutado por una función que no esperaba al azar.
mgw854
Evítalo como la peste. Entendido. ¿Podría elaborar un poco más sobre "no ha solucionado el problema correctamente". Entiendo la idea general, pero no puedo encontrar un ejemplo o algo para entenderla realmente.
AFP_555
2
Un remedio común cuando te encuentras pasando argumentos con muchas capas de profundidad es crear un objeto de método : un objeto de una nueva clase cuyos métodos corresponden a las funciones que transmiten los parámetros. Los parámetros pueden convertirse en variables locales al objeto, y sus métodos ya no necesitan pasar los valores.
Kilian Foth
@KilianFoth Gracias. ¿Podría por favor elaborar un código para que pueda verificar la respuesta?
AFP_555
1
Considere tratar la estructura de su código JavaScript como lo haría en otros idiomas (como los que usan clases "reales"). Algunos enlaces útiles sobre esta pregunta relacionada en SO: stackoverflow.com/questions/927651/…
Ben Cottrell

Respuestas:

7

No uses variables globales.

Además, ¡no pase parámetros por cadenas de funciones!

Es difícil porque no usas un ejemplo real. Pero normalmente habrá un mejor enfoque.

Digamos que tenemos una variable de contraseña que necesitamos usar para llamar a apis que se utilizan en varias funciones de bajo nivel.

Enfoque global (psudocódigo)

var pass;

function multiply(a,b) {
   return apiMultiply(pass,a,b);
}

Enfoque de paso de parámetros

function multiply(a,b,pass) {
    return apiMultiply(pass,a,b);
}

Enfoque de objeto

class math {
    var api;
    constructor(pass) {
        api = new api(pass);
    }

    function Multiply(a,b) {
        api.Multiply(a,b); //uses pass from constructor
    }
}
Ewan
fuente
Excelente. De esta manera, pass no se encuentra en el entorno global y tampoco es un parámetro para múltiples funciones, ya que puede tomarse de los atributos del objeto. Gracias.
AFP_555
3

Evite los globales como la peste.

Cualquier código puede modificar un global. Entonces, si tenía una cadena A (x) -> B (x) -> C (x) -> ... -> Z (x), y almacena x en una X global y ahora tiene una cadena A- > B-> C -> ...-> Z, entonces, en cada paso de esa larga cadena, o en un código completamente independiente, alguien podría cambiar X. Y el valor que usa Z podría ser completamente diferente del que A comenzó con

Es una pesadilla si alguna vez quieres estar seguro de que tu código hace lo que se supone que debe hacer, o que hace lo que crees que hace.

gnasher729
fuente
1
Totalmente de acuerdo. Si usa globales para resolver su problema, ahora tiene dos problemas.
Caleb Mauer