Archive for September, 2007

Editores para PHP5 - OpenKomodo y Eclipse PDT

Monday, September 17th, 2007

Mucha gente se dedica a programar usando bluefish o quanta; en mi caso muchas veces recomiendo screem (aunque por alguna razón extraña en debian y fedora (mis distros) screem es medio “buggy”); sin embargo, todos ellos son editores (x)html con algo de coloreado de sintaxis y autocompletado de tags y esas cosas (screem tiene una funcionalidad “parcial” de autocompletado de funciones de php).

Sin embargo, como programador eso es una “infima” parte de lo que necesitas; necesitas autocompletado real de código, tanto de tu código como el de funciones de php (estaremos de acuerdo que a falta de namespaces, los nombres de funciones en php5 son a veces una pesadilla); se necesita ayuda contextual sobre parámetros; administración (si es posible) automática de los comentarios (sobre todo bloques PHPDoc y Doxygen), descubrimiento de bloques, depuración, resaltado de errores y una gran cantidad más de adiciones que se agradecen.

Komodo Edit 4.0 (alias: OpenKomodo):

Hace algún tiempo me dediqué notablemente a usar Komodo Edit 3.5 (hasta llegar a la 4); era bueno, basado en xpcom+XUL (engine Mozilla), es rápido, ligero y viene con todas esas características de resaltado de sintaxis, completado de código, etc.

Veamos algunas características interesantes:

  • Find all functions: permite listar todas las funciones declaradas en tu archivo php.
  • Crear snippets de código para pegar con solamente arrastrar y soltar (o asignarle un key-binding para amantes del teclado)
  • posee una característica de “vim-emulation” bastante interesante.
  • Trabajar con múltiples proyectos a la vez
  • Indicar que haga un “scanning” de nuestros proyectos para que el auto-completado de código funcione correctamente
  • Indicar donde queda nuestro php para realizar autocompletado (se extraña la caracteristica de agregar xdebug y permitir profiling y debugging de código que tenia la versión propietaria de Komodo ActiveState).
  • Crear macros para automatizar tareas
  • Manejo de multiples tipos de documentos XML, Doctype, Namespaces y Schemas (util a la hora de crear documentos XML)
  • Si te detienes en una llave, resalta donde ha iniciado ese bloque de código
  • Resaltado de errores html (por si estas diseñando templates)
  • Puedes agregar schemas y DOCTYPE propios para que comprenda las nuevas tags
  • Sistema de templates para no repetir la construcción de archivos, html, hojas xslt o clases php.

Cosas que se extrañan:

  • No auto-completa las llaves de apertura o cierre de funciones, tampoco autocompleta los cierres de paréntesis ni actualiza los parámetros al escribirlos
  • Es mas un “editor con vitaminas” que un IDE; pero al compararlo con bluefish, se agradece que lo hayan liberado.
  • Necesitas definir el tipo de documento para que pueda hacer correctamente el code-folding (cerrar un bloque de declaración para ahorrar espacio, muy util!).
  • Algo de cariño a PHP, sigue siendo un editor que tiende más a Python o a Perl

Algunos screenshots:

inicial.png
Pantalla inicial de Komodo Edit

index.png

Pantalla en modo editor - a la izquierda, un proyecto de Komodo

preferencias.png

Hay que “configurar” en preferencias a php para que funcione el auto-completado, pero podemos agregar proyectos propios
autocomplete_komodo21.jpg

El auto-completado se puede hacer incluso de clases propias de nuestro proyecto (realmente ahorra tiempo cuando el proyecto es grande) 

autocomplete_komodo.jpg

El autocompletado se puede realizar incluso con el objeto ya creado (un circulo verde para métodos, un triangulo azul para propiedades del objeto)

auto_komodo3.jpg
El auto-completado tambien incluye los parámetros de nuestras funciones de usuario. 

snippets-komodo.jpg

No tenemos bloques doxygen o phpDoc, pero podemos “crearlos” usando un snippet, podemos incluso agregarle un icono distintivo a dicho snippet y hasta un acceso de teclado.

xml_komodo.jpg

Se agradece la cantida increible de modos para trabajar con archivos XML (para ser un xml editor, screem es algo “laxo” en estas cosas).

