¡Pregúntame lo que quieras!

Cómo lo comentaba en mi blog personal, estoy probando el nuevo servicio formspring.me, en el cual de forma muy sencilla (una de las razones del éxito de estos proyectos: utilidad + simplicidad) pueden hacerme pregunta de los temas que quieran, los cuales responderé con gusto ;-)



Sigue todas las preguntas y respuestas

PHPSenior: el resumen del año 2009

Siguiendo la costumbre de muchos blogs, les hago un resumen de los artículos "más técnicos" que se trataron durante el año. Particularmente este año no fue el más activo en lo que respecta a la creación de nuevos contenidos, ya que la escritura del libro y los posteriores cursos que se fueron dictando durante todo el año nos mantuvieron a todos muy ocupados (incluyo a mis dos grandes colegas y docentes que me acompañan: Andrés Guzmán y Nicolás Fornaro).


Para este próximo año 2010 tengo muchos proyectos, algunos relacionados con este blog y otros relacionados con SURFORCE, los cursos, la nueva versión del libro de POO (que la vengo demorando porque quiero estrenar nuevo material asociado) y las próximas novedades en cursos y libros.


Aquí el resumen de los temas que se trataron durante el año, y espero, el próximo año sea mucho más productivo en todo sentido ;-)

Enero

Febrero

Marzo

Abril

Mayo

Junio

Julio

Agosto

Septiembre

Octubre

Noviembre

Diciembre

¡Feliz Año 2010! ;-)

Video Promocional de la nueva versión Netbeans 6.8

La mayoría ya debe saber que en la actualidad estoy usando más Netbeans que ZendStudio, particularmente porque prefiero usar "software libre" y no tener que usar "software ilegal" ;-)

Aquí les dejo el video promocional (aunque gran cantidad de mejoras son para Java, es un IDE muy completo para PHP y ya empezaron con el desarrollo del soporte para Zend Framework).

Fotos de la pasada PHP Mini Meeting - Argentina (14/11/2009)

El pasado sábado 14/11 nos reunimos varios "phperos" en Argentina en una primer "PHP Mini Meeting". Les voy a hacer un breve resumen de lo que presencié, más algunos comentarios muy personales que hice sobre cada exposición, donde lejos de criticar, intento tratar de transmitirles lo que se trató en cada charla. Desde ya felicito el interés y la dedicación de cada uno de los que dedicó su tiempo personal para preparar y luego presentar cada charla.

Andrés Proaño, organizador de esta primer reunión, se encargó de mostrarnos su proyecto PX, una librería desarrollada en objetos para generar código Xhtml. La única crítica que tuve para hacerle es que no estaba respetando los estándares mínimos de codificación POO, como ser que las clases iniciaran en mayúsculas, singular, etc. Para no ser menos, sugerí que adoptara el estándar de codificación Zend, tema que tal vez en una próxima reunión me encargue de dar.

Germán Peraferrer nos presentó su proyecto ORMphp, herramienta que desarrolló en su empresa para acelerar el trabajo de sus desarrolladores y poder competir con otras empresas en su mismo rubro, logrando acortar los tiempos en preparar prototipos funcionales para sus futuros clientes.

Según nos comentó a través de su presentación, luego de generar la configuración base de conexión a la base de datos, la herramienta genera todos los modelos necesarios (clases) que luego podemos incorporar a nuestros desarrollos y que contienen todas las operaciones necesarias para trabajar con la persistencia de objetos. Según comentamos, fácilmente podríamos integrarlo a Zend Framework (ya que este aún no cuenta con un ORM), y aún mejor, ya viene incorporada la generación de webservices para poder acceder a los datos desde cualquier fuente de origen.

Lo único que tengo para criticarle a Germán es que aún no haya liberado como proyecto libre su herramienta (usando tal vez code.google.com) y tener acceso a una documentación como un wiki y a un svn para bajar su código actualizado. De todas formas Germán ya nos envió el código fuente de la herramienta y una guía de uso, en lo cual estoy en deuda porque aún no pude sentarme a probar, pero que haré dentro de poco (ya que tengo mucho interés de evaluarla y ver si puedo incorporarla en alguno de mis desarrollos actuales :-))

