margenn

PHPStorm

Todos los que utiliceis a diario IDEs basados en Java para programar sabreis que no son especialmente rápidos, especialmente con archivos grandes o cuando tenemos muchos archivos abiertos.

Sin embargo hay algunas recomendaciones y trucos para que nuestro IDE basado en Java funcione más rápida y agilmente.

En margenn, después de haber probado opciones como Netbeans, Eclipse PDT o Aptana, elegimos utilizar PHPStorm, de JetBrains, y la verdad es que para nosotros no hay vuelta atrás, sin duda es el mejor. 

A continuación expongo mi guía de optimización de rendimiento de PHPStorm:

1. Deshabilita todos los plugins que no utilices en tu día a día

 En mi caso, programo con PHP, JS, HTML y CSS por lo que todo lo demás sobra para mi. Estos son los plugins que he deshabilitado (y no son pocos):

  • ASP
  • CVS Integration (Usamos Subversion, Mercurial o Git)
  • Database Support (Desarrollo en remoto - FTP)
  • Java Server Pages Integration
  • LESS support
  • Perforce Integration
  • Phing Support
  • QuirksMode
  • Refactor-X
  • RELAX-NG Support
  • SASS support
  • SpellChecker
  • SQL support
  • W3C Validators
  • XPathView + XSLT Support
  • YAML

2. Desactiva las “inspections” que no consideres necesarias

Especialmente en el caso de Javascript desactivar las inspecciones oportunas agiliza mucho el editor ya que cada vez que editas tu archivo, tiene que escanear todo de nuevo para entender cómo se relaciona el nuevo código que escribes con el existente.

Estas son las que he deshabilitado para Javascript por diferentes motivos:

  • Unnecessary Semicolon
  • Unresolved Function
  • Unresolved Variable
  • Mismatched Collection Query Update Inspection
  • Potentially Invalid Constructor Usages
  • Suspicious Name Combination Inspection
  • Implicitly Internal Declaration
  • Untyped Declaration

Ahora cuando edito un archivo el editor no se ralentiza y la CPU no se pone al 100%.

Deshabilitadas para HTML:

  • Form input without an associated label
  • Image size mismatch
  • Malformed content of <script> tag

Como nota adicional también he deshabilitado todas las inspecciones de PHPDoc, Probably bug y XML.

3. Desactiva las “intentions” que no consideres necesarias

Las intenciones también tienen su impacto en el rendimiento aunque en un grado menor. Desactiva todas las que no consideres útiles teniendo en cuenta tu estilo de código (formato).

Si observais, de nuevo, el lenguaje que más intentions tiene es Javascript.

4. Amplia la memoria disponible para la máquina virtual

En margenn utilizamos exclusivamente MAC OS X (Windows en virtual para testear unicamente):

  • Buscad la aplicación PHPStorm, click secundario y “Mostrar contenidos del paquete”.
  • En el directorio “Contents” encontrareis el archivo “info.plist”, abridlo con TextEdit o XCode.
  • Cambiad la configuración del parámetro VMOptions.i386 a la siguiente:
    -Xms512m -Xmx1024m -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=128m
  • Cambiad la configuración del parámetro VMOptions.x86_64 a la siguiente:
    -Xms512m -Xmx1024m -XX:MaxPermSize=512m -XX:ReservedCodeCacheSize=128m -XX:+UseCompressedOops

En Windows y Linux la ruta y el nombre del archivo de configuración es diferente pero los parámetros son los mismos.

A continuación explico qué significa cada parámetro:

  • -Xms512m: Tamaño de inicio de la memoria de tipo heap de la máquina virtual de Java a 512Mb. El valor por defecto que establece PHPStorm es de 128Mb. Si se aumenta este valor, se elimina el tiempo que se tardaría en aumentar el tamaño en memoria de la máquina virtual si se llegara el caso de que se necesitara más memoria, por lo que aumentaría el rendimiento en los casos que la aplicación haga uso intensivo de la memoria.
  • -Xmx1024m: Tamaño máximo de la memoria de tipo heap de la máquina virtual de Java a 1024Mb (1 Giga).  El valor por defecto que establece PHPStorm son 768Mb. Si la aplicación supera el tamaño máximo de memoria que marca este parámetro, se lanza la excepción java.lang.OutOfMemoryError.  No conviene asignar a este parámetro el máximo de la memoria de nuestro ordenador porque si ya no queda memoria RAM disponible (por la que usa el sistema operativo u otras aplicaciones) se pueden producir escrituras en memoria asignada a otros programas y provocar un auténtico lío.
  • -XX:MaxPermSize=512m: Tamaño máximo de la memoria de tipo PermGen (non-heap) a 512Mb. El valor por defecto de PHPStorm es 250Mb (i386) o 350Mb (x86_64). Si la aplicación supera el tamaño máximo de memoria para este tipo que marca este parámetro, se lanza la excepción java.lang.OutOfMemoryError: PermGen space. El valor necesario para este parámetro siempre suele ser menor que el de la memoria de tipo heap. Si se quiere especificar un valor distinto de 128Mb bastaría con sustituir el valor 128 del parámetro con el que se desee, siempre que sean múltiplos de 2 (64, 128, 256, 512, 768, 1024, 2048…)
  • -XX:ReservedCodeCacheSize=128m: Tamaño de la memoria reservada para caché de código. El tamaño asignado por defecto de PHPStorm es 64m.

