¿Porque los Programadores Requieren de Patrones de Diseño para Comunicarse Efectivamente?

Los patrones de diseño han sido reconocidos como una herramienta muy útil para la ingeniería de software, pero más que eso, son una herramienta de comunicación eficaz. En este artículo por Jason McC. Smith se muestra cómo los patrones de diseño cumplen con los requisitos para una comunicación efectiva, y cómo a su vez, elevan y mejoran la ingeniería de software con su aplicación.

Actualmente los patrones de diseño son una parte estándar de la ingeniería de software, sin embargo, siguen siendo uno de los elementos más incomprendidos de la disciplina de programación. La exposición de un desarrollador a los patrones de diseño usualmente  inicia como una colección de recetas, o un conjunto de fragmentos de código para copiar y pegar fielmente. La aplicación de patrones de diseño como soluciones sacrosantas no ayuda ni a los desarrolladores, ni a su código, y menos a su equipo.

Como desarrolladores somos más que simples ensambladores de curiosidades, y en general somos capaces de mucho más que poner una pieza A en la ranura B. En el fondo, los patrones de diseño son a menudo la tácita evidencia de una simple verdad sobre la programación: básicamente, la programación es comunicación.

Cuando programamos, escribimos simultáneamente la descripción de un sistema que está dirigido a dos audiencias muy diferentes: el compilador, y otros desarrolladores. El compilador es feliz mientras cumplamos estrictamente con la especificación del lenguaje. Otros desarrolladores, incluyendo nosotros en el futuro, tendemos a ser un poco más exigentes. Todos nos hemos encontrado con un pedazo de código que escribimos meses o años antes, tratando de reconstruir nuestro razonamiento. Los desarrolladores quieren y necesitan saber no sólo de qué trata la funcionalidad, sino también el porqué del diseño. Queremos saber lo que es robusto, y lo que es frágil. Queremos saber lo que es maleable, y lo que está detrás de una línea invisible que no se debe tocar. Los desarrolladores necesitamos más información que el compilador.

La documentación es una forma de proporcionar esta información, pero en la mayoría de los casos esta termina desactualizada con respecto al código fuente. Presiones inmediatas, tales como las fechas de liberación o los plazos de los clientes preceden a los objetivos de largo plazo, como la robustez del producto. Los patrones de diseño, por otro lado, se tejen en el código fuente en sí, y no pueden estar fuera de sincronía. Para un desarrollador adiestrado en su significado, le ofrecen una gran cantidad de información más allá de una descripción funcional.

Los patrones de diseño son un destilado de la experiencia de muchos desarrolladores en una sabiduría comunal, y su aprendizaje puede incrementar aumentar en gran medida las posibilidades de comunicación con otros programadores. Proporcionan además un vocabulario común, la semántica y la documentación para conceptos y temas de diseño que quedan fuera de los aspectos estrictamente informáticos de nuestro campo.

Sin embargo, la experiencia en patrones de diseño puede ser difícil de adquirir en el campo. La existencia de patrones de diseño en el código a menudo no es tan explícitamente obvio como, digamos, la definición de un algoritmo, y los patrones de diseño describen situaciones y soluciones que pueden estar fuera del actual conjunto de conocimientos de algunos desarrolladores. Obtener la capacidad de comprender por qué una solución particular se considera una buena práctica puede resultar difícil para un desarrollador, hasta que este obtiene un profundo conocimiento de por qué existen ciertos problemas. Esa comprensión, a su vez requiere experiencia, lo que lleva a una especie de situación del huevo y la gallina.

Para comprender un tema como patrones de diseño se debe comenzar por las bases. Determinar la existencia de problemas comunes de programación y algunas soluciones exitosas ayuda a los desarrolladores a entender la evolución de aquellas que se han convertido en patrones. Esto se convierte en un trampolín para zambullirse en la literatura de patrones y obtener una comprensión más profunda de las experiencias obtenidas a través de un gran esfuerzo. En última instancia, el desarrollador deberá ser capaz de crear sistemas robustos y flexibles con mayor rapidez, y será un mejor comunicador de sus intenciones, sobre todo de los puntos más sutiles de sus implementaciones y diseños. A medida que trabaje con desarrolladores que tengan un conocimiento similar de patrones de diseño, usted encontrará que puede comprender más rápidamente el código de sus compañeros.