Nota: con Germán ya habíamos tenido algún intercambio amistoso sobre "reinventar la rueda", ya que yo le decía que habían demasiados "ORM's", pero bueno, nos pusimos de acuerdo que a veces no queda otra, las herramientas pueden ser muy complicadas de aprender (curva de aprendizaje empinada) y otras tienen demasiadas funcionalidades que no usaremos nunca, lo que nos obliga a generar proyectos más concretos y específicos.

De todas formas, no sugiero nunca empezar primero creando algo nuevo sin evaluar honestamente las alternativas existentes.

Aquí estoy de espaldas, a tres ventanas de twitters, haciendo algún que otro comentario en vivo sobre la charla.

Sebastian Waisbrot, quién nos presentó sus experiencias usando el framework CodeIgniter. Este framework fue uno de los tantos que analicé oportunamente antes de dejar de perder el tiempo y decantarme por Zend Framework ;-)

En resumen, y confirmando con las palabras de Sebastian, sigo desaconsejando su uso: el equipo de desarrollo sigue una seudo-filosofía similar a Debian, quieren ser "ultra" estables y seguros, además, les preocupa en demasía la compatibilidad hacia atrás, lo que lleva a que aún esté internamente desarrollado en PHP4. Por el resumen de funcionalidades que se comentaron (tal vez por la versión que actualmente usa Sebastian), está bastante lejos de la mayoría de los frameworks más conocidos (Zend, Cake, etc).

Nota: sugiero recorrer el blog de Sebastian, ya que encontré muy buenos artículos sobre POO que recomiendo enormemente (lamentablemente desde el año pasado que no lo actualiza).

Aquí estoy a la derecha, sentado junto a Adrián, otro "phpero" que tuve el gusto de conocer.



Finalmente, luego de terminar, el resto nos fuimos a comer unas pizzas y a planear un proyecto de LUG, similar a los que existen para GNU/Linux, pero pensado para PHP (una idea que comparto desde hace muchos años). Así que esperamos que se puedan seguir armando charlas para todos los desarrolladores PHP que quieran participar y compartir sus conocimientos, y terminar de construir una comunidad tan fuerte como cualquier otra de Software Libre.

Quiero agradecer las fotos a Jonathan Margulis, joven fotógrafo profesional que nos acompañó y le dio otro toque de estilo a las fotos (muy buenas, hasta me veo más flaco y todo ;-))

PD: lamento no tener el nombre de todos ni sus blogs, pero como comenté en la reunión, el hecho de comunicarse a través de un foro y que la mayoría use seudónimos, dificulta enormemente que nos conozcamos y que asociemos lo que decimos y quienes somos ;-)

Así que quienes participaron, bienvenidos a enviarme en los comentarios sus nombres y datos para ser actualizados en este post.

¿Conoces la clase "DateTime"?

Es muy dificil conocer todas las funcionalidades que nos puede ofrecer un lenguaje, ya que leer el manual con el listado de funciones de arriba a abajo es tan divertido como leer la guía telefónica. Generalmente cuando tenemos un problema para resolver vamos a buscar en la sección correspondiente, según el tema, y listo (arrays, matemáticas, strings, etc). Lo importante muchas veces es, no solo saber de memoria, sino, saber donde buscar (o como dice el viejo dicho, "lo más importante es tener el teléfono de quién sabe", aunque esto lo único que hace es que evitemos aprender a valernos por nosotros mismos ;-)).

Siempre creí que la evolución natural de PHP debería ser juntar todas las funciones "sueltas" del lenguaje en formato "estructurado" y agruparlas en clases "base" como tiene cualquier lenguaje 100% Orientado a Objetos (tienen clases como String, Integer, etc, y si usamos un IDE veremos fácilmente toda la lista de métodos disponibles que se aplican a ese contexto concreto).