Podeis echar un vistazo a la referencia completa de las opciones de máquina virtual de Java Hotspot.

Después de seguir estos pasos, os aseguro que notareis que PHPStorm funciona más ligero y no se ralentizará apenas al editar archivos grandes.

Hasta el próximo artículo!!

Tags: phpstorm webstorm jetbrains performance jidea java ide php

YUI 2.8 vs. Dojo 1.6 (I) - Calendario

Posted on March 19, 2011 by

A little bit about me

Me encanta Javascript! Mi compañero y socio Jano es quien mejor conoce cuánto me gusta. Ya desde mis inicios en el desarrollo web allá por 2006 cuando empezaba la revolución AJAX vi el potencial de dicho lenguaje para crear aplicaciones web altamente interactivas e incluso one-page-apps como Gmail. Además de tener potencial, el lenguaje me gustaba y era divertido jugar con él modificando una página, actualizando parte del contenido “por arte de magia” sin que la página sufriera un refresco, etc…

En dicha época (2005-2006) afortunadamente surgieron muchos proyectos cuyo objetivo era dotar a los desarrolladores de Javascript de herramientas que nos hicieran la vida más fácil a la hora de añadir interactividad y experiencia de usuario a una página o aplicación web.

Cuando por primera vez conocí jQuery, me pareció horrible…no era el javascript que yo conocía…me parecía alienígena y en un primer momento lo dejé de lado.

Un tiempo más tarde, jQuery no sólo ya no me parecía alienígena sino que lo consideraba fundamental para desarrollar un proyecto cross-browser y en una cuarta parte del tiempo.

Con el tiempo surgieron muchos frameworks, más de cien…pero eran menos de diez los favoritos y realmente buenos. De estos diez, dos llamaron mi atención: YUI y Dojo.

YUI y Dojo eran entonces y son hoy mucho más que una librería para manipular el DOM y realizar llamadas asíncronas con facilidad. Ofrecían y siguen ofreciendo un parque temático de widgets muy amplio y útil además de otras niceties como gestión de dependencias o internacionalización. Son Javascript frameworks con los que puedes construir una aplicación web de principio a fin sin utilizar librerías o plugins adicionales. No era ni es el caso de jQuery.

No quiero que se me entienda mal, me encanta jQuery pero para lo que fue concebido, ser la navaja suiza del DOM y aún sigue siendolo.

De modo que alucinado por lo que ofrecían tanto YUI como Dojo en aquel tiempo y la potencia de jQuery para manipular el DOM, tomé dos decisiones:

  • jQuery era (y sigue siendo) la mejor herramienta para manipular el DOM, mientras que YUI y Dojo ofrecían soluciones más pobres de modo que jQuery tenía que estar en mi arsenal.
  • YUI vs. Dojo: La decisión más difícil…probé ambos durante un tiempo y me convenció YUI por diferentes motivos:
    - Yahoo! 
    - Mejor documentación y organización
    - Comunidad mayor
    - Muy estable

Así que tenía dos herramientas sobre la mesa, jQuery y YUI y vi que ambas se complementaban. jQuery lo usaría para manipulación del DOM y gestión de los eventos y YUI para todo lo demás. So far, so good.

He pasado los últimos años utilizando esta solución mixta y con muy buenos resultados y experiencias pero desde el lanzamiento de Dojo 1.5 y la firme apuesta de Dojo por mejorar la documentación me he vuelto a replantear la pregunta ¿Qué herramienta(s) debo utilizar para el front-end development? Dojo 1.5 y esa pregunta han producido que escriba esta serie de artículos.

Como jQuery está para mi en otra liga distinta a la de YUI y Dojo, la cuestión es clara, ¿cuál elijo entre YUI y Dojo? y si elijo Dojo…¿podrá sustituir también a jQuery y convertirse en mi única herramienta? Si seguis esta serie conocereis mi decisión final.

Bien…y ¿cómo voy a comparar YUI y Dojo?

De la única manera posible, utilizando ambos head to head valorando qué ofrece cada uno y cuál resulta más productivo para las mismas tareas.

Hey…y ¿qué pasa con YUI 3?

YUI 3 lamentablemente está aún hoy bastante verde (incompleto y beta en su mayoría) como para ser comparado con YUI 2.8 o Dojo 1.6.