La comunicación se mejora gracias a que los patrones de diseño facilitan entre los desarrolladores  un lugar común requerido para una transferencia eficaz de información. Una lista utilizada en los campos relacionados de la comunicación refiere algunos temas comunes que incluyen, en ningún orden particular, claridad, concisión, coherencia, exactitud, integridad, concreción y cortesía. Una vez más aprovechando la idea de aprender de las experiencias de los demás, podemos pedir prestadas estas ideas y demostrar cómo los patrones de diseño cumplen con los mismos objetivos de la comunicación efectiva.

Claridad

La claridad en el código no depende de si las llaves se colocan en la línea siguiente, o si se sigue un estilo de sangrado específico. Es posible que el uso de un oportuno artilugio ingenioso para salvar el día le pueda dar al desarrollador de una fantástica sensación de logro. Sin embargo, la  producción de código obscuro y complejo de forma regular se puede comparar con un fuerte carga del cuerpo en el fútbol: una habilidad muy útil en una situación de presión, pero si lo hace con sus colegas de la nada durante un día normal, usted acaba siendo un idiota. El código debe ser claro en lo que hace y cómo lo hace. La selección de nombres significativos para las variables, funciones y tipos es un comienzo, pero el diseño general debe ser también rápidamente comprensible. Los patrones de diseño dan un desarrollador ideas sobre la forma de nombrar y estructurar soluciones de manera que los demás puedan identificarlas fácilmente, proporcionando pistas semánticas tanto en la forma de una clara nomenclatura como en construcciones de diseño evidentes.

Concisión

Cuando utiliza patrones de diseño, usted puede ser conciso en sus expresiones. En lugar de tener que generar documentación para explicar los antecedentes por los qué eligió resolver un problema de una manera particular, cómo espera que sea utilizado y no utilizada la solución, y así sucesivamente, se puede hacer referencia al modelo de diseño subyacente directamente. Incluso mejor, si se pueden usar nemónicos identificables del patrón de diseño en el código en sí, ni siquiera se tiene que generar la documentación. El patrón que está usando va a ser claro, y un desarrollador que lea su código puede investigar ese patrón sólo si es necesario. Esto hace que sea  menos lo que usted deba escribir, y menos lo que otros tienen que leer. Todo el mundo gana.

Consistencia

Ya sea que usted esté trabajando en un procesador de textos o el sistema de control de un avión de combate, un Singleton es un Singleton. No importa si usted programa en Java, C + + o Python, un Decorador es un Decorador. Las implementaciones pueden variar, pero los conceptos y las motivaciones detrás de ellos siguen siendo los mismos. Los patrones de diseño trascienden dominios e idiomas, y nos otorgan una terminología y comprensión coherentes. No sólo su actual sistema se beneficia de un lenguaje consistente, también encontrará mucho más flexibilidad en sus opciones de carrera, porque mucho de su conocimiento y experiencia pueden ser transferidos a diferentes situaciones, lenguajes de programación y entornos de programación.

Exactitud

Crear la solución correcta para un problema dado no siempre es trivial o evidente. Cualquier problema de programación puede ser resuelto en un número casi infinito de formas. Muy pocas de estas implementaciones son buenas soluciones, y mucho menos son las soluciones adecuadas. La literatura sobre patrones de diseño funciona como una referencia para conectar las mejores prácticas con sus soluciones relacionadas. Si se ve que un patrón trabajará adecuadamente en un problema, pero usted recibe un cambio difícil o raro en la asignación y este a su vez hace que el patrón ya no sea adecuado, la redacción en el patrón de diseño usualmente hará referencia a otros patrones relacionados, que le permitirán seleccionar una solución más apropiada.

El uso de un patrón de diseño como una guía para la solución de un problema también le ayuda a asegurarse no únicamente de que se está produciendo la solución correcta, sino que la solución correcta se está aplicando correctamente. Con demasiada frecuencia, resolvemos problemas de manera que se ven muy bien al principio, pero no tomamos en cuenta casos en el límite y pequeños detalles que regresan a mordernos más tarde. La sabiduría colectiva que se encuentra en los patrones de diseño lleva las cicatrices de muchas de estas mordidas. Los patrones de diseño se han probado en batalla y se determinó que son las mejores soluciones prácticas, y que además  han resistido la prueba del tiempo. Las soluciones incorrectas nunca duran mucho tiempo en un ambiente así.

