Excepciones: Cómo forzar un "backtrace" en un sistema que no usa try/catch

Para los que venimos de haber trabajado, aunque sea académicamente, en otros lenguajes/plataformas como Java o .Net, trabajar con excepciones es un tema de todos los días. Al principio, cuando uno está aprendiendo y surge el primer volcado de una excepción (aparecen en pantalla muchas líneas con la información del error) hay una que resalta sobre todas y es la que demoramos más aprender a interpretar: el "backtrace" o ruta de ejecución desde que se inicia el sistema, todas las invocaciones que van sucediendo, en qué línea salta la ejecución, hasta terminar en el lugar exacto donde falló el sistema.

Recuerdo cuando probé por primera vez PHP5 (una beta) y lo primero que fui a probar fue hacer un try / catch forzando el fallo de una conexión a la base de datos con funciones nativas del lenguaje. Mi sorpresa fue mayúscula al comprender que los try / catch no funcionan a menos que nos aseguremos que la función que estamos usando retorne una excepción, y para colmo, PHP no lo hace por defecto! ;-) Así que no quedó otra que dejar las excepciones para nuestros desarrollos donde todo método de nuestras clases debía tener un throw new Exception('mensaje de error');

A pesar de mi desilusión, esto no era problema para los sistemas que hacíamos de cero de ahora en más, pero... ¿cómo haríamos con los sistemas que ya están funcionando y que no puedes salir a modificar miles de líneas de código para que un try / catch funcione?

Particularmente considero que una de las informaciones más importantes para poder hacer un debug de qué falló es el "backtrace". No es lo mismo ver en el log del sistema donde falló algo que ver quién invocó antes y con qué información para que fallara esa rutina.

Bien, hace un tiempo que lo buscaba y lo encontré por accidente en un foro, así que les comento la forma de uso y cómo lo pueden aplicar a sus sistemas "legacy":


class Debug
{
public static function getBacktrace()
{
$ex = new Exception();
return $ex->getTrace();
}
public static function getBacktrace2String()
{
$ex = new Exception();
$trace = $ex->getTrace();

/* Elimino la primer linea que
siempre es la misma y
hace referencia a la
invocación de esta clase */

array_shift($trace);

$trace_ret = '';
$linea = 0 ;
foreach ($trace as $item){

$linea++;

$trace_ret .=
"(".$linea.")"
."[file: ".$item['file']
.":".$item['line']."]"
."[".$item['class']
.$item['type']
.$item['function']."]"
."[args: "
.implode(',',$item['args'])
."] ";
}
return $trace_ret;
}
}


Luego, a continuación, tenemos una clase Log que lo único que hace es persistir cualquier información del sistema que queramos en un archivo de log, por lo tanto ahora agregamos la ejecución del backtrace y lo registramos en el log tal cual nos llega:


/* Método modificado de la clase Log */

public static function setError()
{
$backtrace = Debug::getBacktrace2String();
self::logToFile('errores.log',$backtrace);
}


Listo, ahora automáticamente tenemos que cada vez que el sistema deba registrar un error, este, tendrá toda la información de backtrace, que se vería en nuestro sistema de la siguiente manera:

2009-10-26 09:40:11 (1)[file: /var/www/class/App.php:81][Log::errores][args: /var/www/class/Prueba.php,75,ERROR GRAVE: no se obtuvo el resultado esperado en el metodo: getProveedor,,0,SELECT * FROM proveedores WHERE estado = 1 AND id = 111 AND idCuenta = 1234] (2)[file: /var/www/public/sys/send.php:48][Prueba->getProveedor][args: 111,1234]

Lo cual si indentamos en base a los (n) que son los saltos que va dando la ejecución,

2009-10-26 09:40:11

(1)[file: /var/www/class/App.php:81][Log::errores][args: /var/www/class/Prueba.php,75,ERROR GRAVE: no se obtuvo el resultado esperado en el metodo: getProveedor,,0,SELECT * FROM proveedores WHERE estado = 1 AND id = "111" AND idCuenta = 1234]

(2)[file: /var/www/public/sys/send.php:48][Prueba->getProveedor][args: 111,1234]

