Babel Types by example

BabelJS es una herramienta que siempre me ha interesado. Originalmente 6to5, transformaba Javascript «nuevo» en Javascript «antiguo». Esta era su funcion principal para que la tarea del desarrollador no fuese tan dura al tener que duplicar implementación y aun así soportar navegadores menos actualizados (todos sabemos de quien estamos hablando …).

BABEL

Desde eso ha llovido mucho. Hoy soporta Typescript, JSX y la casi por nadie utilizada sintaxis de Flow. Así como una millonada de plugins disponibles en npm hacen que desarrollar con tu sabor favorito de JS sea más fácil que nunca.

Para progamar un plugin de Babel la propia librería esta dividida en distintos paquetes para ayudar al desarrollo. Aunque para ello tienes que conocer bien la sintaxis de JS, así como las otras sintaxis que también soporta.

Una función es una pieza de código que puede ser llamada en otra parte invocandola con parentesis.

function foo() {
    // 
}

const bar = function () { /* ...*/ }

const biz = () => 24;

Pero no es lo mismo si esta función está declarada directamente, o asignada a una variable, o asignada a una variable y además es una arrow function.

El analizador sintactico (parser) de babel transforma el codigo a una estructura de árbol para transformarla más fácilmente. Este árbol es simplemente un objeto con otros objetos anidados. La estructura se puede visualizar muy bien en ASTExplorer, que es un proyectazo muy util para entender lo que pasa por detrás de la transpilación.

Y aquí llega la parte aun más interesante. El tipo de objeto creado para repesentar una función será una FunctionDeclaration, pero si la estamos asignando es un FunctionExpression. Y bueno para la arrow function es una ArrowFunctionExpression.

Porque sí, no son lo mismo, el programa no sería representado de una manera unívoca si no tuviesemos estos distintos tipos. Todos los tipos que existen en babel están documentados en babel-types, que es el paquete de la librería con funciones para crear y comprobar tipos. Así se facilita mucho el desarrollo de un plugin.

En la documentación oficial explican como se debe usar cada metodo para crear un tipo y que parametros necesita. También si tiene algun alias, si el tipo es de Flow, Typescript o JSX y eso está geniar pero … no es muy didactica.

Para hacer más facil la comprensión de a que se refiere el nombre de cada tipo he publicado una documentación extendida, babel-types-by-example, con uno o varios ejemplos del elemento resaltado en un ejemplo de código.

Documentación de un jsxAttribute en @babel/types by example

Cómo se puede ver, cada tipo es una unidad comprensible por el parser de babel.

Espero que el pequeño «highlight» en cada uno de los elementos sea de ayuda. Para mi, el hecho de encotrar cada uno de los tipos dentro del código está siendo una formación genial en el lenguaje. El proyecto y la documentación de los ejemplos es un trabajo todabía en progreso, pero ya va tomando forma.

No pretende ser una documentación alternativa, ya que el script para generarla se basa en la oficial. Actualmente en versión 7 y pronto en 8 que está en beta. Si el lector tiene feedback sobre el proyecto o quiere contribuir toda ayuda es bienvenida.

Bun va a cambiar las cosas?

Bun bun.sh de la empresa Oven genial juego de palabras no se si tanto como la herramienta que están haciendo.

Bun es Node.js + npm + bundler es una herramienta que llevo probando unos meses para hacer experimentos aqui y allá y la verdad es que es impresionante lo bien que va.

Alguien podria decir que es el nuevo Deno, pero Deno no es package.json compatible, y Bun si lo es, y a demás tiene soporte nativo para JSX y Typescript. Aunque por ahora lo haga igual que Babel.js, solamente eliminando el tipado y ejecutando JS. Solo eso ya es un avance.

Aquí dejo una charla bastante curiosa de Ryan Dahl de porqué empezó con Deno. Tiene un tiempo pero está muy interesante:

Por lo que sé Oven levantaon 7 millones de dolares de financiación para hacer Bun, nada mal. Son aun una startup pequeña pero promete mucho. No son mucha gente, aun están contratando programadores de Zig/C++, porque sí este nuevo JS engine está escrito en Zig, un lenguaje de proposito general y de bajo nivel del cual no conozco ningun otro projecto importante que lo use … ahora hay uno. Pero si tienes curiosidad hay un awesome zig con bastantes cosas.

Todo eso muy bien, pero ¿Va a cambiar Bun las cosas en el mundo JS?

Aun no está claro. Es un buen proyecto con el que jugar y experimentar. Quizas también para tooling, pero hay que tener en cuenta que de los 7897 commits en el momento de escribir esto, 5896 son de Jarred Sumner, el fundador de Oven y creador inicial de Bun.

Por ahora solo hay 7 developers con más de 100 commits, eso nos dice que aun no hay mucha comunidad. Son los empleados de Oven los que principalment contribuyen. Eso no está del todo mal, el proyecto es aun muy nuevo (2 años y medio es poco para un motor de JS de proposito general) y es razonable que esto sea así por ahora.

Como curiosidad me alegra saber que Colin McDonnel (colinhacks) el creador de zod y de la version inicial de tRCP es Developer Advocate en Oven. De hecho es uno de los top 7 devs en Bun. Es bueno para el proyecto, que un developer con bastante notoriedad esté tan involucrado.

Todo el mundo debería programar (en la industria software)

Si buscas «todo el mundo debería de saber programar» vas a encontrar muchas entradas. Hay muchas opiniones a favor de porqué programar es bueno para ti. Adquieres una nueva habilidad, cambia tu forma de pensar, te hace ver las cosas desde otra perspectiva.

