Kata de las gasolineras

Paso a publicar la Kata que los candidatos a .NET Developer de thinkandcloud deben superar:

Estás viajando con tu coche desde un punto A hasta un punto B por un bonito plano finito de 1000x1000.
En ese plano finito hay 10 gasolineras repartidas aleatoriamente con una distancia mínima entre ellas de 5.
De repente te quedas sin gasolina. Lo bueno es que sabes dónde estás y dónde están las gasolineras.

¿Cuál es la gasolinera más cercana?

Resumen de las normas:
- Ubicar aleatoriamente las 10 gasolineras en el plano, con una distancia mínima entre ellas de 5.
- Ubicar aleatoriamente el punto A y el punto B en el plano, con una distancia mínima de 200.
- El coche viaja en línea recta entre A y B. Se nos acaba la gasolina en un punto aletario de esa línea.

¿Qué se valora?
- Más que la solución se valora cómo nos enfrentamos al problema.
- Uso de TDD.
- Ante cualquier duda del enunciado, tomar decisiones valientes.
- Organización.
- Simplicidad.
- Fácil lectura de código.




Enviar emails usando plantillas con sintaxis Razor

Para ser sincero, desde siempre el envío de emails ha sido una de las cosas que más he odiado del mundo de la programación No sé por qué... quizás porque siempre me fallaba algo, usar plantillas/templates era demasiado trabajoso...

Hasta ahora lo solucionaba usando NVelocity para rellenar los templates y el IIS para enviarlos... y creedme que los templates para el NVelocity eran un complejo XML difícil de tratar y con versiones para HTML y texto plano con duplicación de textos... un infierno de mantenimiento.

Así que ante un nuevo proyecto que requiere envío de emails he hecho lo que en principio parece más difícil, aunque realmente es lo más fácil: hacerle caso a Punset, desaprender.

Así que me puse a buscar librerías que me solucionaran el problema. Las premisas que me marqué son las siguientes:
- Plantillas con sintaxis Razor
- Sin dependencias con MVC
- Que la solución esté en nuget
- Extremadamente fácil de usar

El objetivo de este artículo no es sino ahorraros tiempo. He probado más de 6 librerías y definitivamente me quedo con FluentEmail (nuget / github) de lukencode.

Su uso es muy sencillo... y encima es Fluent:

Email
   .FromDefault()
   .To("email@destino.com")
   .Subject("Asunto del email")
   .UsingTemplateFromFile(Server.MapPath("~/MailTemplates/Template.cshtml"), model)
   .Send();

- FromDefault: coge los parámetros por defecto del MailSettings del web.config.
- To: los destinos a quienes va el email. Puede ser un string un listado de strings. También tenemos los métodos BB y BCC
- Subject: el asunto, surprise!
- UsingTemplateFromFile: apuntamos a un fichero .cshtml, la típica view de Razor, vamos. También tenemos la propiedad UsingTemplate, donde en lugar de la url a un fichero le damos directamente el texto.
- Send: envía el email, y SendAsync lo hace de forma asíncrona.

¿En algún momento he dicho Razor? ¡Nooop!
Con la propiedad UsingTemplateEngine podemos elegir el motor de templates que queremos usar... vale, y por defecto es Razor :D


¿Y quién hace el envío?, ¿El IIS?
Pues podríamos, sin problemas... pero personalmente me he enamorado de sendgrid. No hay más que crearse una cuenta (si lo haces desde azure tiene algunos miles de emails gratis al mes) y configurar tu web.config con algo como esto:

<system.net>
  <mailSettings>
    <smtp from="email@origen.com">
      <network host="smtp.sendgrid.net" password="sendgridpassword" userName="sendgriusername" port="587" />
    </smtp>
  </mailSettings>
</system.net>



¿Qué más me cuentas?
Lo primero es que FluentEmail no está preparado para trabajar con IoC y poder testear... pero vamos, problemas cero. Lo metemos nosotros en un servicio, le sacamos una bonita interfaz y ale, a fakear y/o mokear al gusto.