Se que YUI 2.x puede ser utilizado con YUI 3 para cubrir las carencias de este último pero no considero este hecho relevante ya que YUI 3 no es más que un rewrite completo de YUI 2, es decir, más de lo mismo pero con arquitectura, rendimiento y flexibilidad mejorados.

El calendario

En este primer artículo de la serie voy a comparar un widget que he utilizado bastante en los proyectos, el famoso calendario.

Os pondré en contexto, el objetivo del test o demo es asociar un calendario a un campo de texto de un formulario en el que el usuario debe introducir una fecha, de tal forma que cuando el usuario vaya a introducir la fecha, se despliegue un calendario para hacerle más cómoda la selección.

Sin más preámbulos echad un ojo al código fuente de la magnífica demo que he creado  :) y juguetead con ambas implementaciones del calendario antes de continuar leyendo.

Notas del desarrollo con Dojo:

  • Con 4 lineas de código terminado. 
  • El resultado es genial
  • HTML, CSS, comportamiento, localización (i18n), validación y advertencias visuales y localizadas en caso de fechas imposibles 100% automatizados.
  • He tardado 2 minutos
<form> 
    <fieldset> 
        <legend>Dojo calendar input</legend> 
        <label>Select a date:</label> 
        <input type="text" name="dojocalendar" data-dojo-type="dijit.form.DateTextBox" data-dojo-props="name:'dojocalendar',type:'text'"> 
        <input type="submit" value="Send"> 
    </fieldset> 
</form>          
dojo.require("dijit.form.DateTextBox");

Notas del desarrollo con YUI:

  • He necesitado crear HTML adicional (para poder mostrar el calendario) y asignar el atributo autocomplete=”off” al input para que el navegador no muestre un listado de fechas introducidas anteriormente por el usuario.
  • He necesitado crear estilos CSS adicionales.
  • He necesitado implementar todos los eventos de interacción del usuario con el campo de texto (focus porque no hay un indicador visual de que existen valores seleccionables, click para mostrar y ocultar el calendario y keyup para actualizar el calendario si el usuario escribe o cambia la fecha manualmente) y el documento (ocultar el calendario al hacer click tanto fuera del campo de texto como del calendario) para igualar el comportamiento de Dojo.
  • He necesitado localizar el calendario a mi idioma traduciendo las cadenas de texto del mismo e indicando aspectos como qué día de la semana es el primero en aparecer en cada semana de un calendario (Lunes, no Domingo).
  • He necesitado formatear la fecha devuelta por el calendario de dos formas: una de un modo humano y localizado para mostrarsela al usuario y otra en el formato literal date en SQL (como Dojo).
  • He necesitado bastantes más lineas de código.
  • El resultado es bueno, pero no tan bueno como el de Dojo ya que este incluso valida la fecha introducida por un usuario y si es una fecha imposible le alerta visual y descriptivamente además de en su localización. Para igualar el mismo comportamiento en YUI necesitaría un icono, rutina de comprobación de fecha válida, el widget para crear tooltips, el mensaje localizado a mostrar y más HTML y CSS.
  • He necesitado más de 30 minutos.
<form> 
    <fieldset> 
        <legend>YUI calendar input</legend> 
        <label>Select a date:</label> 
        <div class="yuicalendar-popup-wrapper"> 
            <input type="text" id="yuicalendarinput" autocomplete="off"> 
            <input type="hidden" id="yuicalendarhiddeninput" name="yuicalendar"> 
            <div id="yuiCalendarContainer"></div> 
        </div> 
        <input type="submit" value="Send"> 
    </fieldset> 