Nota al margen: hace unos años hicimos un experimento educativo y varios de mis alumnos de mi primer taller piloto a distancia hicieron un pequeño proyecto final que consistía desarrollar clases de tipo "wrapper" que cumplieran este objetivo (siguiendo el API de Java).

Espero que algún día PHP6 o 7 incorpore por defecto este tipo de organización que nos beneficiará a todos los desarrolladores.

De paso les comento que a veces, en raras ocasiones, podemos descubrir en el manual clases que vienen por defecto en PHP, por ejemplo, DateTime:

date_default_timezone_set('America/Argentina/Buenos_Aires');

$date = new DateTime("2009-02-28");
$date->modify("+1 day");
echo $date->format("Y-m-d");

$date = new DateTime("2009-01-01");
$date->modify("-1 day");
echo $date->format("Y-m-d");

// Salida:
//
// 2009-03-01
// 2008-12-31

Y Netbeans detecta todos sus elementos en la ayuda contextual:


Más información (obviamente): Manual Oficial de PHP

PD: y nunca te olvides de conocer las Standard PHP Library (SPL)

¡Próximo lunes, cursos intensivos de 1 mes! (Zend ó POO)

Dada la insistencia de varios alumnos para cursar de forma urgente los cursos de Zend y de POO antes de terminar este año, se abre un período excepcional:

Para quienes estén urgidos de hacer estos cursos, el próximo lunes se abrirán dos grupos reducidos (casi personalizados) para cada uno de los cursos.

Curso intensivo de 1 mes (los dos meses en uno), en el cual tendrán que trabajar más intensamente y dedicarle más horas diarias.

Costo: USD 150 por todo el curso (cursas POO ó Zend).

Nota al margen: Los cursos los empecé a realizar buscando que sean económicos para todo el mundo, por lo tanto, para poder bajar un curso típico de USD 250 dólares a 50 fue que empecé a hacer grupos de 10 a 20 personas. Actualmente ya no da el tiempo para iniciar otro grupo de 2 meses porque nos vamos muy arriba de las fechas de fin de año, lo cual complica la continuidad de los alumnos. Para poder dedicarle a un grupo muy reducido de personas, de forma intensiva durante un período muy breve, el costo del curso se eleva.

Les informo que estos cursos son excepcionales y solo para quienes verdaderamente los necesitan de forma "urgente", de lo contrario, solo tendrán que esperar hasta principios de febrero del año que viene (fecha de nuevo inicio de cursos) y hacerlo en el plazo habitual (2 meses) a un costo promedio de USD 50.

Para hacer la compra deben ingresar a usuarios.surforce.com e ingresar a la sección "Comprar"

Cualquier duda estoy a sus órdenes ;-)

Evento: PHP Mini Meeting (Argentina)



Más información: php-mini-meeting

PD: es este próximo sábado, voy a intentar ir aunque sea un rato (últimamente estoy durmiendo tan poco que no sé si llego despierto como para dar una charla prolija, así que es probable que en esta oportunidad solo haga más que "acto de presencia" y apoye en lo que pueda).

Así que si quieren charlar de PHP5, POO, UML, Zend Framework, etc, bienvenidos, hay tema para rato ;-)

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? ;-)

Plagio, segundo intento: "Desarrollador Senior" versus "PHP Senior"

Parece broma, pero por accidente leyendo el sitio de illasaron.com llego a la siguiente noticia y me encuentro con que la misma persona del plagio anterior vuelve a la carga con un blog "poco original" (creado poco después del incidente que tuvimos), vuelve a copiar contenidos de este blog y ahora "los trabaja un poco más", cambia más palabras y sigue sin hacer referencia a su fuente original.


En mi cabezal dice desde hace años:

PHP Senior
Como convertirse en un "Desarrollador PHP Senior" y no morir en el intento... escrito por Enrique Place de SURFORCE

Ahora el agrega:

Desarrollador Senior
Como convertirse en un "Desarrollador web Senior" y no frustrarse en el intento... escrito por Arley Triana