Lo segundo es que, personalmente, odio los magic strings a niveles enfermizos. Vamos, que poner "~/MailTemplates/Template.cshtml" me mata. Por eso aprovecho el T4MVC (nuget / codeplex) para acabar poniendo MailTemplates._AboutYourProject2TaC_cshtml

El único detalle es que los mailtemplates los pongo dentro del directorio "MailTemplates", y añado "<FileFolder>MailTemplates</FileFolder>" al elemento StaticFilesFolder del T4MVC.tt.settings.xml

Para los que hayáis trabajado con T4MVC sabréis que esto último solo sirve si la carpeta "MailTemplates" está en el mismo proyecto que el T4MVC. Si no es así y sacáis los templates a otro proyecto (y por tanto lo hacéis como debe ser), tendréis que inventaros algo rollo usar enums para diferenciar templates.



Mis chrome extensions: traductor y otras más

Veo con tristeza que llevo mucho tiempo sin escribir en serio en este blog. Supongo que puedo poner mil excusas, pero aunque algunas sean ciertas, lo bien claro es que ninguna es lo suficientemente buena.

A veces me cuesta distinguir entre mi hobby y mi trabajo, porque prácticamente son lo mismo. Lo bueno es que trabajar en tu hobby es la leche. Lo malo es que decidir cambiar de hobby es algo dramático. Pero que no cunda el pánico, de momento mi hobby sigue igual.

La última "ramificación" de mi hobby ha sido la de hacer Chrome extensions. Empiezan a ocurrírseme y no puedo parar. A día de hoy he publicado 4 extensiones de Chrome propias y otra en Avanzis (de momento en fase de test).


Subgurim Translator
De todas esas extensiones, hay una en la que he invertido un poco más de tiempo e interés. La he llamado "Subgurim translator" y he procurado que fuera una herramienta de traducción tan potente como me ha sido posible. Si usais chrome y os es relativamente frecuente traducir, no puedo dejar de recomendárosla. Básicamente he cogido todo lo que hacían otras extensiones, lo he procurado mejorar y he añadido cosas nuevas que ninguna tenía.

Algunas de sus características:
  • Traducción instanténea.
  • Detecta el lenguage de tu navegador y lo guarda.
  • Si cambias el lenguaje origen o el lenguaje destino te los guarda para que no tengas que volver a seleccionarlos. Esto es así porque la mayor parte de las veces solemos traducir siempre entre los mismos idiomas.
  • Si no tienes claro cuál es el lenguaje origen, el botón de "detectar idioma" está muy a mano.
  • Una de las cosas que más me gusta: si eliges un texto en la página en la que estás y haces clic sobre la extensión, ésta te traduce el texto de inmediato. De hecho no importa ni si conoces el texto que has seleccionado. Lamentablemente, por cuestiones de seguridad de javascript, en las páginas HTTPS esta funcionalidad no está activada.
  • Una vez está el texto traducido, copiarlo al portapapeles es un único clic.
  • Por defecto está activada la opción de si se te cierra la extensión puedas mantener el texto original en el que estabas trabajando.
  • Por supuesto tienes un botón para traducir la página entera en un nuevo tab.
Os dejo un vídeo para que le echéis un vistazo.



Enlace del subgurim translator: https://chrome.google.com/webstore/detail/cdalmddifklficcbjgppcibjglmpbjjm

Lo que más me gusta de esta extensión es la arquitectura javascript que le he aplicado. Me encanta como lo he hecho. Es el código javascript más limpio que he hecho nunca.


Otras extensiones
Antes del Subgurim translator he estado trabajando en otras tres extensiones.

Una de ellas es poco útil se trata del Duplicate Tab, que te duplica el tab actual en un único clic. Algo que, como sabéis, se puede hacer clicando con el botón central sobre "recargar" o haciendo botón de la derecha --> duplicar al tab en cuestión... pero yo lo hice porque me apetecía... y para probar mi velocidad de creación de extensiones, jejeje. La verdad no me costó más de un cuarto de hora desde que se me ocurrió hasta que lo publiqué con vídeo incluído.