En definitiva mucho crecimiento personal, desarrollo mental, etc. pero yo no quiero tratar ese tema. Que saber programar es algo bueno para la mente humana es algo de lo que estoy convencido. Es bueno como es bueno dibujar, leer, escribir, bailar, hacer deporte y aprender otros idiomas. Todas esas cosas son buenas. Y con buenas no quiero decir útiles, quiero decir buenas para el ser humano a nivel mental (algunas a nivel físico también pero eso es otra historia).

Pero no, eso no es lo que quiero tratar aquí. Lo que quiero tratar es muy concreto, y es que en cualquier industria/empresa que haga software (aunque esa no sea su fuente de ingresos) porqué todo el mundo debería programar.

Sí, así es. Si eres desarrollador de software y en tu empresa hay alguien que no programa, debería. Si trabajas en una empresa en la que se desarrolla software (sea o no para uso propio) y tu no programas, deberías.

Si no programas, deberías.

Es algo categórico. Todo el mundo tiene que programar. Programar en una empresa que hace software significa aportar al producto. A estas alturas, el que ha leído hasta este punto estará radicalmente a favor o en contra de este principio fundamental que de forma tan improbable se da en el tejido empresarial de cualquier industria, y ahora voy a matizar los comos y porqués.

Programar es una palabra muy grande.

No hace falta que te descargues todas las herramientas de desarrollo que tengan los ingenieros de tu empresa para empezar a colaborar (de verdad) en el producto que hacéis. No lo ibas a hacer, y no tienes por que hacerlo para colaborar.

La industria software ha crecido tanto (y tanto más va a crecer) que la programación es una parte más del desarrollo software. Por eso no considero correcto llamar hoy en día a los que hacen software «programadores» y si «desarrolladores».

Este neologismo adoptado del inglés tiene sentido en muchas áreas en las que no intervienen solo lenguajes de programación o programación clásica. El hecho de usar la palabra «programador» hace una distinción muy radical entre dos clases de trabajadores: los que programan y los que no. Esto no es bueno para la industria. El software es ahora muy amplio y su desarrollo se debe ampliar a toda la capacidad posible de una organización (que es todos los que colaboran en la empresa).

Un desarrollador es un experto en el area de conocimiento relacionada con la programación en lenguajes y usando herramientas de ese ámbito. Y es bueno que haya expertos que se dediquen a su especialidad, pero eso no implica que no puedan hacer nada más. Por su profesión conocen muchas herramientas software y saben lo que les gusta y lo que no les gusta de las herramientas que hacen. Por eso no se les debe considerar como meras máquinas de hacer software si no también usuarios avanzados de este. Su opinión no es la de cualquiera, es la de alguien que usa mucho software y también lo puede producir. Sabe lo que es fácil de hacer y lo que es muy complejo, y ese conocimiento es muy valioso para la organización.

En el otro lado de la mesa estarían entonces todas aquellas personas que colaboran en una organización pero que no programan con lenguajes de programación y las herramientas del ámbito.

Interfaz

En el desarrollo web una gran parte de la aplicación es la interfaz. La interfaz web es un documento (muy) enriquecido que también permite interactuar al usuario con el. A veces las funcionalidades de interactuación son tantas que se pierde el concepto de documento. Pues bien, estos documentos (paginas web) se componen por lenguajes de marcado y lenguajes de estilo, esto es HTML y CSS. Estos no son lenguajes de programación, pero forman parte del desarrollo de la aplicación.

El arte no son herramientas, pero los artistas no hace solo arte conceptual. Puedes encontrar un equipo de diseñadores (o al menos un diseñador) en la mayoría de empresas que hacen software. Después de diseñarlo hay que implementarlo y ¿es esto menos importante que la funcionalidad que se ofrece detrás de la interfaz? para nada. Puede que haya quien lo valore menos; eso no lo hace menos necesario.

En una conferencia hace ya algún tiempo escuché a un desarrollador comentar que en su empresa el CEO hacía cambios en el la hoja de estilos de la página. Muy probablemente serian nimiedades o pequeños bugs sueltos aquí y allá en partes para nada cruciales del negocio … pero los hacía. Ese era el nivel de implicación en su producto. Exigir sin saber es fácil, aquel hombre colaboraba.

Despliegue

La parte más valiosa del software no es en realidad programarlo. Estuve muchos años convencido de que era así. Mejores funcionalidades y más accesibilidad hacen que la gente abandone un programa por otro. O quizás solo un pequeño matiz entre dos aplicaciones ya hace que dejes una para abrazar la otra. De manera competitiva es muy importante lo que tu software hace y como lo hace, así como que este libre de defectos. Y estos aspectos sí tienen gran importancia, de hecho son lo segundo más importante. Lo que es lo más importante del software es entregarlo. En ingeniería de software esto se llama despliegue.

Si tienes un software genial que tiene todas las funcionalidades necesarias para lo que necesita todo el mundo y no esta accesible para nadie ¿de que sirve?.

Si tienes un software parcialmente terminado, lleno de defectos y hasta feo, pero disponible a todo el mundo, ya tienes producto.

Cuidado aquí, no estoy haciendo apología de hacer malas aplicaciones si no de tener buenos sistemas de despliegue. Hay empresas especializadas en hacer software de despliegue, así que en realidad no te hace falta hacértelo tu mismo solo tienes que configurarlo a tu gusto y esto puede ser a veces complejo dependiendo de tus necesidades. Esto consiste en automatizar tareas, en pasos concretos, y aunque muchas veces sea con herramientas con interfaz gráfico, el fin no deja de ser el mismo.