Integridad

La integridad va de la mano con la exactitud. ¿Ha encontrado todos los casos en el límite de la solución? ¿Ha pensado en lo que sucederá dentro de dos años cuando las necesidades cambien, pero el código todavía esté en uso? ¿Ha pensado en todos esos pequeños detalles que parecen surgir más adelante, o va a tener que entrar en un ciclo de eliminación de defectos para mantener el sistema en funcionamiento? ¿Qué tan completa es su cobertura conceptual? Aprenda de aquellos que vinieron antes que ustedes, que han encontrado las grietas y huecos, y encontraron maneras apropiadas para evitarlos o llenarlos. Mediante la utilización de patrones de diseño, otros desarrolladores pueden tener mayor confianza en la integridad y exactitud de la solución.

Concreción

Cuando producimos una solución que nuestros colegas no han visto antes, a menudo hay una buena cantidad de saludable escepticismo. Cuando estamos en el proceso de creación de una nueva solución, a menudo hay una buena cantidad de incertidumbre dentro de nosotros mismos. En ambos casos, los ejemplos concretos y parámetros conocidos del diseño son una ayuda en la definición del problema y la solución. Al referirse a una especificación existente y su descripción no sólo fomenta la discusión, sino que a menudo resalta las limitaciones que no fueron reconocidas o previstas. Al usar patrones de diseño en sus discusiones y codificación, ofrece implícitamente un enlace a un conjunto amplio de información concreta. Al implementar un patrón de diseño en el código y también dejando en claro qué patrón se está utilizando, reduce las preguntas que un desarrollador pueda tener más adelante.

Cortesía

Por último, y volviendo al punto anterior sobre que el código obscuro y complejo es una afrenta  a sus colegas, la comunicación efectiva es simplemente cortés. Cuando se escribe código que requiere que sus compañeros de equipo pasen tiempo reconstruyendo su pensamiento en detalle sólo para usar o mantener el código, les está diciendo que su tiempo vale poco para usted. Diseñe y escriba sus sistemas como si usted fuera el que va a tener que averiguar las intenciones en el camino, porque lo más probable es que sea usted el que termine haciéndolo. Los patrones de diseño son una ayuda en este proceso, ya que le permiten utilizar una abreviatura conveniente y común para conceptos a veces esotéricos que requieren mucho tiempo y esfuerzo de sus colegas para desentrañar. Es en el mejor interés de todos que su código se comunique tan efectivamente como sea posible.

Al final, la programación es acerca de la comunicación efectiva. Hasta que podamos llegar a usar la telepatía, no existe una solución perfecta para que la comunicación entre los desarrolladores sea perfecta, pero podemos utilizar herramientas como los patrones de diseño para hacer más fácil la tarea en muchos frentes. En el frente de comunicación con el compilador, el soporte de herramientas para patrones de diseño sigue mejorando. Existe soporte para la aplicación de patrones en una implementación y vienen avances interesantes en la detección automática de patrones directamente en la comprensión de código y para el cumplimiento de reglas de diseño. Los patrones de diseño son una herramienta de comunicación que todos podemos usar en conjunto para crear una comunidad mejor para nosotros y nuestros clientes. A medida que nuestra comunicación sea más efectiva, también lo hacen nuestros productos, nuestros sistemas y nuestra disciplina. Use los patrones de diseño para catalizar la lista de elementos para su propia comunicación efectiva, y tal vez estará agradecido consigo mismo al crear un sistema claro y cortés. El resto de nosotros lo estará, sin duda.

El artículo original en Inglés se encuentra en Why Programers Need Design Patterns to Communicate Effectively

Jason McC. Smith es Autor de Elemental Design Patterns

Linux: Creación de Usuarios y Grupos para permisos específicos en un folder

Para crear un nuevo usuario bajo cualquier distribución  Linux  usa el comando useradd. El Administrador del sistema es el responsable de crear la cuenta (root). Registrate  como el usuario root (o utiliza el comando  sudo ).

Sintaxis del comando useradd

useradd [opciones] {nombre_usuario}