Las otras dos extensiones son "tab back" y "tab foward". Éstas si me gustan más y son bastante más útiles. Internamente guardan el historial de las pestañas/tabs que vas activando, de forma que navegar sobre ellas es muy fácil. A mí me pasa muchas veces que tengo un montón de pestañas abiertas, voy abriendo una y otra y en un momento dado quiero volver a la anterior pero no sé ni dónde está... pues con estas extensiones se resuelve. Por cierto, la segunda (la tab foward) es inútil por si misma (requiere la tab back). Y de paso aprendí cómo comunicarme entre extensiones.


¿Cómo aprender a hacer extensiones?
Pues la premisa es tener un conocimiento javascript ágil. Una extensión al final no es más que páginas html sobre las que realizas acciones javascript usando la API/librería que Chrome te ofrece. Es un resumen un poco malo, pero es poco más que eso: javascript + html.

Podría dar más explicaciones, pero es que el tutorial de la api es sencillo, breve y directo.



Html5, primeras pinceladas

HTML5 está al caer, y nos tendremos que adaptar sí o sí.

Llevo varios días investigando y la verdad es que en líneas generales me gusta bastante. Aún no voy a escribir artículos al respecto hasta que no lo pruebe bien probado, pero para empezar os adjunto interesantes enlaces.

Javier Casares tiene varios artículos sobre HTML5 muy interesantes. Estos son los que considero más interesantes:
- Enlaces que cobran vida.
- Cómo estructurar una página.
- Los bloques de contenido textual.

El propio blog de Javier Casares es un buen caso de uso de HTML5, así como uno de sus proyectos: tumanitas.com

En todo caso, y como siempre, ante la duda... w3c.



Sobre mi nuevo proyecto

Como ya os he comentado alguna vez, a parte de mis 8 horas diarias en Avanzis mi tiempo libre lo dedico casi exclusivamente a mis propias Webs, lo que acaban siendo otras 20 o 25 horas semanales.

Hasta hace dos años dedicaba ese tiempo a webs sin demasiada intención comercial, hacía simplemente lo que me daba la gana sin preocuparme por el retorno. Me valía con dar rienda suelta a mi "creatividad".

Pero hace dos años decidí iniciar un proyecto "serio"... y así ha sido. Sin duda el proyecto más grande y serio que he hecho hasta ahora, tanto a nivel técnico como por su fin comercial.

La web/producto en cuestión se enfoca a un mercado que existe y creo que está mal cubierto, y la forma de monetización es directamente la de acceso premium. No llega a ser freemium porque los usuarios no-premium sólo tienen el rol de "ver-pero-no-actuar". Es más, sólo se ven entre ellos, no a los usuarios premium.

Pero me dejo de ideas abstractas, concretemos.

La web es trickeo.com, y podría definirse como una red social de gente que quiere hacer tríos y/o intercambios de pareja. De hecho su lema es tan explícito como elegante "¿Trío o intercambio? Tú eliges".

A la hora de registrarte hay dos tipos de usuarios, la persona que va "sola" y cuya intención es hacer tríos; y la pareja, cuya intención es hacer tríos y/o intercambios.

Existen varias webs de contactos que podrían tener cierta similitud, pero trickeo trata de diferenciarse en varios aspectos:


Se dirige única y exclusivamente a tríos e intercambios.
Toda la web gira entorno a ello. Existe la figura del "pretrickeo" que viene a ser algo así como "dos personas que se ponen en contacto para buscar una tercera para hacer un trío". Obviamente en ningún caso se impide que esas dos personas queden antes para "probar".

Está dirigido a usuarios premium.
Dicho de otra forma, sólo entra el que está interesado de verdad. Nada de trolls ni spammers. El que está interesado paga una pequeña subscripción (que varía de 10 a 70 euros según la duración de la suscripción).
Evidentemente, al principio no hay una base suficiente de usuarios, con lo que de buenas a primeras no puedes exigir un pago, pero cuando lleguemos a un base de usuarios respetable (500~1000) aplicaremos ese método.
Este método exige la existencia del usuario no-premium. Éste podrá navegar por la web y conocerla (sólo a otros usuarios no-premium) pero a la hora de ponerse en contacto con alguien deberá hacerse premium.