En fin, un muy buen editor, si se pudieran agregarle algunas cosas IDE (como profiling, debugging, gestión desde el subversión, etc); por su rapidez (usa XUL, como firefox) sería la maravilla de los editores/IDE para PHP5.

Pagina Oficial: http://www.activestate.com/openkomodo/ 

Eclipse PDT:

Con algunas ideas del Zend Editor (Zend e IBM trabajan colaborativamente en este IDE/Plugin para Eclipse) el Eclipse PDT es totalmente un serio compromiso como un IDE para programación en PHP.

Características Interesantes:

  • Verdadero auto-completado (escanea el proyecto, no se necesita incluir el objeto)
  • Outline (muestra la estructura en métodos, propiedades de nuestra clase)
  • Puede mostrar la herencia de nuestras clases
  • Inserta bloques PHPDoc útiles para comentarios
  • Auto-completa llaves, paréntesis, auto-tabula el código de acuerdo a reglas pre-definidas o propias
  • Muestra los errores de PHP incluyendo un tooltip mostrando cual es el error
  • Code-Folding, podemos “cerrar” bloques de código como funciones, clases o incluso comentarios
  •  Auto-Format Document (CRTL+SHIFT+F) no es la panacea, pero auto-indenta y formatea nuestroa archivos automágicamente (una maravilla si se te olvida indentar correctamente).
  • No importa si 200 lineas atrás comenzó el bloque de código, si insertas una llave cerrando, el sabrá cual és.
  • Auto-completa tags, atributos html, incluso auto-completa comentarios de PHPDoc
  • Multiples proyectos a la vez
  • El Proyect Explorer es algo engorroso a veces, pero despues te acostumbras a su forma de organizar archivos y carpetas
  • Refactor: Mover o renombrar un archivo re-acomodará (a veces no) todas las declaraciones de este archivo dentro de tu proyecto actual

Contras:

  • Java: su sola ejecución me pone en el techo el consumo de recursos (casi 200MB de RAM se consume el Eclipse PDT)
  • Profiling es algo dificil de activar (al menos para PHP)
  • No reconoce javascript y CSS, asi que te llena la ventana de “Errors & Warnings” de supuestos “errores de sintaxis” de PHP en documentos javascript.
  • El debugger es una maravilla en aplicaciones sencillas, en un entorno MVC es casi inusable

 Algunos ScreenShots:

 

inicial_pdt.png

 Pantalla completa del Eclipse PDT, se agracede un coloreado de sintaxis bastante entendible (y poco vistoso, util para las largas horas de programación no cansen la vista).

comments.jpg

Son útiles la administración de bloques de comentarios, sobre todo de bloques PHPDoc y Doxygen

explorer.jpg

El  Proyect Explorer muestra todos nuestros documentos y los archivos contenidos en él (aunque a veces prefiero que se comportara como el de Komodo).

outline.jpg

Outline: Muestra la estructura de nuestra(s) clase(s) de nuestro archivo actualmente abierto (en foco en el área de documentos); es de hacer notar que gestiona correctamente las herencias entre clases (comos se muestra e los circulos verdes con una “c”, indicando clases (e I para las interfaces)), vale de resaltar la notación de PDT para esto, circulo verde: funciones publicas, rombo amarillo, funciones privadas, rombo más pequeño, métodos privados, circulo pequeño verde con un punto blanco en el centro, métodos publicos, Si la definición agrega una S en superindice de color rojo, indica que el método o propiedad es estático.

code_folding.jpg

Code Folding: por defecto todas las funciones aparecen en un modo “cerrado” (Fijense en el circulo con el icono + dentro); lo que ahorra mucho espacio en pantalla y evita confusiones.

code_folding2.jpg

Cuando te paras sobre un icono de Code-Folding; veremos un tooltip con el código que el code-folding está ocultando. 

autocomplete_pdt.jpg

El autocompletado de código incluye funciones de usuario, mostrando incluso los parámetros de cada método; usa la misma notación que el Outline para representar cuales son privados, públicos o protegidos. 
El Autocompletado tambien  incluye las variables y propiedades, cada vez que coloquemos el simbol de variable ($) aparecerá esta lista de selección en pantalla.