Calidad

Y una vez entregado se acabó … pues no, hay que testear. Hay tests unitarios, de componente, de sistema, integración. Pueden ser caja negra, caja blanca. Visuales, de rendimiento … en fin, me abruma pensar en catalogar todas las clases de testing de software que existen.

La calidad es algo que diferencia de manera competitiva a un producto, y toda empresa que tenga un plan de negocio a medio plazo sabe que el testing en la industria del software es algo fundamental. Un software sin defectos no te hace ganar dinero per se, un software con defectos te puede hacer perder mucho dinero (o dejar de ganar), y las empresas lo saben y le dedican muchos recursos a ello.

Si el gasto en desarrollo es inversión para ganar dinero, el gasto en calidad es dinero invertido en no perderlo.

Escribir pruebas automáticas es desarrollar software, solo que ese software comprueba que el producto hace lo que debe de hacer. En si eso es programar al más puro estilo, pero eso no es lo único que se hace cuando se desarrollan tests. Los tests hay que definirlos, programarlos, insertarlos en tu flujo de despliegue y actualizarlos si se cambia la funcionalidad del programa. Algunas cosas las hacen los desarrolladores, otras las puede hacer cualquiera. Cualquiera que se precie.

Documentación

La documentación no es solamente tener una web que dice qué hace el producto, el cómo es tanto o más importante. Muchos proyectos han triunfado porque tenían una documentación mucho mejor que los demás. Ahora mismo me viene a la mente jQuery, que aunque ahora es hasta odiado por algunos, fue el numero uno de los frameworks javascript durante mucho tiempo. El motivo, el API estaba escrita para humanos. No tenias que irte al código fuente para ver que hacia y casi cómo lo hacia para entender una función especifica, e incluso tenia varios ejemplos de uso que se adaptaban a la mayoría de las necesidades de los que usaban el producto.

¿Cómo se consigue una documentación así? Estando cerca del código. Si sabes que hace y cómo lo hace tu producto, te será mucho más fácil explicárselo a otro.

Eso está bien para la documentación externa. Para la parte de tu producto software que expones al mundo esta genial pero ¿Y la documentación interna? Aquí se abren dos temas. El primero es que el código debe ser autoexplicativo. En muchos años desarrollado no he visto ningún código completamente autoexplicativo. Es más, no he conocido a nadie que haya visto o conocido a alguien que conozca a alguien que ha visto un código así. Pero hay códigos mejores que otros, y mejorar tu código es cuestión de refactorizarlo, para lo que hay que saber programar.

El segundo tema en cuanto a documentación interna es el análisis de requerimientos. Que es lo que nos pide nuestro stakeholder que haga el producto. Primero hay que recoger información, entender lo que se pide, refinarlo… en general etapas de negociación que hacen humanos con humanos. De esto sale una documentación entendible por humanos también. Y ese es el final. Si la persona que hace este proceso puede también crear test (de la capa de complejidad que considere oportuna) este código de test se podrá usar como documentación viva en el código. Esto también da a la gente que desarrollará el producto una idea de que se pide en el test de aceptación. Más agilidad en las comunicaciones del equipo, más claridad en lo que se pide, producto entregado antes y mejor.

Automatización de tareas

Un script es un conjunto de instrucciones que le dicen al ordenador lo que debe hacer. Esto es lo que haría un usuario paso por paso, pero todo junto en un fichero de texto. Aunque este fichero de texto nunca produzca un programa (compilado) esto no se va muy lejos de lo que es en si un programa en la manera clásica.

Con esta explicación puedes pensar: «Bueno, esto se parece tanto a programar, que es programar». Pues sí, hacer scripts es programar, y es una de las tareas básicas de una lo que los DevOps hacen, pero no la única. DevOps son una especialidad en si misma muy necesaria en la industria software y no me voy a parar a describirla porque daría para varios libros.

La clave aquí es que después de tantos años de industria del software, los mismos problemas le han sucedido a mucha gente que las ha resuelto de forma parecida. Incluso muchas veces las soluciones se han compartido en forma de herramientas de software libre. Los flujos empresariales (salvo excepciones) no son muy distintos unos de otros y se pueden automatizar con herramientas que son por lo general muy configurables.

Aquí estoy abriendo la puerta al simple uso de herramientas de distinta complejidad especializadas según el sector. Se puede argumentar en contra que el uso de software no es programar, y en eso estoy de acuerdo, pero hay mucho software que te permite cofigurarlo con herramientas gráficas.

Existen lenguajes de programación visuales, en las que el programador solo tiene que saber lo que quiere hacer, y arrastra y suelta bloques de instrucciones para realizar su programa.

La mayoría de estos lenguajes tiene una finalidad educativa, sin embargo hay software empresarial que también integra este tipo de interfaces para automatizar tareas repetitivas en flujos empresariales.

La automatización de tareas en si es un concepto muy global y su puesta en practica es especifica de cada herramienta, pero en definitiva buen el conocimiento de las herramientas empresariales por parte de los trabajadores (que no son programadores) es fundamentar, y una de las claves del aumento de productividad de la organización.

Que después de esta perorata no se te ocurre nada aplicable a tu puesto de trabajo, ¿has hecho alguna tarea manual 3 veces o más? pues entonces se puede automatizar, solo necesitas que un experto monte la infraestructura para que tu lo aprendas a hacerlo.

Producto producto producto

Un gran comercial puede vender de todo, chicles, pipas, caramelos y software. Da igual el mercado, su fuerte son las relaciones sociales. No es lo que vende si no el como lo vende y a quien.