Diseño serio y elegante.
Trickeo quiere dar la sensación de ser una página respetable respecto a las otras alternativas. Ni si quiera tenemos publicidad (no la necesitamos dado nuestra forma de monetizar).
Tampoco permitimos fotos eminentemente pornográficas. Es muy difícil trazar la línea de separación, pero queremos que queden como mucho en eróticas.

Absoluta privacidad.
Hay diferentes niveles de privacidad, el mínimo permite que cualquier usuario registrado pueda verte, y el máximo es un modo de invisibilidad total.
Por defecto al usuario premium sólo lo podrá ver otro usuario premium, y el usuario no premium sólo podrá ver a usuarios no premium y ser visto por otros usuarios premium.

Máxima usabilidad
Está pensado para que usuarios de nivel bajo tengan que hacer apenas dos o tres clics para empezar a "trickear", mientras que los usuarios de nivel medio o avanzado podrán disfrutar de un montón de herramientas y mucha navegación interesante.
Resumiendo mucho, trickeo te pregunta por tus gustos sexuales (sexo, orientación sexual, qué tipos de trío o intercambio buscas...) y automáticamente te muestra los usuarios con los que eres perfecto candidato, así como eres mostrado a otros.
A partir de ahí puedes refinar las búsquedas tanto como quieras.
En todo caso tienes la opción de ver a los demás usuarios, su ficha, sus fotos, etc. y si lo crees conveniente ponerte en contacto con ellos.
Todo esto con muy poquitos clics y procurando centrarse mucho en la facilidad.


Podría estar describiendo el funcionamiento mucho más, pero casi mejor si lo probáis vosotros mismo. Os adjunto un código con el que podréis probar trickeo.com en modo premium durante tres meses... y si os gusta ya sabéis ;)

Web: www.trickeo.com
Código de invitación: 459TESS

Ya os iré contando qué tal va, qué decisiones tomamos, nuestro marketing, etc.

Quería acabar dando las gracias a los que han hecho posible la existencia de trickeo.com, desde los que simplemente se ilusionaron y aportaron ideas, hasta el actual equipo trickeo, pasando por aquellos que formaron parte del equipo y ya no están. De verdad: gracias.



Plugin de jQuery: mejora del datepicker

Últimamente le estoy dando mucha caña a jQuery

jQuery no es más que una capa por encima a javascript, además de una forma de establecer unas convenciones de uso. Esto último permite un buen ecosistema de plugins que a su vez redunda en hacer jQuery más estandarizado.

Pero vamos al grano: he estado trabajando en el plugin de jquery UI: Datepicker. Es bastante completito. Yo lo estoy usando de modo que haciendo click sobre un textbox aparezca un calendario.

Éste actualiza el textbox con la fecha en la que te encuentras, pero sólo al hacer click en el día elegido. El problema es que cuando cambias de mes o de año, no actualiza el textbox, con lo que se está comportando de forma extraña... por lo menos diferente a como se comportan otros calendarios como el propio de Windows.

Pero con un pequeño truquito tiene solución fácil, gracias al evento onChangeMonthYear.

El código es éste:

$(".Calendar").datepicker({
        onChangeMonthYear: function(year, month, inst) {
                $(this).val($.datepicker._formatDate(inst, inst.currentDay, month-1, year));
        }
});


Espero que os sea útil ;)



jQuery, Ajax y ASP.NET WebForms

Admito que al principio era reticente a usar jQuery. Al fin y al cabo, todo lo que hace jQuery se puede hacer con javascript, y no lo veía más que como otro framework javascript más.

Sin embargo, conforme he ido utilizándola por necesidades de nuestro nuevo proyecto en Avanzis, más me ha ido gustando... y ahora me es prácticamente imprescindible :D

De la funcionalidad que quería hablar es sobre cómo se trabaja con Ajax en jQuery, y su aplicación para ASP.NET Webforms (con ASP.NET MVC es algo más fácil).

En la página oficial de jQuery encontramos una muy buena documentación de su uso con Ajax. Personalmente el método que más uso es el de getJSON.