Aquí se pueden ver dos saltos, el (1) es lo que veríamos siempre en nuestro log, la aplicación que propiamente falla, pero en el (2) estamos viendo desde donde realmente se inicio la ejecución que luego terminó fallando.

De todas formas, esto es un "parche", deberíamos usar try/catch en todos nuestros sistemas de ahora en más (si es que ya no lo estás usando), pero una forma de mejorar lo que ya existe es agregar un forzado "backtrace".

Espero que lo prueben en sus sistemas y les sea de utilidad ;-)

Propuesta de trabajo: Desarrollador PHP / PHP5 / POO / MySQL (Argentina)

Les comparto la siguiente solicitud que me hace llegar una empresa, si les interesa pueden enviarme sus cv's a mi cuenta de correo (si no la sabes, no calificas para el puesto ;-))

Copio el aviso:

"Incorporaremos a nuestro equipo de desarrollo 2 personas con el siguiente perfil:

Requisitos:

- Experiencia comprobable en PHP
- Programación PHP 5 orientada a objetos (POO avanzado)
- Base de datos MySQL 5

Deseables (no excluyente):

- Frameworks PHP (preferencia Zend)
- Frameworks JavaScript (preferencia JQuery)
- Manejo de entornos Linux
- AJAX (XML y JSON)
- Maquetado en XHTML/CSS, HTML, WML
- Estudiante avanzado o graduado de carreras de informática o similar
- Capacidad de trabajo en equipo.
- Compromiso con calidad de productos y manejo de tiempos.

Empresa del rubro mobile (SMS/MMS/WAP),

Zona Palermo / Belgrano"

Tienen mi absoluta reserva.

Cursos SURFORCE: viento en popa!

Sí, nuevamente estoy poco en el blog, con mis colegas (Andrés Guzman y Nicolás Fornaro) estamos en pleno trabajo por el dictado de los cursos ;-)

Como es de público conocimiento, la última fecha para inscribirse durante este año fue a principios de octubre ( ya que los cursos duran 2 meses) y estaríamos terminando las primeras semanas de diciembre.

En este momento están activos los siguientes grupos:
  • Introducción a Zend Framework (3 grupos, dos abiertos y uno privado)
  • POO para PHP5 (3 grupos, dos abiertos y uno privado intensivo)
  • Análisis y Diseño Orientado a Objetos (2 grupos)
  • Introducción a los Patrones de Diseño (1 grupo)
  • Taller Zend de Zend Framework (1 grupo)
De todas formas, les sugiero que se registren como usuarios, así cuando existan novedades les hago un envío de las próximas fechas de cursos (tentativamente finales de enero, principios de febrero, a confirmar).

En el caso de empresas, se pueden fijar otras fechas especiales, armar grupos privados, o hasta dictados intensivos (en vez de durar 2 meses, se puede hacer en 1 mes o hasta en 2 semanas, dependiendo el tiempo de dedicación diario del alumno).

Espero que para los próximos cursos no te quedes afuera! ;-)

[SURFORCE] Cambio de fecha de inicio de cursos: lunes 12 de Octubre

Hasta esta hora estuve confirmando los pagos de los cursos y aún hay alumnos atrasados, por lo que para poder iniciar con los grupos completos vamos a tener que postergar unos días el inicio de los cursos.

Se extenderá el plazo hasta el próximo viernes para estar al día con el pago del curso y posteriormente SIN EXCEPCIONES no se recibirán más pagos y los cursos darán inicio el próximo lunes 12 de Octubre.

Aún quedan algunos lugares en los cursos para llegar al tope máximo de 20 alumnos, así que quién envíe el pago inmediatamente obtiene el lugar disponible que aún no se ha pago.

¡Si aún no pudiste confirmar tu lugar, esta es la última semana!

Cualquier duda o problema estamos a sus órdenes.

Saludos!

[SURFORCE] El inicio de cursos de Octubre se retrasa 1 día

El fin de semana estuve confirmando pagos de los cursos y aún hay algunas vacantes y bastantes alumnos atrasados, por lo que para poder iniciar con los grupos completos vamos a tener que postergar provisoriamente un día el inicio de los cursos (martes 6/10).