No todos los mercados son iguales, y los productos de consumo y la herramientas no tienen la misma finalidad. Tampoco las leyes son las mismas para vender chicles que requieren cumplir legislación alimentaria, que sierras de calar que están sujetas a otras leyes y su mercado funciona de otra manera. Pero ¿porque hace falta que el comercial sepa como esta hecho el producto? es un producto, que lo venda y ya está.

Pero los alimento, bienes de consumo y herramientas en general tienen algo muy importante en común: están hechos por máquinas.

Toda industria necesita trabajadores humanos, incluso cuando se automatizan procesos y se produce más con menos trabajo humano, aun queda una capa en la que no nos fiamos de la maquinas y queremos a una persona que nos diga que todo va viento en popa «de verdad». Pero por mucho que avanza la ciencia informática en el software todavía no es así.

Hasta que skynet tome conciencia de si misma y decida que los humanos somos un peligro, el software va a tener que seguir haciéndose con mano de obra humana, y esto le atribuye unas características muy particulares.

Ante la duda de si los comerciales no tienen motivos para conocer como esta hecho el software yo me hago la pregunta al revés: ¿Porqué un comercial no tiene que saber como hacer software?

Me estremezco solo de pensar en que un comercial va a venderle a un cliente unas características inventadas, que la empresa va a tener que desarrollar a prisas y carreras generando defectos por todas partes.

Conocer tu producto, en la industria de software tiene que pasar por conocer sus interioridades. Saber que hace y que no, que defectos tiene, y cuales se van a resolver pronto y cuales van a tardar mucho en arreglarse. ¿Se puede vender software sin saberlo? Claro que si, se pueden hacer muchas cosas aun siendo ignorante, pero mejor para todos si se conocen.

Como buen comercial tienes que ir un paso más allá de encontrar un defecto en tu producto. Tienes que decirle a los expertos capaces de arreglarlo que falla, cuando falla y si eres capaz de decirles el porqué tendrás su agradecimiento eterno, y eso pasa por estar cerca del código. Tu ayudas a los desarrolladores a hacer su trabajo y ellos te ayudaran a hacer el tuyo. Un producto sin defectos y que asombra en las demos se vende mucho mejor que uno que falla como una escopeta de feria. El valor añadido es clave en esta industria.

Por otro lado las mejoras no solo vienen de la parte de reducir defectos, también de aumentar el valor añadido a bajo coste. Estando cerca del cliente, el comercial conoce los matices del uso de la aplicación. Si un comercial conoce su producto, sabe si algo que aporta mucho valor se puede desarrollar con mucho o poco coste, con lo que puede hacer peticiones de mejora mucho más al detalle acelerando así el proceso de entrega.

El producto software

Programar es bueno para ti y es bueno para tu organización. La especialización en tus tareas no implica no hacer nada más que eso. Hoy en día prácticamente todo requiere una forma de programación.

No hay una única forma colaborar haciendo software y todas deben estar cerca del código fuente, porque eso es lo que es un producto software, pero no solo eso.

Un buen producto software es un código fuente desarrollado, testeado, documentado y entregado de manera ágil, eficiente y frecuente, que permite al publico usarlo de manera rápida y sencilla.

Son unos requerimientos muy altos, pero estoy hablando de un BUEN producto software, por eso hace falta mucha gente trabajando en el, en muchos ámbitos distintos, todos cerca del código. Por eso todo el mundo en una organización debería colaborar para mejorar el producto, todo el mundo debiera aportar en cada fase des su desarrollo, todo el mundo debería programar.

Dos Páginas

Hoy 25 de septiembre, estaba ojeando uno de los periodicos «que mandan» en España. Lo he empezado a leer solo por casualidad o porque simplemente era el periodico que quedaba libre en el bar. He ido ojeando sin mucho orden ni concierto en las secciones de internacional, sucesos, deportes etc. En las únicas páginas que de verdad me he detenido han sido en dos (2). Dos páginas en todo el periodico me han llamado la atencion y me he parado a leerlas … las dos páginas de ciencia.

Dos páginas de ciencia en un periodico dominical de gran tirada. ¿Que pasa en este país? No nos gusta la ciencia, no vende la ciencia. A unos pocos les gusta mucho, a unos muchos les gusta poco. Lo que es destacable es que a la mayoria le da igual, por eso el gobierno de turno recorta en ciencia y a nadie le importa, y los cuatro grandes partidos no presentan en sus porgramas politicos ningun plan relativo a la ciencia (y a nadie le importa mucho mas que lo anterior) (aquí y aquí).

Digo a nadie le importa pero no es verdad. A unos pocos nos importa mucho. Pero eso es tambien un problema, a la mayoria deberia interesarle al menos un poco (en vez de nada).

Estas dos páginas de ciencia eran básicamente dos articulos, el primero más orientado a la inverstigación historica al rededor de la ciencia. Uno de esos que van bien en cualquier momento del año cuando no sabes que poner, porque vale siempre, la historia no caduca. El segundo era una entrevista a un matematico, pero con preguntas tan genericas que se las podrias hacer a un profesor de instituto y este responderia igual de bien. En definitiva eran dos articulos de divulgacion cientifica muy superficial, pero no me estoy quejando, eran interesantes y mejor eso que nada. Pero deberían ser más.

Deberían ser más de dos páginas lo que hubiera en los periodicos normalmente (no ya en el dominical). Pero en el telediario también, en todas partes, más de dos páginas. Así quizas la sociedad estaría más interesada y la politica estaría más pendiente de satisfacer esas ganas de ciencia en la sociedad. Porque la ciencia no es un gasto, es una inversión.