Leyendo muy por arriba veo que tiene otro artículo parecido a uno que escribí, pero ahora le cambia más palabras para que sea más difícil de distingir... aunque sigue siendo evidente:

Nueva versión plagiada

Copio la captura del plagio que realizó en el blog anterior, y no puedo salir de mi asombro que siga intentando cambiar algunas palabras para que sea más difícil darse cuenta (hasta usa mi propio uml que hice con Argo)... pero sigue siendo tan evidente:

Vieja Versión Plagiada

Antes decía su Plagio Version 1: "tener una clase BaseDeDatos" ahora dice "tener una clase Database", antes decía "devuelve un objeto llamado bd" ahora dice "devuelve un objeto llamado $conn", pero mantiene los subtítulos "¿Ventajas / usos?" y los cambia por "¿Ventajas y usos?", etcétera, etcétera (si tienes tiempo encuentra las diferencias entre sus propias versiones de plagios que son bastantes y muy cómicas).

¿Soy muy paranoico o estamos ante un sorprendente caso de estupidez humana?

Más información

Artículo original y el Plagio Versión 2, todo por el mismo "autor", Arley Triana

Cambio de fecha de inicio de cursos: 7/Septiembre

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 una semana el inicio de los mismos.

Se extenderá el plazo hasta el próximo viernes (7/9) 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 7 / Septiembre.

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.

Para quienes sí hicieron el pago correspondiente, sepan disculpar el cambio de fecha. Desde ya les pido a todos que ingresen a http://usuarios.surforce.com y revisen que sus pagos y su asignación a su grupo se encuentra actualizada, de la misma forma, quienes compraron el libro de POO para PHP5, ya pueden bajarlo en conjunto con todo el material extra.

En caso contrario, por favor nos envían un email y lo revisamos.

Opciones del sistema:
  • Resumen de Compras, para ver todos los pagos acreditados
  • Cursos > Tus Grupos
  • Libros > Actualizaciones
  • Libros > Material Extra
Cualquier duda o problema estoy a sus órdenes.

¡Última semana, si no te inscribiste aún, luego no hay más excusas! ;-)

Copiar sin citar = Plagio


La verdad que estoy bastante molesto con este caso de Plagio. No es la primera vez que veo que una persona copia literalmente contenidos de este blog y los copia íntegros, y para peor, sin citar:

"Una persona comete plagio cuando copia o imita algo que no le pertenece haciéndose pasar por el autor de ello. Dicha acción, al estar protegida la obra legalmente por el derecho de autor, podría conllevar un juicio y una posible imposición de multas y la obligación de indemnizar los daños y perjuicios."


Claramente los contenidos de este blog tienen licencia Creative Commons (ver pié del sitio) y se aplican algunas restricciones. Existen distintas versiones de la licencia que puedes optar según tus intereses: en este caso puedes copiar, redistribuir y hacer obras derivadas, siempre y cuando cites al autor y no sea con fines comerciales (no quiere decir que no puedas lucrar con los contenidos, pero para eso debes pedir permiso).





Lo correcto sería que hiciéramos un comentario de un artículo que nos pueda gustar, hacer alguna cita de algún párrafo, pero no copiar íntegro el contenido que no permite distinguir si lo escribimos nosotros u otra persona (a menos que lo aclares explícitamente, avises cuando inicia algo que no escribiste, le agregues comillas, etc), pero esto es lo peor y ya muestra muy mala intención.


Esta persona, el Ingeniero Arley Triana Morín, vive en Cuba y hace un año tuvimos una pequeña discusión: me envió un email haciendo una consulta técnica y como no le respondí "inmediatamente", directamente me insultó.


Ahora bien, estaba borrando suscripciones a blogs desde mi Google Reader y de casualidad tenía a esta persona registrada. Luego de revisar un rato y encontrar "familiares" algunos temas y artículos (a veces mi memoria me juega malas pasadas), me percato que son copia literal de contenidos de este blog que escribí hace algún tiempo.


Nota: para peor cambia los enlaces que hacen referencia a otros articulos de este mismo blog por las copias en su propio blog (muy prolijo), ni que decir eliminar algunos párrafos con comentarios personales o cambiar levemente algún título.

