Todavía creo que el registro es un enfoque válido para utilizar una clase estática. La frase a menudo declarada de que no es verificable tampoco es verdad si lo haces bien. Quiero implementar esto pero no encontré el tiempo, sin embargo, pensé en algo como lo siguiente.
class Logger {
protected static $handlerSet = [];
// Pure static class {{{
private function __construct() {}
private function __clone() {}
private function __sleep() {}
private function __wakeup() {}
// }}}
public static function critical($message, array $context = []) {}
// You know the PSR drill...
private static function log($level, $message, array $context) {
foreach ($this->handlerSet as $handler) {
$handler->handle($level, $message, $context);
}
}
}
Por supuesto que no queremos exponer a la gestión de los manipuladores a todas las clases, por lo tanto, se utiliza una clase de niño que tiene acceso al conjunto manipulador protegida.
final class LoggingManager extends Logger {
public static function addHandler(Handler $handler, $name, $level) {
static::$handlerSet[$name] = $handler;
}
public static function removeHandler($name) {
if (isset(static::$handlerSet[$name])) {
unset(static::$handlerSet[$name]);
}
}
public static function resetHandlers() {
static::$handlerSet = [];
}
// Other useful stuff...
}
La prueba es ahora bastante fácil, si realmente desea probar algo así como la explotación forestal (podría ser que tiene algún retorno de la inversión para usted, no sé).
class SomeTest extends YourFrameworksTestCase {
public function testThatSomethingLogsSomething() {
try {
$handler = new TestLogHandler();
LoggingManager::registerHandler($handler, 'test', 'debug');
// Test something.
$this->assertLogRecordExists($handler, '[debug] StackOverflow');
}
finally {
LoggingManager::resetHandlers();
}
}
}
También sería posible crear un caso de prueba más sofisticados para extender que implementa toda la afirmación de entrada de registro para usted. Este enfoque es bastante fácil y una clase en su sistema no debería importar si un controlador está registrado o no, ni qué hace con los mensajes registrados. Cosas así se manejan en su aplicación y solo allí. Las ventajas son obvias:
- Acceso global al administrador de registro y registro.
- Prueba fácil, comparable a la inyección de dependencia.
- No hay necesidad de codificar las soluciones DIC.
- Instancia de registrador único, siempre.
- ...
Él escribe en su pregunta '¿Puedo usar cuando quiera en mi appliaction como esto'. ¿Cuál es la diferencia de usar un Logger :: log() estático con una instancia global? Si llama a Logger :: log() en métodos aleatorios, sus dependencias no son claras + las pruebas se vuelven difíciles (no puede burlarse de su registrador, por lo tanto, dependen de su funcionamiento). – koen