Dependiendo de las opciones en la linea de comando, la instrucción useradd actualizará los archivos de sistema (/etc/passwd y /etc/shadow con la contraseña) y puede ademas crear la nueva carpeta de home para el usuario y copiar archivos iniciales.

Agregar en Lunux un nuevo usuario llamado itbrain

Teclea el siguiente comando:

useradd itbrain

Asigna una contraseña para itbrain:

passwd itbrain

Si no asignas una contraseña la nueva cuanta se creara con un estado bloqueado. Para desbloquear la cuenta, se requiere utilizar el comando passwd. Usa passwd para asignar una nueva contraseña y establecer parámetros de expiración de la misma.

Establece una fecha de desactivación para la cuenta

Puedes establecer una fecha de desactivación para una cuenta con el formato AAAA-MM-DD usando la opción  -e  al momento de crear la cuenta:

useradd -e {aaaa-mm-dd} {nombre_usuario}
useradd -e 2012-10-31 itbrain

Establecer la expiración de la contraseña

La opción -f {dias} establece el número de días en que la cuenta será desactivada una vez que la contraseña haya expirado. (Si se establece la opción o, la cuenta se desactiva de inmediato. Si se usa -1,  la cuenta no se desactiva después de la expiración de la contraseña.)

useradd -f {dias} {nombre_usuario}
useradd -e 2012-10-31 -f 30 itbrain

Linux: Administración de espacio en disco

Todos nos hemos topado con el problema de espacio en disco, ya sea porque en nuestra maquina se nos acaba el espacio por tanto mp3’s o videos o en el servidor que estamos administrando los backups y logs que se generan empiezan a consumir ese precioso espacio que al final nos puede afectar en el rendimiento del sistema operativo y por consiguiente de las aplicaciones que ahí corren.

Es necesario conocer los comandos adecuados para conocer el espacio que se esta ocupando, quien lo esta ocupando y ver que podemos eliminar para poder tener mas.

Conocer el espacio usado en disco

Lo que primero hay que conocer es el total de espacio que estamos usando en el disco duro y para realizar eso usamos el comando:

df -h

El cual nos dice el espacio del Sistema de archivos en la columna Size, el espacio usado en la columna Used, el espacio disponible en la columna Avail y el porcentaje que representa el espacio usado  y por ultimo el punto de montaje de ese sistema de archivos. Se usa la opción “h” (human-readable) para que nos de valores que nos arroje el comando vengan en valores de Kilobytes, Megabytes o Gigabytes y no en bloques que es como por default imprime los valores.

Conocer el espacio usado por un folder en especifico

Ahora, si lo que deseamos conocer es el espacio especifico de un folder debemos correr el comando:

du folder -ha

Donde folder es el nombre o ruta hacia el folder del cual queremos conocer el espacio que esta usando. Como salida este comando imprime el tamaño de cada uno de los archivos y folders contenidos dentro de el. Se usa la opción “h” para, igual que en el comando ‘df’, los valores que arroje vengan en Kilobytes, Megabytes o Gigabytes. La opción “a” (all) se usa para que se impriman el tamaño tanto folders como archivos ya que si no se usa esta opción solo se imprimen folders.

Existen otras opciones a usar para este comando y como en la mayoría de los comandos en linux esas opciones se puede conocer ejecutando el comando de la siguiente forma:

du --help

La salida del comando ‘du’ se podría ordenar para así poder obtener, por ejemplo, los 10 folders y archivos que son los que ocupan mas espacio dentro de un cierto folder:

du folder -ka | sort -n -r | head -n10

Se usa la opcion ‘k’ en el comando ‘du’ para que en lugar de que nos imprima valores en Kilobytes, Megabytes o Gigabytes solo imprima todos los valores unificados a Kilobytes y el comando ‘sort’ pueda ordenarlos de manera uniforme. Y para solo obtener los 10 primeros se utiliza el comando ‘head’. Así que si, por ejemplo, se desea obtener los primeros 5 solo hay que variar el valor en la opción ‘n’ del comando ‘head’.

Pero si lo que se desea saber es el tamaño total de cierto folder sin tener que ver el tamaño de su contenido se usa el comando:

du folder -hs

La opción ‘s’ (summarize) hace que solo se imprima el valor total del folder si que se muestre el tamaño de cada folder y archivo que contiene.

