Etiquetas: , , , , , ,

Mejorando la consola de Windows con ConEmu y PowerShell

0 comentarios

El otro día empecé lo que va a ser una serie de artículos sobre MongoDB. Aunque la intención es explicar como trabajar con .NET en MongoDB, la primera tanda de artículos estará relacionada directamente con el gestor de base de datos y su uso desde la consola. Y cómo la consola de Windows es un poco "ligth", vamos a ver como dotarla de funcionalidades extra.

Si habéis utilizado algún sistema Linux en alguna ocasión, os habréis dado cuenta que la consola es una gran herramienta que permite  realizar muchas tareas de forma rápida y flexible. Aunque la consola asusta mucha gente, usada con sabiduría puede hacernos ser mucho más eficientes, e incluso, sacarnos de algún lío. Podemos abrir pestañas, editores de texto y ejecutar multitud de comandos y scripts, para interactuar con el sistema operativo.

Como la consola de Windows de toda la vida (CMD) aporta pocas opciones, Microsoft lanzó con Windows Vista una versión avanzada, conocida como PowerShell. Esta nueva consola nos permite lanzar comandos al sistema operativo, como hacía la antigua consola, pero además nos permite conectar con SLQ Server o IIS. La intención de este artículo no es profundizar en los comandos de PowerShell, pero bastará con ejecutar un "help about" en la misma consola de PowerShell para descubrir mucha información sobre la misma. En definitiva, con PowerShell tenemos una herramienta similar a las shell existentes en Linux.


Ampliar las opciones de la consola


Ahora que nos hemos decidido por usar PowerShell, nos encontramos con el problema de que más allá de las funcionalidades que ofrece, el entorno no es del todo amigable. Para solucionarlo vamos hacer uso de Conemu, que nos permite usar la consola tradicional de Windows o PowerShell, pero añadiendo un montón de opciones interesantes.

Instalarlo es tan fácil como instalar cualquier programa de Windows, y nada más abrirlo ya vemos las diferencias. Tenemos opción de abrir muchas pestañas (algo que nos será muy útil con MongoDB), configurar el color del fondo, del texto, la fuente, que la ventana sea semitransparente ...  Pero nada más abrir, vemos un problema: se nos abre la consola normal de Windows y no PowerShell. Afortunadamente arreglarlo es muy sencillo y basta con agregar los siguiente parámetros al arranque del programa: 

"C:\Program Files\ConEmu\ConEmu64.exe" /config "shell" 
/dir "c:\" /cmd powershell -new_console:n

De todas formas si queremos abrir una consola normal, podremos hacerlo en cualquier momento si al abrir insertamos:

C:\Windows\System32\cmd.exe

Añadir Notepad++ para editar texto


Pues ya tenemos consola con opciones avanzadas, que arranca PowerShell ¿qué nos falta? Personalmente lo primero que he echado de menos es un editor de texto. Sí, podemos editar archivos de texto con notepad, pero no es precisamente la mejor manera de crear y editar scripts. 