A las pruebas me remito.


En resumen: Arley, yo por lo menos te "cito", y soy el autor original.

¿Por qué usar un (zend) framework?

Estas preguntas me la han hecho muchas veces, así que es buen momento para compartirlas en el blog :-)
  • ¿Para qué sirve un framework?
  • ¿Por qué Zend Framework?
  • ¿Cuales son las ventajas de no hacer todo yo?
  • etc
La idea de los frameworks es que son "cajas de herramientas" que puedes aprovechar en tus desarrollos... la filosofía del desarrollo profesional debería ser "¿cómo harías para construir una casa con las manos y sin martillos? imposible, no terminaría nunca, debo usar herramientas..."

Por ejemplo, no tienes que crearte tu propia clase de persistencia para recuperar o guardar datos, lo cual incluye además de lo básico, muchas funcionalidades que te ahorran tiempo y hasta te dan mayor seguridad por controles internos que ya incorporan de fábrica.

Si le sumamos que el esquema de trabajo es MVC, ya te da una forma de organizar tus sistemas, donde colocar cada cosa, etc, que te permite estandarizar y ahorrar mucho tiempo.

Un ejemplo bastante común: tú quieres validar un email que recibes de un formulario, en vez de tener que implementar toda esa parte (y hacerlo bien) puedes hacer uso de clases existentes como Zend_Validate_EmailAddress()

$email = $this->getRequest()->getPost(' email', 'none@example.com');
$validator = new Zend_Validate_EmailAddress();

if (
$validator->isValid($email)) {
// email seems valid
} else {
// email seems invalid; Outputting the reasons
}


Listo, sigues adelante y programas el resto de lo importante de tu sistema, ya que lo que te importa es terminar el trabajo, entregar el sistema y cobrar al cliente.

De alguna forma, muy resumida, te "profesionaliza".

No sé si quedó claro el ejemplo ;-)

PD: se podría decir que lo importante no es si usas Zend Framework (más allá que yo lo use), creo que deberías por lo menos conocer alguno y estudiarlo en profundidad para sacarle provecho en el reuso de componentes y experiencia de la empresa o grupo que lo desarrolló. Siempre existirán ventajas, más si tu eres un equipo reducido de desarrolladores y el framework fue hecho por un equipo más grande y especializado en su diseño y desarrollo, no lo hicieron en su tiempo libre.

"Apóyate en hombros de gigantes"

¿Entrando en la "optimización extrema"?

Siempre fui renuente a todos los artículos sobre "optimización extrema", ya que en PHP es muy poco probable que sirva hilar tan fino como para decir que:

++$a es más rápido que $a++ (aunque encontraremos opiniones opuestas)

Que foreach es más lento que un for, o que para imprimir varios valores en un echo es "más rápido" hacerlo con "," que con ".", etcétera.

No será la primera vez que diré que me parece una locura este tipo de optimizaciones, no tienen sentido en un ambiente web, en un entorno LAMP, y particularmente para PHP... a menos que estemos usando este lenguaje para hacer grandes "cálculos científicos" en memoria, pero estimo que si necesitas esto, erraste el entorno y el lenguaje para hacerlo.

"Optimizaciones Reales"


Para el que no lo sepa, en la actualidad trabajo durante la semana en una empresa argentina relacionada con productos / servicios vinculados a los celulares, y nuestra principal tarea es -muy resumidamente- enviar y recibir SMS (aunque ahora estamos empezando a trabajar con MMS).

También desarrollamos sistemas de administración y estadísticas para nosotros y para nuestros clientes (que son sistemas que ahora se hacen mayormente con Zend Framework), pero para estos sistemas nuestro tráfico es "reducido y controlado", lo opuesto a un servicio público como podría ser una red social donde los usuarios van creciendo día a día.

En este caso, de los sistemas web comunes, la "optimización extrema" no tienen ningún tipo de efecto, más que intentar hacer las cosas bien dentro de los "parámetros conocidos" y muchas veces estamos hablando de hacer las consultas sql de forma correcta (algo que no es tampoco común para la media de los desarrolladores PHP).