Vayamos directamente al ejemplo. Bien sencillo: tenemos un TextBox y un Button. En el texto escribiremos un entero, y al presionar sobre el botón se ejecutará una función jQuery/Ajax que enviará el dato a servidor. En el servidor procesaremos el dato y devolveremos un resultado que nuestro javascript procesará. Vamos una ida-y-vuelta al navegador usando Ajax.

Nuestro HTML:
        <input type="text" id="box" />
        <input type="button" id="button" />

Nuestro javascript:
    $(document).ready(function() {
        $('#button').click(function() {
            var idValue = $('#box').val();
            if (idValue && (idValue != '')) {
                sendData(idValue);
            }
        });
    });

    function sendData(idValue) {
        var actionData = { id: idValue };
        $.getJSON('/test/ajaxtest.aspx', actionData, function(data) {
            if (data == true) {
                alert('par');
            }
            else if (data == false) {
                alert('impar');
            }
        });
    };

Nuestro código en servidor:
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(Request.QueryString["id"]))
            {
                int id = Convert.ToInt32(Request.QueryString["id"]);

                if (id%2 == 0)
                    returnJSON(true);

                returnJSON(false);
            }
        }

        protected void returnJSON(object data)
        {
            if (data.GetType() == typeof(bool))
                data = data.ToString().ToLower();


            Response.Clear();
            Response.ContentType = "application/json";
            Response.Flush();
            Response.Write(data);
            Response.End();
        }


Como vemos, en nuestro código javascript lo primero que hacemos es decirle al navegador que en el momento esté preparado ("ready") coja el elemento con el identificador "button" y le asigne una función a su evento "click".

Dicha función lo único que hace es coger el valor del elemento con identificador "box", y si este valor es válido se ejecuta la funcion "sendData". La función "sendData" es la importante... y para ser importante es bien sencillita :D

Lo primero que hacemos es crear el elemento JSON, que será el dato que mandaremos a servidor.

Luego ejecutamos la función getJSON. Ésta se compone de tres parámetros. El primero es la URL a la que apuntamos. En nuestro caso ponemos un página .aspx normal y corriente. También podríamos crearnos un HttpHandler que gestionara todas las llamadas AJAX, o si estuvieramos usando ASP.NET MVC no tendríamos más que poner la ruta correspondiente.

El segundo parámetro es la variable json con los datos que enviaremos a servidor. Y el tercer parámetro es la función que se ejecutará cuando vuelva de servidor y que luego analizaremos. Lo importante de esta función es que el dato que devuelven ya está en JSON, con lo que es muy fácil trabajar con él.

En cuanto al código de servidor, también es muy sencillo. Lo único que hace es recoger el dato que hemos enviado (y que en este caso se recibe como querystring), tratarlo y devolver una respuesta.

El quid de la cuestión está en que la respuesta debe ser un JSON, de lo cual se encarga el método "returnJSON". En nuestro ejemplo sólo devolvemos true o false, pero si creamos una variable JSON cualquiera igual nos vale (por ejemplo "{text:'texto de respuesta'}").

Y volviendo a la función javascript, vemos que tratar con JSON es muy sencillo. En nuestro caso sólo tratamos el "true" o el "false". Para mí es muy común trabajar sólo con eso, puesto que lo normal es mandar un dato a servidor, realizar una acción y devolver un booleano como diciendo "todo correcto" o "ups, ha habido un error".

Fácil, ¿no?



Mi blog personal

Hace tiempo que le tenía ganas, y por fin me ha lanzado.

Ya tengo blog personal como Javier Navarro. (http://www.javiernavarro.net/). No sé si es un error, porque Subgurim.net está muy bien posicionado y me lee bastante gente. Comenzar con JavierNavarro.net desde cero es algo atrevido... pero qué narices, lo hago porque quiero y no espero apenas visitas.

Lo separo porque en este blog quiero seguir hablando en exclusiva de ASP.NET, Javascript, C#, Bases de datos, etc, y en mi blog personal hablaré de más o menos lo que me venga en gana, desde cosas personales hasta, sobretodo, temas del mundo de los emprendedores, la tecnología e Internet.

Ya sabéis, estáis todos invitados a mi blog: Javier Navarro.

PD: Si me considero un SEO mínimamente razonable, tengo que salir primero en Google como "Javier Navarro".