Pregunta

Editar: Advertencia: ahora me doy cuenta de que la siguiente técnica generalmente se considera una mala idea porque crea dependencias ocultas en aras de lucir ordenada.


Recientemente descubrí que puede usar StackTrace para inferir información sobre la persona que llama de un método.

Esto le permite crear un aspecto aparentemente "genial" API mediante la cual simplemente invocas un método sin molestarte en pasarle parámetros explícitos, y el método determina qué hacer en función del StackTrace.

¿Es esto algo malo y, de ser así, por qué?

Ejemplo:

public class Cache {
  public Object CheckCache()
  {
    Object valueToReturn = null;
    string key = GenerateCacheKeyFromMethodPrototype(new StackTrace().GetFrame(1).GetMethod()); //frame 1 contains caller
    if(key is in cache) valueToReturn = itemFromCache;

    return valueToReturn;   
  }
}

public class Foo { 
  private static Cache cache = new Cache();

  public Blah MethodFoo(param1, param2...)
  {
    Blah valueToReturn = cache.CheckCache(); //seems cool!
    if(valueToReturn == null)
    {
      valueToReturn = result of some calculation;
      //populate cache
    }

    return valueToReturn;
  }
}

Estoy seguro de que hay errores en el pseudocódigo anterior, pero me entiendes.


Editar: gracias por las respuestas de todos.

¿Fue útil?

Solución

Hay dos razones por las cuales no hacer esto:

  • Es lento
  • Se crea una solución frágil.

Si desea hacer esto, será mejor que use una herramienta que admita la Programación Orientada a Aspectos, como el Proxy Dinámico de Castle.

Otros consejos

Otro problema es que el compilador puede "en línea" su método en el proceso de optimización, por ejemplo,

void MethodA() {
    MethodB();
}

void MethodB() {
   foo();
}

se convierte en:

void MethodA() {
   foo();
}

Esto obviamente es un problema porque la persona que llama inmediatamente para foo ya no es el Método B, sino el Método A. Sin embargo, hay un atributo que puede colocar en su método para evitar que esté en línea:

[MethodImpl( ... NoInline )]

(No recuerdo el parámetro exacto)

-Oisina

Es malo porque no puedo saber qué hace la función cuando la llamo. No puedo probar la función, porque mi prueba la llamará desde una función diferente, lo que puede invocar un comportamiento diferente.

Y es malo porque ahora hay un "invisible" contrato debo obedecer al llamar a la función. No solo tengo que asegurarme de que se pasan los parámetros correctos, también tengo que asegurarme de que la función actual tenga el nombre correcto. ¿Qué pasa si tuviera que ajustar la llamada de función en una función lambda anónima? De repente, he cambiado el comportamiento del programa, y ?? no lo había adivinado de antemano, así que ahora puedo pasar el día siguiente depurando por qué el programa se rompió repentina y mágicamente.

¿Qué sucede con las funciones sobrecargadas? ¿Distingues entre ellos? ¿Funciones con el mismo nombre, pero en diferentes clases? Funciones con " especial " nombres, como constructor, finalizador, operadores o lambdas?

¿Y qué pasa cuando el compilador integra las funciones?

Eso no me parece nada genial. ¿Por qué querrías poner todas las formas posibles de obtener el estado requerido en el método mismo? Esto es como un anti patrón para la inyección de dependencia. No vayas allí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top