Pero en el primer caso, nosotros somos una empresa que podemos "estar orgullosos" que hacemos el envío de SMS/MMS a través de un ambiente web que incluye Apache, MySQL y PHP (aunque muchos podría discutir que no es la mejor tecnología, tal vez sería mejor usar arquitecturas como Java y puedo llegar a estar de acuerdo con ellos).

Desde hace unas semanas estamos haciendo funcionar una aplicación masiva en la que existen miles de usuarios enviando miles de SMS para juntar puntos en modalidad de "trivia" (se envían preguntas y se deben responder con opciones como "A" o "B") para un concurso que durará unos meses. Cada MO (mensaje originado por el usuario) enviado equivale a una instancia de apache evaluando la información recibida, registrando todos los datos y respondiendo a continuación con un MT (mensaje originado por el sistema). El juego cambia de comportamiento de acuerdo al tipo de jugador, tiene incentivadores que motivan al jugador seguir en carrera, le informa los puntos, le envía nuevos desafíos, lo recaptura si deja de jugar por distintas unidades de tiempo, etc.

Y aquí es donde entra la optimización que yo le llamaría "extrema". Les comparto algunas prácticas que fui aprendiendo sobre la marcha para que las discutamos juntos a ver que les parece y si no son tan esotéricas como las "++$a versus $a++":

Evitar el acceso a la base de datos

Generalmente el "cuello de botella" de los servidores está en el acceso a disco, el consumo de procesador es mínimo, pero sí es crítico el acceso a la base de datos y el principal recurso es acceder al disco. Una decisión de diseño fue evitar en algunos casos acceder a una tabla para traer datos y los dejamos "estáticos" en un array dentro de una clase (evitamos conectar, consultar, traer datos, desconectar).

Desventajas: perdemos "flexibilidad" ya que en vez de tener un admin que acceda a una tabla hay que modificar el código en el fuente (en nuestro caso son datos que no cambiarán frecuentemente y más que flexibilidad buscamos rendimiento y que el sistema no quede sin recursos).

Evitar repetir el acceso a base de datos

Nuevamente, nuestro cuello de botella. Algo muy común cuando desarrollamos orientado a objetos es que cada objeto es independiente del otro, y si lo hacemos "3 capas", en algún momento cada objeto terminará accediendo a la base de datos por su cuenta.

Me ha pasado de implementar un log que activo con todas las consultas del sistema y ver que se repiten algunas consultas dentro del mismo acceso al sistema, una y otra vez, cuando en sí están trayendo la misma información.

Por ejemplo (el ejemplo no es real, pero lo que importa es el concepto), imaginen que tengo el nombre del usuario en la base de datos y cada vez que hago algo como $jugador->getNombre() hace un SELECT nombre FROM jugadores WHERE id = 100;. Como la instancia se usa en varias partes del sistema y requiere verificar información del nombre en distintas oportunidades, esta consulta se repite "n" veces. Para evitar esto se cambia la operativa por una "carga tardía" (lazy load), nunca cargar nada hasta que lo necesite (no cargues toda la información en el constructor del objeto), y cuando ya tenga el valor, y si es un valor que no tiende a cambiar/actualizarse, retornar su contenido sin ir nuevamente a la base (parece tonto, pero hasta que no lo detectas que lo estás haciendo no tomas conciencia de que debes evitarlo).

Antes lo podrías tener así:



Luego lo podrías cambiar por:



Mejorar el acceso a base de datos

Algo que es poco común que un desarrollador domine, hacer correctas consultas a las bases de datos, agregar índices según lo que necesitemos hacer, evitar los índices en los lugares que no conviene, verificar el tipo de cada campo y si realmente es el que necesitamos.