Hace poco leí una frase interesante que era algo así como:

«¿Crees que la educación es cara? prueba como de cara es la ignorancia.»

Pues bien, la ciencia es la educación, tambien la historia y la literatura, no digo que no, pero estas no se encuentran en una crisis tan grande como la que afronta la ciencia desde hace años en España.

Así que si tienes que ver algo con la política, por favor empuja para tener en tu programa algo que mejore la ciencia minimamente. Si tienes alqo que ver con el periodismo, por favor empuja para que en el medio en el que trabajas haya más divulgación cientifica. O si simplemente te interesa la ciencia, por favor haz de tripas corazón y habla con tus amigos y familia de lo buena, necesaria, interesante y hasta divertida es la ciencia.
Esto es más una de las cosas que a veces pienso más que un llamamiento, pero por mi parte es algo que voy a seguir fomentando en mi pequeño circulo.

Unselect KendoUI Treeview (de verdad)

La mayoría de soluciones para deseleccionar un nodo de un árbol de Kendo UI no me han funcionado. O no funcionan, o dejan el widget en un estado ‘bastardo’ que no permite continuar con el funcionamiento esperado.
Desde la docu oficial dan una solución … que lamentablemente no funciona:

//Unselect all nodes
var treeView = $("#treeView").data("kendoTreeView");
treeView.select($());

Al final casi que ha sido más fácil destripar un poco la libraria. Si tienes instanciado un treeview y devuelves la función select esto es lo que obtienes;

/*
* var tree = $("#treeview").data("kendoTreeView");
* console.log(tree.select);
*/
function (n){var i=this,r=i.element;return arguments.length?(n=e(n,r).closest(H),n.length&&(r.find(".k-state-selected").each(function(){var e=i.dataItem(this);e.set("selected",!1),delete e.selected}),i.dataItem(n).set("selected",!0)),t):r.find(".k-state-selected").closest(H)}

El método .select() es un getsetter dependiendo del arguments.length, bueno pues hay que mirar la parte donde si que le pasas parámetros (ya que primero deselecciona antes de volver a seleccionar).

Deseleccionar los elementos de un árbol de kendo

No podiemos solo eliminar la clase ‘.k-state-selected’ porque en Kendo UI siempre hay un dataSource que mantiene al widget.
Hay que recuperar el dataItem y decirle “deseleccionate”, o lo que viene siendo lo mismo .set(“selected”, false)

false a.k.a. !1

$("#treeview").kendoTreeView();