Personalmente un editor que utilizo bastante para estos temas y que tiene un gran número de opciones es Notepad++. Este editor nos permite resaltar la sintaxis de muchísimos lenguajes (SQL, C#, JavasScript, Java ...), comparar archivos y además tiene un sistema de plugins para añadir funcionalidades extra. Muy recomendable. Para poder utilizarlo basta con descargarlo e instalarlo. No requiere de ninguna configuración especial, así que ponerlo a funcionar, es muy sencillo.

Una vez instalado, si abrimos una consola PowerShell desde ConEmu y ejecutamos Notepad++, se nos mostrará un error diciendo que no se encuentra el comando. Podemos solucionar esto añadiendo la ruta de instalación de Notepad++ a las variables de entorno, pero vamos a hacerlo de una manera más elegante. Utilizaremos los alias.  Una alias no es más que una manera distinta de llamar a un comando o programa, de manera que cuando introduzcamos el alias en la consola Powershell se realice la acción deseada.

Para añadir un nuevo alias debemos hacerlo en un perfil, así que vamos a ello. Para ver la ruta dónde está nuestro perfil, basta con ejecutar el comando

$profile

Esto nos indica dónde está nuestro perfil, pero es posible que la ruta no exista. Cosa que podemos comprobar con el comando

test-path $profile

Este comando devuelve true si el archivo existe o false si no existe. En cualquier caso ahora vamos a abrir el perfil con el comando

notepad $profile

Lo abrimos con Notepad, porque aun no tenemos ningún otro editor configurado. Si el archivo no existe PowerShell nos preguntará si queremos crearlo. Le diremos que sí y añadiremos las siguientes líneas:

$NOTEPADPLUS = "C:\Program Files (x86)\Notepad++\notepad++.exe"
Set-Alias notepadp $NOTEPADPLUS

Las líneas son bastante sencillas. Estamos declarando una variable $NOTEPADPLUS con la ruta al ejecutable de Notepad++. Luego creamos un alias con Set-Alias y elegimos que se abra la ruta con el comando notepadp. Yo he puesto notepadp, pero podéis poner lo que mejor os parezca (editor,notepad++ o chorizo).

Ahora si guardamos los cambios del archivo creado, cerramos y volvemos a abrir ConEmu, nos aparecerá un error diciendo que la ejecución de scripts no está permitida. Esto es porque al arrancar la consola se trata de ejecutar el script que hemos creado antes y que carga los valores del perfil, pero por seguridad, no pueden ejecutarse scripts que no estén firmados. La seguridad siempre es buena, pero en este caso el script lo hemos creado nosotros, así que deberíamos poder ejecutarlo. Si ejecutamos: 

Get-Help About_Signing

Obtendremos mucha información sobre la firma de scripts. Nosotros en este caso ejecutaremos simplemente el comando:

Set-ExecutionPolicy RemoteSigned

Que nos permitirá ejecutar scripts creados localmente. Una vez hecho esto, cerramos y abrimos ConEmu, y veremos que el error ya no aparece. Y ahora si ejecutamos el alias se nos abrirá Notepad++ e incluso nos creará el archivo si se lo pasamos el nombre como parámetro:

notepadp test.sql


Añadir nano para tener un editor de texto interno


Notepad++ está muy bien, pero a veces simplemente queremos editar archivos de forma rápida y sencilla. Es un poco molesto que se abra una nueva ventana para editar un par de líneas. En Linux para estas cosas yo suelo usar nano que es un editor bastante potente, pero muy sencillo de utilizar. No obstante también se puede usar vim o cualquier otro. Para gustos los colores.

Así que bajamos nano y lo descomprimimos en una ruta conocida. No es necesario instalarlo. Y siguiendo los mismos pasos que hemos seguido antes, añadimos un alias para nano en nuestro perfil de PowerShell.

$NANOPATH = "C:\Program Files (x86)\Nano\nano.exe"
Set-Alias nano $NANOPATH

Function Edit-Profile
{
    nano $profile
}
La idea es la misma que con Notepad++. Creamos un alias llamado nano (podéis poner lo que queráis) que se ejecutará desde cualquier consola PowerShell. Y como bonus track, sobreescribimos la funcionalidad de la función Edit-Profile para que use nano. Así que si en PowerShell ejecutamos:

Edit-Profile

Veremos nuestro perfil dentro de PowerShell en un editor nano.


Y ahora, con nuestra vitaminada consola, las próximas entradas sobre MongoDB serán más sencillas.



















Etiquetas: , , , ,

Introducción a NoSQL y las bases de datos documentales.

0 comentarios

Seguramente hayas oído hablar de las bases de datos NoSQL (Not Only SQL). Es algo que últimamente está muy de moda en el mundo del desarrollo. Casi tanto como que las chicas lleven shorts en verano o que la gente utilice cascos grandes para el MP3.

Resumiendo las bases de datos NOSQL, difieren en varios puntos a las bases de datos relacionales de toda la vida como son: que no usan SQL ya que no son bases de datos relacionales, que no se necesitan estructuras fijas (tablas, columnas etc.) y en general no soportan ACID.

Hay muchos tipos distintos de bases de datos NoSQL que que podríamos agrupar distintos tipos: documentales, de grafo, de clave/valor, multivalor, orientadas a objetos o tabulares. Y dentro de cada tipo hay muchas implementaciones distintas lo cual es bueno (mucho dónde elegir) y malo (mucho dónde elegir).

En nuestro caso vamos a hablar de bases de datos documentales. Aunque esta primera toma de contacto se centrará más en las bases de datos documentales, lo haremos teniendo en cuenta que en el futuro utilizaremos MongoDB.

MongoDB es un sistema gestor de base de datos orientado a documentos. Lo cuál quiere decir, en lenguaje de andar por casa, que lo que guardamos en la base de datos son documentos. MongoDB guarda los documentos en BSON, que no es más que una implementación binaria del conocido JSON. Por tanto todos los documentos guardados en la base de datos se pueden tratar como haríamos en JavaScript. De hecho, ya iremos viendo que para realizar consultas, en la consola de MongoDB utilizaremos JavaScript. Por ejemplo:

{
    "Nombre":"Charlas con un Cylon",
    "Twitter":"@_rubenfa",
    "Lenguajes": [
        {
            "Nombre":"C#",
            "Entorno":".NET"
        },
        {
            "Nombre":"Visual Basic",
            "Entorno":".NET"
        }
    ]
}
Los documentos se guardan en colecciones, que podrían asemejarse a las tablas que conocemos de los sistemas relacionales. La diferencia principal es que los documentos no tienen porque tener los mismos campos. Puede que un documento tenga un campo que no existe en otro, e incluso los tipos de datos pueden ser diferentes. Por ejemplo que en la colección Personas, existan estos dos documentos, es totalmente válido:

{
    "Nombre":"Perico",
    "Apellidos":"De los palotes"
    "DNI":"787978J"
},
{
    "Nombre":"John",    
    "DNI":232333233,
    "Telefono":"+7889987987789798"    
}

Como se puede ver, no tenemos un esquema definido, por lo que el enfoque que utilizaremos con MongoDB es totalmente distinto al que utilizaríamos con un RDBMS. Al no existir las relaciones directamente, tenemos que pensar un poco en como vamos guardar los documentos para no sobrecargar nuestra base de datos haciendo consultas demasiado grandes o duplicando consultas.

Por ejemplo imaginando que tenemos una colección que se llama clientes y otra que se llama pedidos podríamos tener tres implementaciones totalmente diferentes.

Una colección para pedidos y clientes.

{
    "Cliente":1233,
    "Nombre":"Pedro Ramírez",
    "Dirección":"Calle de la piruleta 14",
    "Pedidos":[
        {
            "id_pedido": 1,
            "Productos":
            [    
                {
                    "id_producto":1, 
                    "Nombre":"Pentium IV", 
                    "Fabricante":"Intel", 
                    "Cantidad":1
                },
                {
                    "id_producto":2, 
                    "Nombre":"Tablet 8 pulgadas", 
                    "Cantidad":1
                }
            ]            
        },
        {
            "id_pedido": 2,
            "Productos":
            [    
                {
                    "id_producto":77, 
                    "Nombre":"Impresora Láser", 
                    "Fabricante":"Canon", 
                    "Cantidad":3
                }                
            ]
        }    
    ]
}

En este caso los pedidos están embebidos dentro de los datos del cliente. Esto hará que realizar consultas Pedido-Cliente sea sencillo y rápido. Lo malo es que el tamaño de los clientes crecerá según vaya haciendo pedidos, cosa que puede ser desaconsejable en muchos casos. Imaginad un cliente con 100.000 pedidos. La muerte.

Dos colecciones: una para pedidos y otra para clientes

Clientes

{
    "Cliente":1233,
    "Nombre":"Pedro Ramirez",
    "Dirección":"Calle de la piruleta 14",
}


Pedidos

{
    "id_pedido":1,
    "id_cliente":1233,
    "Productos":
            [    
                {
                    "id_producto":1, 
                    "Nombre":"Pentium IV", 
                    "Fabricante":"Intel", 
                    "Cantidad":1
                },
                {
                    "id_producto":2, 
                    "Nombre":"Tablet 8 pulgadas", 
                    "Cantidad":1
                }
            ]
},
{
    "id_pedido": 2,
    "id_cliente":1233,
    "Productos":
        [    
            {
                "id_producto":77, 
                "Nombre":"Impresora Láser", 
                "Fabricante":"Canon", 
                "Cantidad":3
            }                
        ]
}    

Ahora los datos están más separados. Lo bueno es que la colección de clientes será más fácil de manejar, pero lo malo es que en nuestra aplicación deberemos controlar las relaciones. Para buscar los pedidos de un cliente, primero tendremos que conocer el identificador del mismo, por lo que quizá necesitemos realizar dos consultas.

Dos colecciones con datos duplicados: una para clientes y otra para pedidos.

Clientes

{
    "Cliente":1233,
    "Nombre":"Pedro Ramirez",
    "Dirección":"Calle de la piruleta 14",
    "ultimo_pedido:" 
    {
        "id_pedido": 2,    
        "Productos":
        [    
            {
                "id_producto":77, 
                "Nombre":"Impresora Láser", 
                "Fabricante":"Canon", 
                "Cantidad":3
            }                
        ]
    
    }
}



Pedidos

{
    "id_pedido":1,
    "id_cliente":1233,
    "Dirección":"Calle de la piruleta 14",
    "Productos":
            [    
                {
                    "id_producto":1, 
                    "Nombre":"Pentium IV", 
                    "Fabricante":"Intel", 
                    "Cantidad":1
                },
                {
                    "id_producto":2, 
                    "Nombre":"Tablet 8 pulgadas", 
                    "Cantidad":1
                }
            ]
},
{
    "id_pedido": 2,
    "id_cliente":1233,
    "Dirección":"Calle de la piruleta 14",
    "Productos":
        [    
            {
                "id_producto":77, 
                "Nombre":"Impresora Láser", 
                "Fabricante":"Canon", 
                "Cantidad":3
            }                
        ]
}    

En este caso tendríamos mucho más fácil consultar el último pedido de un cliente o saber la dirección a la que ha sido enviado un pedido sin tener que hacer dos consultas. La parte mala, es que estamos duplicando datos, ya que hay campos que existen en distintas colecciones.

En definitiva tenemos un sistema mucho más flexible. Como no hay restricciones, la lógica principal para controlar la integridad de los datos, recaerá en la aplicación. Esto choca frontalmente con el pensamiento relacional al que solemos estar acostumbrados. De hecho, hay que pensar que si nuestros datos son mayoritariamente relacionales, lo mejor es utilizar una base de datos relacional clásica.

Y de momento lo dejamos aquí. En próximas entradas veremos como ejecutar MongoDB y realizar consultas simples.






Etiquetas: , , , ,

Añade parámetros, que es gratis.

0 comentarios

Estoy añadiendo funcionalidad a un web service existente y me he encontrado con una desagradable sorpresa. Un método que acepta 19 parámetros. Sí, habéis leído bien, acepta 19 parámetros. 

Lo peor de todo es que tengo que modificar este engendro y añadirle un parámetro más. Lo ideal sería refactorizar todo el método, pero no tengo tiempo para eso. Más que nada porque el código es tan malo que tendría que modificar todo el web service, y a mi jefe de proyecto le podría dar algo.

¿Por qué no es bueno añadir tantos parámetros?

En un capítulo de Clean Code (de Robert C.Martin) analizan este problema. Al final llegan a la conclusión de que un parámetro es bueno, dos no es malo, tres podría ser aceptable siempre que sea justificado y más de tres ya habría que justificarlos muy, pero que muy bien. En el caso que nos ocupa, parece improbable que se pueda justificar el uso de 19 parámetros en un mismo método. Normalmente esto indica un problema de diseño. Es probable que se esté rompiendo el principio de responsabilidad única, que dice que una clase o método debería hacer una cosa y solo una. Lógicamente si el método recibe tantos parámetros, es probable que sea porque el mismo esté realizando más de una cosa.

Bien, en este caso, no se está haciendo más de una cosa. Simplemente el método crea un XML dependiendo de los parámetros de entrada. Entonces ¿no habría una manera mejor de hacerlo? Sí, usar clases o estructuras. En mi caso el método tiene conjuntos de datos que se podrían agrupar de forma bastante sencilla. Por ejemplo, suponiendo el método:

public XmlDocument GenerateXML(int id_cliente, string nombre_cliente, 
                               boolean recibir_publicidad_cliente, DateTime fecha_alta_cliente,                                
                               int id_producto_comprado, string descripcion_producto_comprado, 
                               DateTime fecha_lanzamiento, string codigo_activacion_producto_comprado,
                               string version_producto_comprado, int dias_validez_producto_comprado)

 
He creado un método con 10 parámetros y hasta me he cansado. Independientemente de lo que haga este método, ¿no es más fácil hacerlo de esta otra manera?:

struct Cliente
{
    public int id { get; set; }
    public string nombre { get; set; }
    public DateTime fecha_alta { get; set; }
    public bool acepta_publicidad { get; set; }
    public int id_cliente { get; set; }
}

struct Producto
{
    public int id { get; set; }
    public string decripcion { get; set; }
    public DateTime fecha_lanzamiento { get; set; }
    public string codigo_activacion { get; set; }
    public string version { get; set; }
    public int dias_validez { get; set; }
}
    
public XmlDocument GenerateXML(Cliente cliente, Producto producto)
Yo lo he hecho con estructuras, pero se podría hacer lo mismo con clases. Instanciando un objecto Cliente y otro Producto, nos bastaría con pasárselo al método para que realizara las operaciones necesarias. El código quedaría más limpio y más fácil de mantener.

Así que ya sabéis, antes de definir un nuevo parámetro, pensar si es necesario. Yo me voy a añadir otro más al engendro. Total dónde caben 19, caben 20.





Etiquetas: , , ,

Cursos gratuitos sobre MongoDB

0 comentarios

Una entrada rápida.

Generalmente lo más sencillo al hacer algo en MVC es optar por Entity Framework o LINQ to SQL. Pero claro, aunque sencillo y potente, no tiene porque ser lo más divertido. 

Últimamente he estado trasteando mucho con MongoDB  Es cierto que hay otras bases de datos NoSQL más orientadas a .NET como RavenDB, pero yo elegí MongoDB porque existe bastante diversidad de servicios online y con planes gratuitos muy interesantes. En concreto yo estoy utilizando mongolab, que además está en fase de pruebas para ser incluido en Azure como opción adicional. Tienen un plan gratuito que permite una base de datos de hasta 500 MB. Más que suficiente para hacer pruebas.

¿No está MongoDB más orientado a Java? En principio pudiera parecer que sí, pero el driver de MongoDB para C# funciona muy bien y es muy sencillo de utilizar. Así que, si queréis probar,  no lo dudéis. Pensar en modo "no relacional" es un reto para toda persona, que cómo yo, esté acostumbrada a trabajar con  SQL Server u Oracle. Lo podéis descargar desde NuGet.

Si queréis profundizar más, 10gen, empresa detrás del desarrollo de MongoDB está ofreciendo una serie de cursos gratuitos. En principio hay tres diferentes: para desarrolladores Java, para desarrolladores en general (aunque se utiliza Python) y para administradores.

Los cursos son cíclicos, así que cuando termina una convocatoria, empieza otra. Según comentan en la información, están pensados para poder seguirse utilizando unas 10 horas a la semana. Al final del mismo, tras finalizar las evaluaciones, trabajos y el examen final, se obtiene un diploma de 10gen, certificando la finalización del curso.

Así que nada, formación y gratis. ¿A qué esperáis para apuntaros?

Ya os iré contando qué tal la experiencia.

Volver a Windows 7 desde Windows 8, regresar al pasado.

0 comentarios

Cuando instalé Windows 8 en mi ordenador portátil hace unos meses, no pensé que el cambio fuera a ser tan sencillo. Me adapté rápido y a día de hoy soy productivo prácticamente al 100%.

Estos días me he acordado de Marty McFly intentando regresar al futuro. Me he visto en la necesidad de utilizar un nuevo portátil en el trabajo, pero en esta ocasión con Windows 7. Y como suele pasar en estos casos, empiezas a echar de menos las cosas cuando las pierdes. Y echo de menos muchas cosas de Window 8.