find.jpg

Entre la ayuda contextual que podemos encontrar, está la posibilidad de ver donde fue declarada una función, incluyendo la posibilidad de ir a la declaración de la misma (Menu Contextual -> open Declaration).

phpdoc.jpg

Podemos agregar bloques de comentario PHPDoc, para poder comentar nuestras funciones.

doc.jpg

PDT puede (al reconocer un bloque PHPDoc) autocompletar las directivas de PHPDoc con simple escribir un @ (el inicio de una directiva PHPDoc).

task.jpg

Podemos gestionar las Tags (etiquetas) que usaremos para marcar nuestras “tareas” (por ejemplo TODO), al agregar un comentario con dicha etiqueta (ej: //TODO: terminar esta funcion) PDT generará la lista de tareas pendientes de la aplicación.

task2.jpg

Y generar la lista de “tasks” que son las tareas pendientes de la aplicación.

Página Oficial: http://www.eclipse.org/pdt/ 

Como verán, no necesitamos conformarnos con un “simple editor de texto” (he visto gente trabajando con gedit, sin recordar las nefastas consecuencias de las “copias de seguridad” que hace gedit y varios editores bajo gnome y kde) cuando contamos con par de herramientas que pueden no solamente servirnos de editor de código, sino como un completo administrador de proyectos para PHP.

Si alguien es amante de las recomendaciones personales, en mi caso uso ambos, cuando necesito dedicarme exclusivamente a programar (y de repente a escuchar música) sin más nada, puedo usar Eclipse, que aunque es pesado, como hemos visto posee una y mil características que lo hacen un IDE muy util (y hasta necesario); si voy a trabajar varias aplicaciones a la vez (cssed para editar hojas de estilo, preview en el browser (swiftfox) y una serie de aplicaciones más abiertas, evidentemente me decanto por openKomodo.

Pero la decisión queda en ustedes …

mySQL functions: Paro Forzoso (II parte)

Monday, September 17th, 2007

Y bueno, del anterior post (SSO) vamos a presentar el código que calcula el Paro Forzoso, es bastante más sencilla que la anterior función asi que la posteo completa y sin comentarios adicionales:

 

DELIMITER $$
 DROP FUNCTION IF EXISTS `nomina`.`paro_forzoso`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `paro_forzoso`(sueldo DECIMAL(8,2)) RETURNS decimal(8,2)
READS SQL DATA
BEGINDECLARE porcentaje DECIMAL(2,2);
DECLARE lunes INT;
DECLARE mes INT;
DECLARE fecha DATE;
DECLARE primero DATE;
DECLARE quince DATE;
SELECT curdate() INTO fecha;
SELECT DAYOFMONTH(fecha)  INTO mes;
SELECT STR_TO_DATE(CONCAT(YEAR(fecha), '-', MONTH(fecha), '-', 1), '%Y-%m-%d') INTO primero;
SELECT STR_TO_DATE(CONCAT(YEAR(fecha), '-', MONTH(fecha), '-', 15), '%Y-%m-%d') INTO quince;
SELECT valor INTO porcentaje FROM parametros WHERE parametro = 'paro';
IF mes <= 15 THEN
BEGIN
SELECT (WEEK(quince,5) - WEEK(primero,5)) INTO lunes;
END;
ELSE
BEGIN
SELECT (WEEK(LAST_DAY(fecha),5) - WEEK(quince,5)) INTO lunes;
END;
END IF;
return TRUNCATE((((sueldo*12)/52)*(porcentaje*lunes)), 2);
END$$
DELIMITER ;

Lo unico importante de comentar es agregar a la tabla parametros el porcentaje del paro forzoso (0.005) o lo que es igual:

 

INSERT INTO parametros VALUES('paro', 0.005, 0);

y es todo! … para calcular ambos (paro forzoso y sso) desde una tabla, digamos “empleados”, donde tenemos el sueldo base, eso sería:

 

SELECT sueldo_base, sso(sueldo_base, 0) as seguro, paro_forzoso(sueldo_base) as paro FROM empleados.

Calculando el Seguro Social con un procedimiento almacenado de mySQL 5

Sunday, September 16th, 2007

Hace algún tiempo atrás habia realizado esta y otras funciones para mySQL 5 en un proyecto de nómina (no sé como les terminó de ir) y quise publicarlo ahora ya que algunas personas me habian pedido esta función.

La función almacenada de mySQL consiste en un simple calculo de la cuota del Seguro Social Obligatorio Venezolano; hacerlo en procedimiento almacenado?, claro!, todos los datos necesarios para realizar el cálculo se encuentran del lado del servidor, por qué llevarlo al lado de la aplicación (Lenguaje de programación) para realizar un calculo que enteramente puede realizar la DB?.

Habia hecho esta función junto con otras 15 de conceptos de nómina para unos amigos que estaban desarrollando un sistema.

Primero; vamos a comentar el código; despues aparecerá integramente.

Concepto de Funciones en mySQL 5.

Una función es un pequeño “script” de código SQL (si fuera postgresql; pudiera ser en python o hasta en php) que puede ser convocado en la línea de una instrucción SQL; ejemplo:

SELECT md5(password), CURDATE() as fecha_actual, CURTIME() as hora_actual FROM usuarios

En el ejemplo anterior, las resaltadas son funciones internas de mySQL (una calcula el checksum md5 de una cadena; las otras devuelven la fecha y la hora actual).

Se pueden crear funciones propias, la diferencia entre una función y un procedimiento almacenado en mySQL es que una función SIEMPRE debe devolver un valor y este valor debe ser un escalar (un número, una cadena, el valor de un campo de una fila, etc); un procedimiento almacenado puede devolver escalares, filas, resultsets completos o simplemente no devolver nada.

SSO (Seguro Social Obligatorio) for Dummies.

El SSO Venezolano se calcula en base a los lunes contabilizados del mes, la formula suele ser:

 

((sueldo*12 meses) / Semanas laborales(default: 52)) * (retención SSO (defecto: 0.04)*lunes del mes)) <-redondeado a 2 cifras

Bien; ahora describamos el asunto:

La tabla parámetros:

Es un verdadero fastidio tener que modificar una costante (lease IVA, SSO, retención ISLR, algún gravamen) cada vez que el gobierno decide modificarla; por ende, es mejor guardar este valor en una tabla de parámetros; en dicha tabla, podremos guardar los porcentajes y valores de los distintos conceptos; de esta manera no tendremos que editar la función si de repente estos valores cambian:

La forma de la tabla es como sigue:

 

CREATE TABLE  `nomina`.`parametros` (
  `parametro` varchar(10) NOT NULL default '',
  `valor` decimal(3,3) NOT NULL default '0.000',
  `patronal` decimal(3,2) NOT NULL default '0.00',
  PRIMARY KEY  (`parametro`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

e Insertamos un registro como el siguiente:

 

INSERT INTO parametros VALUES ('sso',  0.04,  -0.87);

A los patronos se les retiene el doble de lo que se le retiene al empleado.

La función Almacenada SSO:

Oficialmente el delimitador de sentencias de mySQL es el punto y coma (;), por ende, debemos cambiarlo antes de poder escribir una función almacenada (que termina todas sus sentencias en punto y coma) para ello escribimos:

DELIMITER $$

Y ahora cuando terminemos de escribir la función almacenada escribimos:

END$$ (en vez de END;)

Ahora viene el cuerpo de declaración de la función:

DELIMITER $$

DROP FUNCTION IF EXISTS `nomina`.`sso`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `sso`(sueldo DECIMAL(8,2), tipo INT) RETURNS decimal(8,2)

Inicialmente ejecuto un DROP IF EXISTS que me permite verificar si la función existe y borrarla (en caso que estuviera editandola; no existe ALTER FUNCTION o ALTER PROCEDURE, por lo que hay que borrar primero un procedimiento si deseamos cambiarlo).

La directiva SQL SECURITY DEFINER nos indica que la función se ejecutará en un ámbito de permisos igual a quien creó la función (forma por defecto); la otra forma INVOKER hace que la función se ejecute en el ámbito de permisos de quien la ejecuta; para un ejemplo:

Tengo permisos sobre la tabla A y creo una función con DEFINER que lee esa tabla -> resultado -> La función puede leer la tabla A
Creo una función que intenta leer la tabla B y no tengo permisos para leer esa tabla -> resultado -> La función no puede leer la tabla B
Creo una función con INVOKER que lee la tabla B y usuario que invoca la función puede leer B -> resultado -> la función puede leer B
Creo una función con INVOKER que lea la tabla A y usuario que invoca NO puede leer la tabla A -> resultado -> La función no puede leer la tabla A.

DEFINER pide el usuario que deseamos colocar como DEFINER.

FUNCTION sso() es la declaración de función y pide algunos parámetros (dentro del paréntesis); estos son sueldo (de tipo DECIMAL(8,2), longitud integer 8 con 2 decimales de precisión) y un tipo (que es un entero 1 o 0); la situación es que en Venezuela, hay 2 cotizaciones de SSO; la nacional (0.04) y la estadal (0.02, es menor porque por lo general en las zonas rurales no hay Seguro Social, asi que para que te voy a retener algo que no existe?); la función retorna un valor escalar (el SSO calculado) de tipo DECIMAL(8,2).

Las funciones de mySQL repito, tienen 3 limitantes:

 

  • No pueden conectarse (por defecto) a datos en otras tablas.
  • No pueden recibir parámetros de salida (todos los parámetros son de entrada)
  • Solo pueden devolver escalares

Para obviar la primera observación (para que nuestra función pueda obtener datos desde otras tablas) entonces agregamos a la declaración:

READS SQL DATA

Y eso permite a nuestra función ejecutar sentencias SQL dentro del código.

El cuerpo de la función:

BEGIN
DECLARE porcentaje DECIMAL(2,2);
DECLARE lunes INT;
DECLARE mes INT;
DECLARE fecha DATE;
DECLARE primero DATE;
DECLARE quince DATE;
SELECT curdate() INTO fecha;
SELECT DAYOFMONTH(fecha)  INTO mes;
SELECT STR_TO_DATE(CONCAT(YEAR(fecha), ‘-’, MONTH(fecha), ‘-’, 1), ‘%Y-%m-%d’) INTO primero;
SELECT STR_TO_DATE(CONCAT(YEAR(fecha), ‘-’, MONTH(fecha), ‘-’, 15), ‘%Y-%m-%d’) INTO quince;
IF tipo=0 THEN
SELECT valor INTO porcentaje FROM parametros WHERE parametro = ’sso’;
ELSE
SELECT valor INTO porcentaje FROM parametros WHERE parametro = ’sso-estado’;
END IF;
IF mes <= 15 THEN
BEGIN
SELECT (WEEK(quince,5) - WEEK(primero,5)) INTO lunes;
END;
ELSE
BEGIN
SELECT (WEEK(LAST_DAY(fecha),5) - WEEK(quince,5)) INTO lunes;
END;
END IF;
return TRUNCATE((((sueldo*12)/52)*(porcentaje*lunes)), 2);
END$$

DELIMITER ;

Algunas observaciones útiles:

DECLARE sirve en ANSI DB2 SQL (la base de mySQL) declarar variables a ser usadas dentro del código.

SELECT INTO … permite hacer un SELECT de un escalar y devolverlo a una variable interna:

SELECT valor INTO porcentaje FROM parametros WHERE parametros = 'sso'

La función calcula el SSO quincenalmente, determinando primero a partir de la fecha actual, en que quincena estamos y retornando la cantidad de lunes de esa semana:

IF mes <= 15 THEN
    BEGIN
    SELECT (WEEK(quince,5) - WEEK(primero,5)) INTO lunes;
    END;
ELSE
    BEGIN
    SELECT (WEEK(LAST_DAY(fecha),5) - WEEK(quince,5)) INTO lunes;
    END;
END IF;

Posteriormente computa el resultado y lo devuelve con dos cifras de precisión usando TRUNCATE().

Le faltan muchas cosas a esta función (como que la fecha sea parametrizada y no que la tome de la actual) y cosas así; pero tomemos en cuenta que no tengo mucha experiencia en administración y esta función la construí con una experta en nómina sentada a mi lado.

Espero que entiendan algunas cosas más de la construcción de procedimientos almacenados y funciones almacenadas en mySQL.