Hay que tomar en cuenta que para obtener los valores de tamaño el comando tiene que recorrer el contenido del folder para ir sumando el tamaño de cada elemento que contiene, así que, si el folder es muy grande la ejecución de este comando puede tardar.

Borrar archivos y folders

Ya que se conoce el elemento que se desea borrar se hace uso del comando ‘rm’ para eliminarlo. Si se trata de un archivo se usa el comando:

rm archivo

pero si se trata de un folder y nos interesa borrar el mismo y su contenido, se usa el comando:

rm -rf folder

hay que tomar en cuenta que una ves borrados ya no es posible recuperarlos así que estos comandos se tienen que usar con mucho cuidado.

grails

Creacion de un proyecto base con Grails 2.0.3

Vamos a crear un proyecto web base para una aplicación que podría usar un kinder considerando solo poder hacer Altas Bajas y Cambios (ABC) de dos entidades Tutores y Alumnos.  Yo trabajaré en un Linux Mint, las instrucciones en consola son similares en cualquier distribución derivada de Debian o Ubuntu, para windows solo cambiarían las carpetas y las variables de entorno.

Empecemos instalando Grails.

Necesitamos tener instalado java y haber definido nuestra variable de entorno JAVA_HOME.

  1. Descargar grails
  2. Descomprimir ZIP en una carpeta (la mia será /opt )
  3. Crear las variables de entorno GRAILS_HOME y JAVA_HOME (si no existe)
export GRAILS_HOME=/opt/grails-2.0.3
export PATH=$PATH:/opt/grails-2.0.3/bin

Para comprobar que nuestra instalación está completa debemos ejecutar el comando grails para obtener la versión.  En algunos sistemas como el mío se requiere reiniciar la sesión de usuario para que se apliquen los cambios en las variables de entorno.

$ grails -version
Grails version: 2.0.3

Ahora creamos nuestra aplicación, se genera una carpeta con el nombre de la aplicación, ingresamos a dicha carpeta y luego abrimos la consola de grails.

$ grails create-app kinder
| Created Grails Application at /home/wdonet/branches/grails/kinder
$ cd kinder/
$ ls
application.properties  grails-app  lib  scripts  src  test  web-app
$ grails
| Downloading: plugins-list.xml
grails> help

Podemos usar el comando help para ver todos los comandos que tenemos disponibles en la consola de grails, incluso puedes obtener ayuda de un comando en especifico escribiendo por ejemplo : help create-app.  Pero toma nota que la consola de grails es una forma para jugar con el ambiente de tu proyecto, si quieres ejecutar tu aplicación es mejor usar el comando grails (fuera de la consola).

Como yo utilizo IntelliJIDEA como IDE para desarrollo, le voy a agregar el soporte para este IDE al proyecto, pero no es necesario, si usas eclipse, STS u otro, este paso no es necesario ya que Grails genera por defecto el archivo de configuración para abrir el proyecto en eclipse.

grails> integrate-with --intellij
| Created IntelliJ project files..

Sigue leyendo

Introducción a MongoDB

 Me metí un poco a ver como funcionaba CouchDB pero entre revisiones y vistas rápidas a referencias aquí y allá llegue a MongoDB, ambas son alternativas No-SQL (termino que empezó a agarrar fama desde 2009) y que su almacenamiento de datos está orientado a documentos JSON y BSON (Bynary JSON) para ofrecer sistemas flexibles, rápidos, ligeros, potentes y fáciles de usar.

Según Eliot Horowitz, 10gen CTO y co-fundador de mongoDB, prácticamente podrías tomar una base de datos hecha en MySQL, cambias el modelo relacional a uno basado en documentos y obtendrías varias mejoras como:

  1. Documentos embebidos para mejorar la velocidad
    1. El uso de json es más amigables con objetos en lenguajes de programación
    2. El meter documentos embebidos y arreglos reduce la necesidad de hacer joins
  2. Manejabilidad
  3. Desarrollo ágil con base de datos sin esquemas
    1. Al usar JSON/BSON es fácil de codificar y administrar
  4. Escalabilidad horizontal más facil
    1. Es una solución para sistemas que requieren escalar horizontalmente sobre varios servidores.
    2. La funcionalidad de autosharding permite escalar tu cluster agregando mas equipos sin necesidad de dar de baja el servicio.