//Unselect
$("button#deselect").click(function(){
  var tree=$("#treeview").data("kendoTreeView");

  $("#treeview")
    .find(".k-state-selected")
    .each(
      function () {
        var e = tree.dataItem(this);
        e.set("selected", !1);
        delete e.selected;
    });
});
[iframe src=»http://jsbin.com/ebejad/3″ width=»400px» height=»300px» ]

Unselect en Kendo UI TreeView
Hay que tener en cuenta que en Kendo UI se suele seguir el patrón MVVM para tener sincronizado la interfaz con los datos que son representados.

LET – variables locales al ámbito de bloque

Let es una de las muchas mejoras previstas para la versión 6 de EcmaScript que la mayoría de navegadores/máquinas virtuales JS no soportan.

No es una aportación sustancial al lenguaje. Principalmente está descrita para alejar a los nuevos programadores de las malas prácticas que el lenguaje ofrece a los noobs.

SpiderMonkey (JS de Firefox) implementa en gran medida esta funcionalidad. A partir de la versión 1.7 de JavaScript podemos usar estas y otras mejoras, pero siempre es necesario indicar que versión de javascript se debe ejecutar.

Esta instrucción nos permite jugar con variables locales. Esto no es novedad en javascript, lo novedoso es que su ámbito local es el bloque de código, no la función.

En mis pruebas he comprobado que Firefox acepta el type del script como texto o aplicación. Este es el type recomendado, pero ambos funcionan.

<script type="text/javascript;version=1.7">...</script>
<script type="application/javascript;version=1.7">...</script>

-Let como Declaración-

En el primer console.log baz no se le ha asignado valor, pero dentro de ese ámbito ha sido reservada ese identificador.

<script type="text/javascript;version=1.7">
function yeah(){
    var foo="aaa";
    {
        console.log(foo, baz);// aaa, undefined
        let baz="zzz";
        console.log(foo, baz);// aaa, zzz
    }
    console.log(foo, baz);// ReferenceError: baz is not defined
}

yeah();
</script>

En el ámbito de la función no existe la variable baz puesto que es local al bloque. Aunque podemos acceder a las variables de este ámbito de función y de bloque, estos no son el mismo. Con la sentencia Let restringimos el acceso de ámbito al bloque. Con la sentencia var solo se restringe a la función.

Redeclaraciones

No están permitidas, así de simple. Este es un punto de rigidez mayor que con Var donde están completamente permitidas.

En el siguiente ejemplo mientras que con foo no tenemos problemas, con let no están permitidas múltiples declaraciones. Sin mostrar por consola ninguna línea anterior se nos devuelve un error de tipos:

TypeError: redeclaration of variable baz

<script type="text/javascript;version=1.7">
function yeah(){
    var foo="aaa";
    var foo="bbb";
    {
        var foo="ccc";
        let baz="zzz";
        console.log(foo, baz);
        let baz="_";//TypeError: redeclaration of variable baz
    }
    console.log(foo, baz);
}

yeah();
</script>

Sucede de la misma manera si declaramos baz en un bloque interior pero con la declaración var, con lo que las dos variables estarían en conflicto.

<script type="text/javascript;version=1.7">
function yeah(){
    var foo="aaa";
    var foo="bbb";
    {
        var foo="ccc";
        let baz="zzz";
        console.log(foo, baz);
        {
            var baz="_";//TypeError: redeclaration of variable baz
        }
    }
    console.log(foo, baz);
}

yeah();
</script>

Sacando el segundo baz a otro bloque ya no encontramos ningún problema en la nueva declaración. Estamos en otro bloque con distinto ámbito de bloque.

<script type="text/javascript;version=1.7">
function yeah(){
    var foo="aaa";
    var foo="bbb";
    {
        var foo="ccc";
        let baz="zzz";
        console.log(foo, baz);// ccc, zzz
    }
    console.log(foo, baz);// ccc, undefined
    let baz="_";
    console.log(foo, baz);// ccc, _
}

yeah();
</script>

Mezclando variables globales, locales y locales al bloque

Veamos el comportamiento a través de bloques y funciones. Modificamos una variable global en la línea 2 de la función:

<script type="text/javascript;version=1.7">
var a="aaa";
function yeah(){
    console.log(a);// aaa
    a="bbb";
    {
        console.log(a);// undefined
        let a="zzz";
        console.log(a);// zzz
    }
    console.log(a);// bbb
}

yeah();
console.log(a);// bbb
</script>

Dentro del bloque la variable ‘a’ global existe, pero también existe otra variable local a la función llamada ‘a’, solo que aun no se le ha asignado ningún valor.

Una vez asignado el string “zzz” se puede mostrar, pero al ser local al bloque no se puede trabajar con ella fuera del bloque.

Es importante tener en cuenta que un bloque viene definido solamente por llaves ( { } ). Aunque ciertas expresiones como if y for puedan tener efecto para sentencia siguiente sin bloque (se puede entender que está dentro de un bloque indirectamente) el caso de Let es estricto en el bloque definido por llaves.

<script type="text/javascript;version=1.7">
if (false) var x = 9; // legal
if (false) let x = 9; // SyntaxError: let declaration not directly within block
</script>

-Let como Expresión-

Una expresión let limita el alcance de la variable declarada a sólo esa expresión.

De esta manera podemos usar let para usar una variable en una sentencia solamente.

var a = 5;
let(a = 6) alert(a); // 6
alert(a); // 5

Claro que como las funciones son instrucciones, podemos utilizar una para ejecutar todo el código que queramos con determinado valor local

<script type="text/javascript;version=1.7">
var a = 5;
let(a = 6) (function(){
    console.log(a);// 6
    a+=100;
    console.log(a);// 106
})();
console.log(a); // 5
</script>

Pero todos los valores declarados con let seguirán siendo locales a esa expresión, sin existir fuera de ella.

<script type="text/javascript;version=1.7">
var a = 5;
let( a = 6, b=2000 )(function(){
    console.log(a);// 6
    a+=100 + b;
    console.log(a);// 2106
})();
console.log(a); // 5
console.log(b); // ReferenceError: b is not defined
</script>

El uso de Let como expresión de esta última manera lleva de forma natural a pensar en usarla como una sentencia más.

-Let como Sentencia-

La sintaxis es muy parecida a la expresión, y tiene precedentes en otras sentencias como for, while, if, … así que en definitiva podemos decir que es una expresión más que genera un ámbito local.

<script type="text/javascript;version=1.7">
var global_a = 10;
var global_b =20
let( a = global_a, b=2000 ){
    console.log(a);// 10
    a+=100 + b;
    console.log(a);// 2110
    global_b = a/2;
};
console.log(global_a); // 10
console.log(global_b); // 1055
console.log(a); // ReferenceError: a is not defined
</script>

así con Let creamos un ámbito en el que existen variables privadas y locales para ese ámbito.

-Let con otras sentencias-

Ya que tenemos una intrucción que declara variables locales al bloque, porqué no combinarla con las que ya existen.

Si declaramos variables con Let en un for en la parte de inicialización obtendremos variables locales al for.

<script type="text/javascript;version=1.7">
for(let i=0; i<5; i++){
    //...
    console.log(i);// 0 1 2 3 4
}
console.log(i); // ReferenceError: i is not defined
</script>

Así i desaparece al acabar el for, que es cuando acaba el bloque de la sentencia.

Lo mismo sucede en el caso de for..in y for..of para el uso de Let.

En conclusion:

Muchas veces la forma de programar en JS es como es porque sólo define ámbito una función. Usando let podemos jugar con los ámbitos de bloque como en otros lenguajes clásicos. Pero esto no le quita a var sus propiedades tradicionales de definicion de variables.

-Problemas con Let-

Redeclaraciones de parámetros

La redeclaración de un parámetro de la función con Let y con var es un tema pendiente. Las redeclaraciónes con var sobreescriben el valor del parámetro, si, pero las redeclaraciones con var están permitidas en cualquier bloque y función tantas veces como se desee. Con let no es igual.

La redeclaracion de un parámetro con var y su posterior uso modifica el objeto arguments en la posición donde aparece la variable.

function fun(a, b, c){

    var b = 1000;
    return arguments;

}
console.log(fun("a1", "b2", "c3")); // ["a1", 1000, "c3"]

Existe una discusión en la comunidad de si debería ser igual con Let en este caso.

function f(a) {

    let a = 42;
    return arguments[0]

}
console.log(f(7));// PROBLEMA -> 42 ¿debería ser 7 o 42?

Los chicos de Mozilla dicen que sí, por eso en su implementación la redeclaración de parámetros funciona igual en let que en var.

Let en primer nivel

Este si que es un bug real de mozilla y es que Let en primer nivel (nivel de función) se comporta como Var. Permite redeclaraciones, cosa que no debería ser posible. En mozilla tienen documentado el bug (https://bugzilla.mozilla.org/show_bug.cgi?id=589199) y está en sus planes de para completar la implementación de ecmascript 6

UnderscoreJS, funciones de delay

Me han parecido muy interesantes que veo necesario comentar. Salidas de underscore js que es una librería que cada vez me está gustando más. Es un conjunto de funcionalidades que se puede decir que «completan» el javascript básico de cualquier navegador.

-Delay-

Retrasar una funcion, wrapping del setTimeout ya existe en javascript. Es muy sencilla, pero solo por abstraer el temporizador se merece una mención.

// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){ return func.apply(null, args); }, wait);
};

-Debounce-

Devuelve una función que mientras parecida a ‘_.delay‘. Si la función se vuelve a ejecutar antes del tiempo indicado la cuenta vuelve a empezar.
Cuántas veces has querido volver a empezar la cuenta atrás para alguna acción que has lanzado. Tiene mucho más sentido si son métodos asociados a eventos del usuario. Un pequeño retraso en algo a veces, como que aparezca/desaparezca info extra cuando se hace hover/blur da muy buena experiencia al usuario (solo es un ejemplo de uso, seguro que hay mil más).

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
    var timeout;
    return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    if (immediate && !timeout) func.apply(context, args);
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
};