Al finalizar el lunes (hoy) se evaluarán los cursos que inician mañana y cuales se postergan una semana hasta el próximo lunes para poder cerrar con el cupo previsto de alumnos.

¡Si aún no pudiste confirmar tu lugar, hoy es el día!

Ni bien tenga novedades les estoy enviando un email a todos los usuarios registrados

Sepan disculpar estos inconvenientes.

Discusión: "¿cuál es tu grado de madurez en POO?"

Todo surgió respondiendo una consulta en un foro y me pareció interesante discutirlo aquí. Les comparto los "niveles" o "etapas" que considero que todo desarrollador pasa cuando decide dejar atrás la programación estructurada.

Generalmente todos empiezan por el primero y luego pocos llegan hasta el último (la mayoría solo logra llegar al 2 y se estancan en el 3):
  1. "Programación Estructurada": el inicio, desde donde parten, la "nada" ;-)
  2. "Programación Estructurada con uso de Objetos": usan objetos "sueltos / aislados", no los saben relacionar entre ellos, se reusan a leer material con "conceptos", creen que es mejor aprender a través del "prueba y error".
  3. "Programación Orientada a Objetos Sin Conceptos Claros": "creen que lo hacen bien" pero luego heredan clases mecánicamente pensando que es el mejor mecanismo para reusar código.
  4. "Desarrollo 100% OO": personas que invirtieron sabiamente su tiempo para aprender primero los conceptos para luego poder aplicarlos de forma correcta

Puedes seguir desarrollando estructurado y apoyarte en algunos objetos, pero lo ideal es que te vayas adecuando a la forma de trabajo con objetos y estructures todo el sistema de esta forma (y eso empieza por "pensar en objetos", no en código).

Nuevamente, "crear clases y jugar con objetos" es algo que todos podemos hacer, pero desarrollar "orientado a objetos" es un tema más de tener los conceptos claros que de saber la sintaxis de cómo se codifica.

Recomiendo que antes de preguntar qué es o qué no es POO, revisar el apartado de Wikipedia sobre POO y paradigmas de programación y las diferencias entre ellos.

¿Tú, en qué nivel de madurez estás? ¿crees que hay otros niveles o etapas más? ;-)

Primeros pasos en Zend Framework: cómo "aprender a pescar"

Una de las prácticas que trato constantemente de inculcar es que "aprendan a pescar" y a no "depender que los alimenten en la boca".

Durante un curso, y particularmente después que termine, deberían siempre seguir estos pasos respetando el orden:


Paso 1) "Siempre consulta primero el manual oficial"

Buscar en el manual oficial http://framework.zend.com/manual/en/

Intenta tratar de identificar el componente que provee la funcionalidad. Por ejemplo, si no sabes el significado de los parámetros del método render(). Este método es parte del componente Zend_Controller - zend.controller.action y concretamente aquí comenta los parámetros zend.controller.action.viewintegration.render



Paso 2) "Consulta la API online del Framework"


En caso de no encontrar una explicación o esta sea breve, consultar la API online que se genera a partir de los fuentes a través del uso de PHPdoc - http://framework.zend.com/apidoc/core/ (en el combo superior pueden seleccionar el componente que quieren visualizar, Zend_Controller, y luego buscar la clase Zend_Controller_Action).



Paso 3) "¡Usa el código, Luke!"


Como complemento hasta pueden consultar el mismo código fuente de la librería, que ahí se aprende también mucho de cómo funciona el framework y hasta buenas prácticas de desarrollo: revisa el código de /library/Zend/Controller/Action.php


Paso 4) "Usa Google"

Y recién, solo recién, navegar en Google buscando artículos (y con cuidado, hay que aprender a discernir qué es bueno y qué es malo, ya que hay mucha basura).


En Resumen


Todo esto lo sacan navegando el menú de documentación del sitio oficial framework.zend.com, y desaconsejo terminantemente empezar primero buscando en google y creyendo en el primer artículo que encuentran en el buscador (aunque sea de mi autoría ;-)), ya que hay demasiados charlatanes que hablan sin saber y conceptualmente pueden llevarnos a cometer errores o adoptar malas prácticas.