En realidad no estamos quitando todo el trabajo que ya se ha hecho con las bases de datos relacionales porque en muchas cosas como la creación de indices, llaves primarias, consultas dinámicas y actualizaciones, por mencionar algunas,  se tiene que hacer los mismo, salvo que se busca tener las ventajas arriba descritas.

La gente de apache que desarrolla CouchDB mencionan que los esquemas relacionales funcionarán en algunos casos mientras que los esquemas no-SQL funcionarán en otros.

 

El modelo de datos de MongoDB considera lo siguiente:

  • Un sistema mongo contiene un conjunto de bases de datos.
  • Una base de datos (database) contiene un conjunto de colecciones.
  • Una colección (collection) contiene un conjunto de documentos.
  • Un documento (document) es un conjunto de campos.
  • Un campo (field) es un par llave – valor.
  • Una llave (key) es un nombre en forma de cadena.
  • Un valor (value)es:
    • un tipo de dato básico, string, integer, float, timestamp, binary, etc.,
    • otro documento, ó
    • un arreglo de valores

El lenguaje de consulta

Al tratar con objetos json la estructura de un nombre podria ser: {nombre: ‘Sebastian’, paterno: ‘Morales’}, esta estructura se puede usar por ejemplo para buscar todos los documentos (registros) de una colección (tabla) que empaten con el nombre “Sebastian Morales”, pero también podemos hacer lo siguiente:

  • {nombre.paterno: ‘Morales’}, para obtener los que tengan apellidos ‘Morales’.
  • {nombre.paterno: /^M/}, para obtener los que tengan apellidos que inicien con ‘M’
  • {keywords: ‘tecnico’}, para los documentos con ‘tecnico’ dentro del contenido del arreglo
  • {keywords: {$in:[‘tecnico’, ‘licenciado’]}, para los documentos con ‘tecnico’ o licenciado dentro del contenido del arreglo.

Si tenemos muchos documentos en una colección y queremos mejorar la velocidad de búsqueda de las consultas, crearemos índices comose muestra abajo, pero hay que tomar en cuenta que se ocupa mas espacio y reduce la velocidad de los ‘update’.

  • ensureIndex({nombre.apellido:1})
  • ensureIndex({keywords: 1})

 

Instalación y primeros ejemplos

Aunque los procesos de instalación son diferentes para cada S.O. yo presentaré el que realicé en Linux Mint.  Debo comentar que el sitio de MongoDB recomienda que se descargue la última version de sus servidores ya que los repositorios de Debian o Ubuntu no se encuentran del todo actualizados, no obstante para propositos de esta entrada nos basta seguir lo siguiente:

sudo apt-get install mongodb

Entre los comandos que se instalarán se encuentran mongod (servidor) y mongo (cliente).  Este último debe ser el usado para entrar a la consola y ejecutar consultas al servidor.

$ mongo

> db.alumno.save({nombre:’julian’, paterno:’rodriguez’, edad:12, grupo:’2A’})

> db.alumno.find()

{ “_id” : ObjectId(“4f99d713b16869a4f4d5abd9”), “nombre” : “julian”, “paterno” : “rodriguez”, “edad” : 12, “grupo” : “2A” }

> help

Con db.alumno.save() creamos la colección alumno y agregamos el primer documento con el nombre de julian, luego lo consultamos con db.alumno.find() y para ver mas ayuda sobre los comandos ejecuta help.

Por defecto, el comando mongo se conecta a una base de datos llamada “test” en localhost, por eso al ejecutar el comando mongo, verían algo como esto:

wdonet@wdonet-mint12 ~ $ mongo
MongoDB shell version: 1.8.2
Thu Apr 26 17:06:35 *** warning: spider monkey build without utf8 support.  consider rebuilding with utf8 support
connecting to: test
> db

test
> use miPropiaBD
switched to db miBD
>
db
miPropiaBD

Usamos el comando use para poder cambiar la base de datos y lo comprobamos con el comando dbo con show dbs.  Esto no crea inmediatamente la BD, sino hasta que por primera vez le insertas datos. El comando show no mostrará la nueva BD hasta que insertes datos.  Lo mismo sucede con las colecciones.

En MongoDB no hay campos predefinidos (lo que serían columnas en un RDBMS), tampoco hay esquemas definidos para dichos campos por lo que sus tipos de dato pueden variar y las colecciones pueden guardar diferenets campos.

> j = { nombre : "roberto"};
{ "nombre" : "roberto" }
> t = {edad : 30}
{ "edad" : 30 }
> db.nuevaColeccion.save({j, t})
Thu Apr 26 19:25:15 SyntaxError: invalid object initializer (shell):1
> db.
nuevaColeccion.save(j)
> db.
nuevaColeccion.save(t)
> db.
nuevaColeccion.find()
{ "_id" : ObjectId("4f99e77c00745aa18f47cb08"), "nombre" : "oswaldo" }
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }
>