Algunas pautas que recuerdo ahora:
  • Revisa por qué campos haces normalmente las condiciones de tus WHERE y crea un índice (recuerda que las claves primarias generan implícitamente un índice).
  • Recuerda que por cada índice que agregues tu tabla se recarga si esta tienen que actualizar los datos constantemente, ya que hará un "insert" en la tabla real y luego deberá actualizar el índice (como si fueran dos tablas). Si tienes 100 índices, y es una tabla grande y con muchas actualizaciones, será mejor que te tomes el tiempo y veas cual puedes eliminar.
  • Diferencia las tablas de "lectura/escritura" sobre las de "solo lectura". Si tu tabla necesita hacer ambas y sabes que crecerá, limita la cantidad de índices (ver punto anterior), pero si es de solo lectura, puedes tomarte la libertad de agregar más índices que en el primer caso.
  • Usa los mismos tipos y largos en los campos de tus tablas: si creas jugador_id y es un int(11), que así sea en todas las demás tablas, ya que unir campos que son de distintos tamaños tendrá un costo de conversión al compararlos.
  • Diferencia lo que es un varchar de un char: si tus valores de texto serán fijos, es decir, tienes un campo de 100 caracteres que será probable que siempre esté lleno, usa char(100), si puede que esté lleno de caracteres o existan casos donde no tenga nada, o pocos (10 caracteres), define que es de tipo varchar (var = variable).
  • etc
En estos casos (bueno, siempre) el manual del motor de base de datos es tu amigo.

No tengas miedo de desnormalizar una base de datos

Lo aprendí con el tiempo, no ser extremista y purista, luego de aprender las reglas, descubre cuando se justifica romperlas para sacar más provecho ;-)

Nos pasó que ante un tráfico masivo de datos estábamos teniendo un crecimiento desmedido en tablas que registran la entrega y salida de SMS, y que cuando queríamos hacer un cruzamiento de datos entre otras tablas, las consultas nos generaban pérdidas de segundos muy valiosos.

Por ejemplo, si nosotros tenemos un sistema que maneja múltiples carriers, por lógica deberíamos tener en la tabla de participantes el número de celular y el número de carrier al cual corresponde. En sistemas donde las tablas de participantes pueden crecer exponencialmente no es conveniente que por cada MO tengamos que acceder a una tabla extra para saber esta información, por lo que en tablas importantes "desnormalizamos" su acceso y duplicamos estos campos para evitar tener que hacer un join contra una tabla extra (y así con otros datos).

Duplica campos en distintas tablas (número de teléfono, carrier, id de usuario, etc) para evitar tener que hacer joins contra una tabla que crece y se actualiza constantemente.

Evita acceder a los datos de producción para hacer consultas

Aunque puede ser obvio, evita tener un sistema de estadísticas para tu clientes que hagan consultas directas contra una base de datos en producción. Cualquier consulta compleja puede tirar el rendimiento de tu sistema. Puedes intentar duplicar la base en otro servidor una vez al día, o simplemente crear "tablas resúmenes" con un proceso que corre cada "x" horas y en vez de sumar todos los datos cada vez que se consulta, ya lo haces en la carga y el sistema de estadísticas muestra solo los totales.

Si quieres darte un lujo, solo accede a producción para dar datos "reales" con un "count", y si quieres acceder a tablas, que estas no sean las más usadas.

En resumen

Fuera que descarto que debemos diseñar bien nuestro sistema pensado cual será el contexto en el cual funcionará, pensar en las clases y sus relaciones, y ver si estamos programando correctamente, a menos que estemos hablando de muchas clases por cada vez que hay una invocación en nuestro sistema (estoy hablando de 50 clases o más), lo más probable es que la optimización no se deba hacer en el código PHP, probablemente esté más orientado hacia nuestra comunicación con la base de datos (y descarto que ya estamos usando algún sistema de caché del lado del servidor).

Sé que no es de todos los días tener este tipo de situaciones de cantidades masivas de tráfico, pero cuando ocurren, estos detalles afectan el rendimiento o directamente la estabilidad del servidor.

¿Tienes algún tips para compartir? ¿cual fue tu experiencia en estos casos? ;-)

Artículos relacionados:

Entradas populares