Las dos principales razones contra el uso de métodos estáticos son:
- código usando métodos estáticos es difícil de prueba
- código usando métodos estáticos es difícil de extienden
Tener una llamada al método estático dentro de algún otro método es en realidad peor que la importación de una variable global. En PHP, las clases son símbolos globales, por lo que cada vez que llamas a un método estático dependes de un símbolo global (el nombre de la clase). Este es un caso cuando global es malvado. Tuve problemas con este tipo de enfoque con algún componente de Zend Framework. Hay clases que usan llamadas a métodos estáticos (fábricas) para construir objetos. Me fue imposible suministrar otra fábrica a esa instancia para obtener un objeto personalizado devuelto. La solución a este problema es usar instancias y métodos de instance y aplicar singletons y similares al principio del programa.
Miško Hevery, que trabaja como Coach Ágil en Google, tiene una teoría interesante, o mejor dicho, aconseja, que debemos separar el tiempo de creación del objeto desde el momento en que usamos el objeto. Entonces, el ciclo de vida de un programa se divide en dos.La primera parte (el método main()
Digamos), que se ocupa de todo el cableado de objetos en su aplicación y la parte que hace el trabajo real.
Así que en lugar de tener:
class HttpClient
{
public function request()
{
return HttpResponse::build();
}
}
Más bien debería hacer:
class HttpClient
{
private $httpResponseFactory;
public function __construct($httpResponseFactory)
{
$this->httpResponseFactory = $httpResponseFactory;
}
public function request()
{
return $this->httpResponseFactory->build();
}
}
Y luego, en la página de índice/principal, nos gustaría hacer (este es el paso de cableado objeto, o el tiempo para crear el gráfico de instancias para ser utilizado por el programa):
$httpResponseFactory = new HttpResponseFactory;
$httpClient = new HttpClient($httpResponseFactory);
$httpResponse = $httpClient->request();
la idea principal es para desacoplar las dependencias fuera de y nuestras clases. De esta forma, el código es mucho más extensible y, la parte más importante para mí, comprobable. ¿Por qué es más importante ser comprobable? Porque no siempre escribo el código de la biblioteca, por lo que la extensibilidad no es tan importante, pero la capacidad de prueba es importante cuando realizo la refactorización. De todos modos, el código comprobable generalmente arroja un código extensible, por lo que no es una situación real.
Miško Hevery también hace una clara distinción entre singletons y Singletons (con o sin una S mayúscula). La diferencia es muy simple. Los singletons con una minúscula "s" son aplicados por el cableado en el índice/principal. Crea una instancia de un objeto de una clase que hace no implemente el patrón Singleton y tenga cuidado de pasar esa instancia a cualquier otra instancia que lo necesite. Por otro lado, Singleton, con una "S" mayúscula es una implementación del patrón (anti) clásico. Básicamente un mundo disfrazado que no tiene mucho uso en el mundo de PHP. No he visto uno hasta este punto. Si desea una única conexión de base de datos para ser utilizado por todas las clases es mejor hacerlo de esta manera:
$db = new DbConnection;
$users = new UserCollection($db);
$posts = new PostCollection($db);
$comments = new CommentsCollection($db);
Al hacer lo anterior está claro que tenemos un producto único y también tenemos una buena manera de inyectar una simulacro o un talón en nuestras pruebas. Es sorprendente cómo las pruebas unitarias conducen a un mejor diseño. Pero tiene mucho sentido cuando crees que las pruebas te obligan a pensar en la forma en que usarías ese código.
/**
* An example of a test using PHPUnit. The point is to see how easy it is to
* pass the UserCollection constructor an alternative implementation of
* DbCollection.
*/
class UserCollection extends PHPUnit_Framework_TestCase
{
public function testGetAllComments()
{
$mockedMethods = array('query');
$dbMock = $this->getMock('DbConnection', $mockedMethods);
$dbMock->expects($this->any())
->method('query')
->will($this->returnValue(array('John', 'George')));
$userCollection = new UserCollection($dbMock);
$allUsers = $userCollection->getAll();
$this->assertEquals(array('John', 'George'), $allUsers);
}
}
La única situación en la que haría uso (y los he usado para imitar el objeto prototipo de JavaScript en PHP 5.3) miembros estáticos es cuando sé que el campo respectivo tendrá el mismo valor a través del ejemplo . En ese punto, puede usar una propiedad estática y tal vez un par de métodos estáticos getter/setter. De todos modos, no olvide agregar la posibilidad de anular el miembro estático con un miembro de instancia. Por ejemplo, Zend Framework usaba una propiedad estática para especificar el nombre de la clase de adaptador DB utilizada en instancias de Zend_Db_Table
. Ha pasado un tiempo desde que los usé, por lo que puede que ya no sea relevante, pero así es como lo recuerdo.
Los métodos estáticos que no se relacionan con las propiedades estáticas deben ser funciones. PHP tiene funciones y deberíamos usarlas.
Solo quiero decir: ¿Qué es el # $ *%? !!!!? Se pone realmente confuso. De todos modos, supongo que esto ayudaría: http://www.php5-tutorial.com/classes/static-classes/ – Omar
Así que básicamente use objetos cuando trabaje con cosas únicas como una foto, usuario, publicación, etc. y use estática cuando su significado para cosas generales? –
hablando bien del usuario, solo tiene un usuario activo en cada solicitud. por lo que tener el usuario activo de la solicitud estática tendría sentido – My1