Cada vez que se inserta un documento en la colleccion, se crea un identificador del objeto “_id” que es diferente para cada documento, funciona como una llave primaria.

También es de observar que los ‘;’ son para terminar una instrucción, pero si solo es una por línea, no son necesarios.  Otro conveniente es que podemos usar ciclos y operaciones matemáticas como el que sigue:

> for (var i = 0; i <= 5; i++) db.nuevaColeccion.save({x: i*i, y: i+i});
> db.
nuevaColeccion.find()
{ "_id" : ObjectId("4f99e77c00745aa18f47cb08"), "nombre" : "
roberto" }
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0a"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0b"), "x" : 1, "y" : 2 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0c"), "x" : 4, "y" : 4 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0d"), "x" : 9, "y" : 6 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0e"), "x" : 16, "y" : 8 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0f"), "x" : 25, "y" : 10 }

El comando find() devuelve un objeto cursor, pero esta limitado a 20 resultados por pagina, si tuvieramos más de 20 documentos y quisieramos ver la siguiente página de resultados, deberíamos ejecutar “it” para que el shell itere automáticamente sobre el cursor

> it

Podemos jugar un poco con un cursor mediante metodos hasNext() o forEach(), e imprimimos con el método printjson().

> var cursor = db.nuevaColeccion.find();
> while (cursor.hasNext()) printjson(cursor.next())
{ "_id" : ObjectId("4f99e77c00745aa18f47cb08"), "nombre" : "roberto" }
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0a"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0b"), "x" : 1, "y" : 2 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0c"), "x" : 4, "y" : 4 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0d"), "x" : 9, "y" : 6 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0e"), "x" : 16, "y" : 8 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0f"), "x" : 25, "y" : 10 }
>
> db.
nuevaColeccion.find().forEach(printjson);
{ "_id" : ObjectId("4f99e77c00745aa18f47cb08"), "nombre" : "roberto" }
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0a"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0b"), "x" : 1, "y" : 2 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0c"), "x" : 4, "y" : 4 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0d"), "x" : 9, "y" : 6 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0e"), "x" : 16, "y" : 8 }
{ "_id" : ObjectId("4f99e96600745aa18f47cb0f"), "x" : 25, "y" : 10 }
>
> var cursor = db.nuevaColeccion.find();
> printjson(cursor[1])
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }

Los resultados del cursor se almacenan en memoria, por lo que hay que tener cuidado con resultados con muchos documentos.

Por último, para el propósito de introducción de esta entrada, podemos convertirlo en un verdadero arreglo como sigue:

> var arreglo = db.nuevaColeccion.find().toArray();
> printjson(
arreglo[1])
{ "_id" : ObjectId("4f99e77e00745aa18f47cb09"), "edad" : 30 }

Para salir:

> exit;

Fuentes:

Introducción a PostgreSQL

Hace un par de días me tuve que meter con PostgreSQL (versión 9.1.3) a manera de conocerlo un poquito ya que no sabía nada y me encontré con algunos detalles.

Para su instalación en Linux Mint o Ubuntu debemos hacer lo siguiente.

  1. sudo apt-get install postgresql libpq-dev (instala el motor y un usuario postgress con todos los privilegios para operar sobre el servidor)
  2. sudo su postgress (esto te permite abrir una sesion con el nuevo usuario postgress)
    1. createuser -d -s -P usuario , creamos un usuario donde:
      • -d es para darle permisos de creación de base de datos
      • -s es para darle permisos de superusuario
      • -P para poderle indicar un password al usuario
    2. exit
  3. sudo apt-get install pgadmin3 – para instalar el cliente gráfico (opcional)