Así si ejecutamos:

function x(){
    return "executed";
}
var x_debounced = _.debounce(x, 60*1000);

x_debounced();// 00:00:00
x_debounced();// 00:00:10
x_debounced();// 00:00:21

//el resultado será:
"executed" // 00:01:21

Además la función incluye el parámetro ‘immediate‘. En caso de querer que la ejecución sea anterior al tiempo de espera solo debemos ponerlo a true.
De este modo el tiempo indicado es el tiempo tras la ejecución en el que no podrá volver a ejecutarse la función.

Un ejemplo sería:

function x(){
    return "executed";
}
var x_debounced = _.debounce(x, 60*1000, true);

x_debounced();// 00:00:00 : "executed"
x_debounced();// 00:00:10
x_debounced();// 00:00:21
x_debounced();// 00:00:46
x_debounced();// 00:01:47 : "executed"

//bloqueado hasta 00:02:47

-Throttle-

Devuelve una función que sólo se puede ejecutar una vez en un periodo de tiempo. Es similar al concepto de semáforos con un recurso, solo que el recurso es la propia función.

Internamente usa ‘_.debounce‘ para liberar la ejecución.

Mantiene un control de si se ha vuelto a ejecutar la función durante el periodo de bloqueo para ejecutarla de nuevo al final.

// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time.
_.throttle = function(func, wait) {
    var context, args, timeout, throttling, more, result;
    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
    return function() {
        context = this; args = arguments;
        var later = function() {
            timeout = null;
            if (more) func.apply(context, args);
            whenDone();
        };
        if (!timeout) timeout = setTimeout(later, wait);
        if (throttling) {
            more = true;
        } else {
            result = func.apply(context, args);
        }
        whenDone();
        throttling = true;
        return result;
    };
};

Del mismo modo, si ejecutamos:

var x_throttled = _.throttle(x, 60*1000);
x_throttled();// 00:00:00 “executed”
x_throttled();// 00:00:10
x_throttled();// 00:00:21

// 00:01:00"executed"

Ante un uso masivo de la función nos aseguramos que solo se ejecutará realmente en los periodos indicados.

Para tu toolkit

Podemos incluir las funciones entre los métodos de Function, así como en su prototipo, para que cualquier función herede este método y podamos generar funciones delay, debounce y throttle en modo inline.

Hacer esto es tan sencillo como:

Function.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){ return func.apply(null, args); }, wait);
};
Function.prototype.delay = function(wait) { return Function.delay(this,wait); };

Function.debounce = function(func, wait, immediate) {
    var timeout;
    return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    if (immediate && !timeout) func.apply(context, args);
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
};
Function.prototype.debounce = function(wait, immediate){ return Function.debounce(this,wait,immediate); };

Function.throttle = function(func, wait) {
    var context, args, timeout, throttling, more, result;
    var whenDone = Function.debounce(function(){ more = throttling = false; }, wait);
    return function() {
        context = this; args = arguments;
        var later = function() {
            timeout = null;
            if (more) func.apply(context, args);
            whenDone();
        };
        if (!timeout) timeout = setTimeout(later, wait);
        if (throttling) {
            more = true;
        } else {
            result = func.apply(context, args);
        }
            whenDone();
            throttling = true;
            return result;
    };
};
Function.prototype.throttle = function(wait) { return Function.throttle(this,wait); };

Fuciones publicas vs privilegiadas

Hace tiempo que encontré este texto de Douglas Crockford sobre las funciones privadas en JavaScript. En el explica como crear funciones privadas de un objeto. Estas son declaradas en el constructor pero no se le asignan al objeto this. De esta manera solo las funciones dentro del mismo ámbito (el del constructor) tienen el privilegio de acceder a ellas.

function myKlass(){
   var privateValue=0;
   function privateFunction(){
      return ++privateValue;
   }
   //Esta funcion tiene el privilegio de acceder a privateFunction
   this.pivileged=function(){
      return "Ejecución nº "+ privateFunction();
   }
}
var obj = new myKlass();
obj.pivileged();//Ejeción nº 1
obj.pivileged();//Ejeción nº 2
obj.pivileged();//Ejeción nº 3

