2010-12-16 24 views
7

En una clase teórica de acceso a la base de datos, encontré que hay bastantes funciones auxiliares que uso en la clase, que no tienen nada que ver con la instancia de la clase (y otras que podrían manipularse no estar relacionado con la instancia de la clase que usa la inyección de dependencia).Desventajas de los métodos estáticos en PHP

Por ejemplo, tengo una función que obtiene una cadena entre otras dos cadenas en una variable. He estado pensando en mover eso a una clase String_Helper, o algo por el estilo. Esta función ya se ha convertido en estática.

Además, tengo una función que consulta una base de datos, query($sql). La instancia proporciona los detalles de la conexión, pero he estado considerando hacerlo estático y usando query($sql, $connection). Los desarrolladores podrían llamarlo estáticamente y no necesitar crear una instancia de la clase de la base de datos.

Para mí, las preguntas son:

  1. ¿Vale la pena hacer algo como esto? Funciones como la función de consulta me preguntan si esto no es solo yo tratando de hacer que todo sea lo más estático posible, sin ninguna necesidad real. ¿Bajo qué circunstancias considerarías esto útil?

  2. Sé que las funciones estáticas son más difíciles de probar, pero si me aseguro de que su código es completamente libre de dependencia (o usa inyección de dependencia cuando sea necesario), entonces son tan fáciles de probar como todo lo demás, ¿no?

  3. No es una preocupación en este momento, pero si, en el futuro, decidiera extender las clases con las funciones estáticas, me sería imposible hacer que el código actual use mis funciones extendidas. He pensado en Singletons, pero surge el mismo problema: el código llamaría al Singleton_Class::getInstance() y no al My_Extended_Singleton_Class::getInstance(). La inyección de dependencias parece ser la única forma de resolver este problema, pero podría llevar a una API clunkier, ya que cada dependencia tiene que asignarse a un objeto en __construct().

  4. Tengo una clase de contenedor, que contiene ciertos datos de forma estática para que se pueda acceder a ellos en cualquier parte del script (alcance global). Si no puedo usar funciones estáticas o singletons, una clase que contenga instancias de diferentes variables sería genial. Uno podría usar, por ejemplo, Container::$objects['MyClass'] = $MyClass_object;, y luego el resto del código podría simplemente acceder al Container::$objects['MyClass']. Si extendiera la clase MyClass, podría usar Container::$objects['MyClass'] = $MyExtendedClass_object;, y el código que usó Container::$objects['MyClass'] usaría MyExtendedClass, en lugar de MyClass. Esta es, de lejos, la mejor manera de hacerlo, en mi opinión, pero me gustaría saber qué piensas al respecto.

Respuesta

9

Ok, permítame responder a estos uno por uno ...

1. ¿Vale la pena hacer algo como esto

Sí y no. Es una buena idea dividir las funciones de ayuda en sus propias clases. Mantiene el "alcance" de cada una de las clases rígidamente definidas, y usted no obtiene chirrido. Sin embargo, no hagas un método estático solo porque puedes. El método de consulta está ahí para hacerte la vida más fácil al administrar la conexión, entonces ¿por qué querrías perder ese beneficio?

2. Son más difíciles de probar

No son más difíciles de probar.Los métodos estáticos que dependen del estado son más difíciles de probar (que acceden a variables miembro estáticas o variables globales). Pero los métodos estáticos en general son tan fáciles de probar como los métodos de instancia (de hecho, pueden ser más fáciles ya que no necesita preocuparse por la instanciación).

3. La extensión de las clases

Esta es una preocupación válida. Si coloca String_Helper::foo() en la clase, se encontrará con problemas. Pero una opción sería establecer el nombre de la cadena auxiliar como una variable de clase. Entonces podría hacer {$this->stringHelper}::foo() (nota, PHP 5.3 solamente). De esta forma, para anular la clase, todo lo que necesita hacer es cambiar la clase de ayudante de cadenas en esa instancia. El marco Lithium hace mucho ...

4. Registro Global

me quedaría lejos de esto. Básicamente estás haciendo que cada clase sea singleton sin aplicarla. Las pruebas serán una pesadilla ya que ahora depende del alcance global. En cambio, crearía un objeto de registro y lo pasaría a clases a través del constructor (Dependency Injection). Todavía logras lo mismo, ya que tienes una tienda para los objetos/clases, pero ya no dependes de un alcance global. Esto hace que las pruebas sean mucho más fáciles.

En general

Cuando usted está buscando en hacer las cosas de esta manera, me gusta que parar cuando llegué a este tipo de preguntas. Deténgase y siéntese y piense * ¿Qué problema real estoy tratando de resolver? ". Enumere el problema explícitamente. Luego, extraiga nuestras supuestas soluciones y vea si realmente las resuelven. Si lo hacen, piense en el futuro y en si esas soluciones son realmente sostenibles a largo plazo (tanto desde el punto de vista de la corrección de errores, como con respecto a las adiciones de funciones). Solo si estás contento con ambas respuestas, incluso deberías considerar hacerlo. Ah, y también recuerda mantenerlo simple. . la programación no se trata de hacer la solución más compleja, más inteligente o más increíble. se trata de hacer la solución más simple que resuelve el problema ...

Espero que ayude ...

buena suerte!

+0

Con estas preguntas, estaba tratando de resolver dos problemas: en primer lugar, si valdría la pena hacer las cosas estáticas y qué problemas/desventajas podrían surgir al hacerlo. En segundo lugar, quería encontrar la forma más sencilla de almacenar un conjunto de instancias de objetos, a la vez que los ponía a disposición cuando era necesario. Tu idea de usar un registro que se inyecte a cualquier función que pueda necesitar dependencias es brillante, ya que significa que la API no se llena de argumentos para todas las dependencias, y todavía tengo una manera de administrar cualquier cantidad de instancias de un objeto. Gracias. :) –

+0

@ Bruno: No hay problema. Es una forma bastante estándar de interactuar con un gran número de objetos. Tiene el beneficio de ser muy comprobable, ya que solo creas un registro lleno de objetos simulados (o solo el que necesita la prueba) e inyectártelo. No hay efectos secundarios globales, por lo que no hay necesidad de preocuparse por romper accidentalmente nada. Buena suerte otra vez ... – ircmaxell

Cuestiones relacionadas