Que te sirva, aprende a pescar por tu cuenta y no esperes que te resuelvan tus propios problemas ;-)

[SURFORCE]: ¡Últimos cursos del año!


¡Estimados lectores, se vienen los últimos cursos del año! Hace unas semanas que se están recibiendo los pagos de las inscripciones:
  • Fecha de inicio de los cursos: Lunes 5/Octubre
  • Fecha límite para hacer los pagos: Viernes 2/octubre
Y como novedad para todos los alumnos que ya hicieron el curso de Introducción a Zend Framework, estamos iniciando el primer Taller de Desarrollo en Zend Framework, donde aplicaremos todo lo visto en el curso (y más), trabajando de principio a fin un proyecto completo de desarrollo a distancia (incorporando versionado con svn, instalación en servidores, gestión ágil de proyectos, etc)

¡No pierdas tu lugar! ¡De lo contrario, hasta el año que viene! ;-)

Para poder realizar la inscripción empieza por registrarte como usuario en SURFORCE

PD: cualquier duda o asesoramiento puedes enviarnos un email a info en surforce.com

Cajón del recuerdo: reflotando viejos posts anteriores a PHPSenior

Se dio la casualidad que para armar el post anterior tuve que salir a buscar en mi "base de recuerdos" (los posts de mis blogs) para poder responder algunos temas que alguna vez traté. Inquieto como siempre, me puse a buscar en mi blog personal (el primero de todos los blogs que creé) y que luego, buscando especializar, dieron lugar a este blog, PHPSenior (al principio tenía tres, PHP5, Smarty y Pear, que luego se fusionaron en este blog ;-)).

Algunos recuerdos de cuando hablaba de todo un poco, pero particularmente sobre desarrollo web, web 2.0, servidores, etc, y que no han perdido vigencia (y no me gustaría que se olvidaran, al día de hoy los busco cuando quiero volver a repetir algo que hice por hace mucho tiempo ;-)).

Un resumen de los post más interesantes que puedo rescatar:

2005
2006
2007
Y en el 2005 escribía lo que sería mi frase de cabecera profesional:


"¿Lo quiere rápido, barato, o bien hecho? Puede elegir dos de las tres cosas."

– El espectro del Titanic (Arthur C. Clarke, 1998)


Espero que algunos de estos recuerdos les sirva ahora. ;-)

Pregunta recibida: "¿Consejos para hacer las interfaces web?"

Esta semana recibí un email de una ex-alumna que me solicitaba mi recomendación sobre qué hacer y cómo las "interfaces web" en sus desarrollos PHP. Les comparto mi respuesta que puede ser útil a más de uno con la misma duda:

"En sí lo que estoy usando y recomiendo para los desarrollos web es algún framework general, como es Zend Framework. Con eso ya resuelves todo el problema de estructurar un proyecto, cómo organizarlo, además de múltiples clases que resuelven muchos temas repetitivos (como la persistencia, armado de la interfaz, etc). En las vistas tienes "funciones" que provee Zend (llamadas View Helpers) que simplifican mucho el trabajo (no deja de ser html o html generado a través de funciones), luego, la otra parte se hace con un buen uso de css y javascripts, y siguiendo la filosofía "productiva", te recomiendo usar siempre un framework, como bien podría ser jQuery.

No sé cómo estás con estos temas, pero la base es saber bien HTML + CSS (sin tablas) y luego complementarlo con JS (usando un framework para aumentar la productividad)

Enlaces recomendados
Si no quieres entrar aún con Zend, puedes ver sistemas de plantillas (templates) como Smarty, que también te resuelven muchos temas rutinarios y repetivos (revisa en mi blog por Smarty y verás varios artículos de cuando lo usaba, antes de Zend). Pero nuevamente, aquí ataca solo HTML, si te manejas bien con lo básico y simple, html solo es presentar los datos y css es dar estética, y js comportamiento ("3 capas de presentación"), si mantienes esto simple, las interfaces se hacen bien y rápido, fáciles de implementar (de lo contrario tienes un problema adicional al desarrollo puro y duro del sistema)."

¿Ustedes qué opinan? ¿agregarían algo más? ;-)

Entradas populares