Si extendemos el prototipo de la función myKlass podemos obtener una clase más rica, con muchas más funciones publicas que estarán en todos los objetos creados con la sentencia new.
Hasta aquí nada nuevo, porque esto es posible en javascript ya desde hace mucho. Pero el diferenciar entre Publica y Privilegiada es algo que no me acaba de gustar.

Toda función puede tener ciertos privilegios.

Las funciones creadas dentro del constructor tienen acceso a todas las funciones dentro del mismo ámbito. Sí, esto es un privilegio, pero estas funciones no tienen acceso a, por ejemplo, terceras funciones internas a otra funcion privilegiada (o publica).
Así que en realidad solo tiene privilegio a un ámbito, que casualmente es el del constructor. Es muy sencillo crear otro ábito y declarar alli una gran cantidad de funciones privadas y asignarselas al prototipo. En este nuevo ámbito podriamos tener otras funciones privilegiadas que solo tuviesen acceso a este ámbito. Veamoslo:

myKlass.prototype.otherPrivileged=(function(){
   var otherVariable=0;
   function otherExecution(){
      return otherVariable+=100;
   }
   return function(){
      return "Aqui vamos a "+otherExecution();
   }
})();
obj.otherPrivileged();//Aqui vamos a 100
obj.otherPrivileged();//Aqui vamos a 200

Aqí tenemos una función que también tiene ciertos privilegios. No tiene acceso a privateValue o a privateFunction, pero solo ella tiene acceso a otherVariable y otherExecution.

Para una función está muy bien. Pero ¿y si queremos un grupo de funciones ‘privilegiadas’?. Pues nuestro ámbito de privilegios debe devolver no una sola función, sino un objeto con las funciones que deseemos y extender el prototipo de nuestra ya muy nutrida clase con ellos.

var superFunctions=(function(){
   var v1=0,v2=2000,v3=775;//...
   function fprivate1(){/*...*/}
   function fprivate2(){/*...*/}
   function fprivate3(){/*...*/}

   function fpublic1(){/*...*/}
   function fpublic2(){/*...*/}
   function fpublic3(){/*...*/}
   return {
      fpublic1: fpublic1,
      fpublic2: fpublic2,
      x: fpublic3
   }
})();

for(fun in superFunctions){
    myKlass.prototype[fun]=superFunctions[fun];
}

new myKlass();
/* Cuidado con los nombres de las funciones, serán los del objeto devuelto
x	fpublic3()
fpublic1	fpublic1()
fpublic2	fpublic2()
otherPrivileged	function()
pivileged	function()
*/

Con una funcion para extender prototypos de funciones se habría quedado un código más legible, pero en definitiva esto es lo que se debe hacer.

Sea como sea, podemos hacer que cualquier función publica sea en cierta medida privilegiada. Por eso prefiero no hacer distinción entre las funciones de un objeto. Cada una puede implementar su funcionalidad con acceso a otros métodos o no, eso no importa.

Más pixels aleatorios, esta vez con Canvas

Hace tiempo escribí un post acerca de los pixels aleatorios. Dibujaba una imagen en java para probar que no ser repetían patrones en la funcion random. Para hacer lo propio en javascript ahora gracias al html5 podemos usar la etiqueta canvas y pintar dentro de ella. Nos declaramos un canvas del tamaño que queramos, por ejemplo de 300 x 300

<canvas height="300" width="300" id="mycanvas"></canvas>

Antes de dibujar en nuestro lienzo tenemos que usar el contexto, en este caso en 2d.

Para dibujar pixel a pixel solo tienes que dibujar cuadrados de un pixel de tamaño. Empezamos por la cordenada (0,0) hasta la (299,299). En realidad puedes dibujar fuera del canvas, pero por supuesto no esperes que se vea.

function drawRandom(id){
	var canvas = document.getElementById(id);
	var ctx = canvas.getContext('2d');

	for(var j=0;j<300; j++){
		for(var i=0;i<300; i++){
			ctx.fillStyle = getRandColor();
			ctx.fillRect(i, j,i+1, j+1);
		}
	}
}

function getRandColor(){
	//Si quieres puedes usar solo blanco y negro para verlo más claro
	//var blanco="rgb(255,255,255)";
	//var negro="rgb(0,0,0)";
	return ("rgb("+(parseInt( (Math.random()*1000) % 256))+","
		+(parseInt( (Math.random()*1000) % 256))+","
		+(parseInt( (Math.random()*1000) % 256))+")");
}

drawRandom("mycanvas");

Puede que tarde un rato, o incluso que el navegador piense que tienes un bucle infinito en ejecución. Después te pintará una imagen tan «bonita» como esta:

canvas con pixels de colores aleatorios
canvas con pixels de colores aleatorios

Para este ejemplo sencillo vemos que la funcion Math.random( ) se comporta bastante bien en cuanto al grado de aleatoriedad. Pero si quieres profundizar en hacer dibujos con canvas puedes ver más cosas aquí. Si ya lo has hecho en otros lenguajes (no como yo) no te resultará complicado hacerlo en javascript.

Visión general de un SQLInjection

Me ha parecido muy completa esta presentación de SQL injection. Toca un poco de Doctrine y Propel para dar ejemplos de buenas practicas.
Da un dato interesante, entre el 40-60% de los casos de acceso a datos no autorizados son por fallos de injecciones de SQL en el código de una web. Un error muy común por lo visto.
Las transparencias son de Krzysztof Kotowicz un experto en seguridad en e-comerce y web 2.0. Solo echarle un ojo a su blog ya es algo muy recomendable apara estar al día en seguridad para la web.