</form>  
(function(y){
    var initYUI = function(){
        var yue = y.util.Event,
            yud = y.util.Dom,
            yuiCalContainer = yud.get('yuiCalendarContainer'),
            yuiCalInput = yud.get('yuicalendarinput'),
            yuiCalHiddenInput = yud.get('yuicalendarhiddeninput'),
            
            setDate = function(type, args, obj) {
                var date = args[0][0], 
                    year = date[0], 
                    month = date[1], 
                    day = date[2],
                    userDate = (day < 10 ? "0" + day : day) + "/" + (month < 10 ? "0" + month : month) + "/" + year;

                yuiCalInput.value = userDate;
                updateInputDate(userDate);
                yuiCalendar.hide();
            },
            
            getDateFields = function(userDate){
                return userDate.split("/");
            },
            
            updateInputDate = function(userDate){
                var dateFields = getDateFields(userDate);
                yuiCalHiddenInput.value = dateFields[2] + "-" + dateFields[1] + "-" + dateFields[0];
            },
            
            updateCalendar = function(e){
                var month, year, dateFields, userDate = this.value;

                if (/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(userDate)) {
                    dateFields = getDateFields(userDate);
                    month = dateFields[1];
                    year = dateFields[2];
                    updateInputDate(userDate);
                    yuiCalendar.cfg.setProperty("selected", userDate, false);
                    yuiCalendar.cfg.setProperty("pagedate", month + "/" + year, false);
                    yuiCalendar.render();
                }
            },
            
            yuiCalendar = new y.widget.Calendar("yuiCalendarContainer", { 
                locale_weekdays: "1char",
                navigator: {
                    strings : { 
                        month: "Selecciona un Mes", 
                        year: "Introduce un Año", 
                        submit: "Hecho", 
                        cancel: "Cancelar", 
                        invalidYear: "Por favor, introduce un año válido" 
                    }
                },
                start_weekday: 1,
                MDY_DAY_POSITION: 1,
                MDY_MONTH_POSITION: 2,
                MDY_YEAR_POSITION: 3,
                MONTHS_LONG: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
                WEEKDAYS_1CHAR: ["D", "L", "M", "M", "J", "V", "S"]
            });
         
        yuiCalendar.selectEvent.subscribe(setDate);
        yuiCalendar.render();
        
        yue.on("yuicalendarinput", "keyup", updateCalendar);
        
        yue.on("yuicalendarinput", "focusin", function(e) {
            this.className = "focused";
            yuiCalendar.show(); 
        });
        
        yue.on("yuicalendarinput", "click", function(e) {
            if (this.className == "focused") {
                this.className = "";
                return;
            }
            
            if (yuiCalContainer.style.display == "block") {
                yuiCalendar.hide();
            } else {
                yuiCalendar.show();
            }
        });
        
        yue.on(document, "click", function(e) {
            var el = yue.getTarget(e);

            if (el != yuiCalInput && el != yuiCalContainer && !yud.isAncestor(yuiCalContainer, el)) {
                yuiCalendar.hide();
            }
        });
    };
    
    (new y.util.YUILoader({
        require: ["calendar"],
        loadOptional: false,
        onSuccess: initYUI,
        timeout: 10000,
        combine: false
    })).insert();
}(YAHOO));

Bueno, esas son mis notas de desarrollo…sin duda alguna Dojo ofrece muuuchas más ventajas sobre YUI en este escenario tan real y típico como la vida misma. Dojo cubre de forma automatizada y productiva todas las necesidades típicas en este escenario y por ello le doy un 10.

Por último he comparado las opciones que nos da cada framework en cuanto a usos del calendario más allá del típico (flexibilidad):

  • Con YUI podemos crear grupos de calendarios (Multi-Page)
  • Con YUI podemos seleccionar varias fechas en un mismo calendario (Multi-Select)
  • Todo lo demás puede hacerse con ambos frameworks de un modo u otro.

Tanto el Multi-Page como el Multi-Select de YUI me parecen de bastante poca utilidad la verdad. No he encontrado hasta la fecha un escenario donde haya necesitado dichas soluciones.

Conclusión

YUI 0 - 1 Dojo

Dojo ha demostrado ser mejor en todos los aspectos en esta comparación, dejando por los suelos a YUI.

¿Y vosotros qué opinais? ¿Con cuál os quedariais?

Espero que os haya gustado mi análisis y la demo, en el próximo combate entre YUI y Dojo analizaré otro widget, el autocomplete.

Stay tuned!!

Tags: yui dojo calendar calendario javascript framework widget

Wordpress: YouTube shortcode plugin

Posted on January 13, 2011 by

Durante el desarrollo de un proyecto basado en Wordpress 3 observé resignado la necesidad de crear mi propio plugin para insertar (embed) videos de Youtube en cualquier parte del sitio web.

Muchos pensareis que hay varios plugins que sirven para este propósito, pero lo cierto es que ninguno cumplía todos los requisitos:

  • Poder mostrar en una misma página más de n videos de Youtube cada uno con una configuración del reproductor diferente y utilizando shortcodes.
  • Soporte de todos los parámetros oficiales del reproductor de Youtube.
  • Interfaz del reproductor de video de Youtube automáticamente localizada en el idioma del usuario.
  • Soporte de Flash y HTML5.
  • Detección automática de navegadores web que no implementen Adobe Flash y en ese caso, utilización del nuevo código de Youtube para estos (iPhone, iPad y otros dispositivos no sólo de Apple).
  • Soporte de navegadores que no interpretan Javascript (Flash necesario para reproducir el video).
  • Cálculo automático de la altura del reproductor de video de Youtube.
  • Poder utilizar cualquier identificador de un video de Youtube.
  • Sin interfaz de admin.
  • Lo más ligero posible.

De modo que creé hace un par de días mi primer plugin para Wordpress, que cumple con los requisitos expuestos, y al que he bautizado Youtube shortcode.

Espero que os sea de utilidad ;)

Tags: wp wordpress plugin youtube shortcode video embed