Detalles de interés que se podrán observar en las instrucciones de ejemplo que copio mas adelante:
  • La diferencia contra otros manejadores de Base de Datos es que se puede hacer herencia entre tablas.
  • Cuando se heredan las tablas, las llaves primarias se tienen que redefinir dado que estas no se heredan.
  • Cuando se borran las tablas, los índices también se eliminan de forma automática.
  • Cuando se hacen muchas operaciones de creación/borrado en la base de datos, es necesario darle mantenimiento (opción vacuum en el pgadmin3).
  • La sintaxis para las fechas siempre es: YYYY-MM-DD.
Vamos a los ejemplos ahora sí:
-- Eliminamos la vista
DROP VIEW if exists dime_sus_tutores, dime_personas_sin_cel;
-- Eliminamos indices primero (aunque cuando se borran las tablas estos ya se eliminan)
DROP INDEX if exists idx_clave_escolar;
-- Eliminamos las tablas
drop table if exists
 tutores, personas, alumnos, tutores_alumnos;
 
-- Tabla personas PADRE
create table personas (
 id integer PRIMARY KEY,
 nombres varchar(75) not null,
 genero varchar(1),
 fecha_nacimiento date,
 lugar_nacimiento varchar(150),
 curp varchar(18) unique,
 tel varchar(20),
 cel varchar(20),
 email varchar(50),
 cuando date default current_date
);
-- Tabla hija de personas
create table tutores(
 id integer primary key,
 ocupacion varchar(100)
) inherits (personas);
-- Tutores
insert into tutores (id, nombres, genero, fecha_nacimiento, lugar_nacimiento, cel, ocupacion) values
 (1, 'Ricardo Rogers', 'm', '1970-01-10', 'Ciudad de México', '0445554374879', 'Musico'),
 (2, 'Guillermo Garcia', 'm', '1971-04-12', 'Tlaxcala', '044 55 94637383', 'Contador'),
 (3, 'Pita Perez', 'f', '1964-05-22', 'Ciudad de México', null, 'Ama de casa');
-- Tabla hija de personas
create table alumnos (
 id integer primary key,
 clave_escolar varchar(25),
 fecha_ingreso date,
 carrera varchar(50)
) inherits (personas);
-- Creacion de un indice
create unique index idx_clave_escolar on alumnos(clave_escolar);
insert into alumnos
 (id, nombres, genero, fecha_nacimiento, lugar_nacimiento, cel, clave_escolar, fecha_ingreso, carrera) values
 (4, 'Leonora Rogers Mendoza', 'f', '1994-01-10', 'Ciudad de México', '044 55 12345678', 'a100-101', '2011-08-14', 'informatica'),
 (5, 'Maximiliano Hotel', 'm', '1993-04-12', 'Tlaxcala', '044 55 87654321', 'b200-202', '2011-07-13', 'contaduría'),
 (6, 'Lupita Gómez Pérez', 'f', '1993-02-22', 'Ciudad de México', null, 'c300-303', '2011-06-12', 'contaduría'),
 (7, 'Arturo Gómez Pérez', 'm', '1994-05-22', 'Ciudad de México', null, 'd400-404', '2011-05-11', 'administración')
 ;
-- Tabla que relaciona personas y tutores
create table tutores_alumnos (
 id_tutor integer REFERENCES tutores(id),
 id_alumno integer references alumnos(id),
 primary key (id_tutor, id_alumno)
);
-- relaciones
insert into tutores_alumnos values (1,4),(2,5),(3,6),(3,7);
-- una vista
create view dime_sus_tutores as
 select a.nombres as Alumno, a.clave_escolar as Clave, t.nombres as Tutor, t.cel
 from tutores_alumnos ta
 left join alumnos a on ta.id_alumno = a.id
 right join tutores t on ta.id_tutor = t.id
 order by a.nombres
;
-- otra vista
create view dime_personas_sin_cel as
 select p.id, p.nombres, p.tableoid, c.relname
 from personas p, pg_class c
 where cel is null
 and p.tableoid = c.oid
;
Fuentes:    
  1. @mromtz – Mario Martinez — Taller de PostgreSQL —
  2. 2 módulos de un curso en línea
  3. www.postgresql.org