Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Sunday, November 1, 2009

Sobre editores, programación visual y demás yerbas

Perdón por la tardanza, pero acá seguimos con Ruby. :-)

La idea del tercer Post era estudiar los métodos en Ruby. Ese post quedara para la próxima semana, porque para esta me quede pensando en una duda que planteo Maximiliano en los comentarios del anterior post.


No voy a ser exhaustivo, sino tan solo explicar porque no confundir programación dentro del paradigma de objetos con la programación de Interfaces de usuario. Luego, me explayare en interesantes editores e IDEs para programar, en Linux y Windows, teniendo en cuenta los mas usados en Ruby.


Sobre la programación en objetos y la programación de GUI


El paradigma de objetos implica una visión abstracta y lógica de diversas entidades que existen en el mundo real. El paradigma de objetos obliga a ciertas reglas de construcción de objetos, manejo de memoria y técnicas o mecanismos particulares tales como envío de mensajes, herencia, polimorfismo, etc...


Todo lenguaje que soporta o implemente lo anterior, mas otras cuestiones adicionales, se considera un lenguaje que soporta el paradigma de objetos.


Con los objetos se realiza el modelo de datos y de comportamiento de una aplicación.


Por otro lado, las GUI (Interfaz Gráficas de Usuario) son una manera de representar un sistema ante los usuarios.


Pensemos en un sistema de 3 capas:


+-------------------------------------+
|---------Interfaz de usuario---------|
+-------------------------------------+
|----------Modelo de objetos----------|
+-------------------------------------+
|--------Modelo de datos físico-------|
|-----------(Base de datos)-----------|
+-------------------------------------+


El diagrama anterior nos muestra que el modelo de objetos esta entre la interfaz del usuario, y la base de datos física. Es decir, el modelo de objetos es el sistema, en memoria y trabajando. La interfaz de usuario es la forma amigable en que el usuario ingresa datos y pide que se ejecuten determinadas acciones. El modelo de datos físico es el almacenamiento permanente con alguna tecnología (Sistemas de archivos, SGBD, etc...)


De todo lo anterior podemos extraer varias conclusiones:


  • Los modelos de capas son muy ventajosos para los desarrolladores de aplicaciones, porque permite dividir el trabajo de una manera clara y natural.


  • Estudiar objetos no es estudiar las maneras que al usuario le gusta ver el sistema, sino estudiar la lógica interna de un lenguaje de objetos, como Ruby, Smalltalk, Python, etc...


  • La interfaz de usuario no solo es la GUI de ventana. Muchos grandes sistemas siguen funcionando en consolas de textos (sistemas financieros que es muy difícil o imposible dejarlos inoperativos aunque sea por un corto tiempo). La tendencia hoy en día es realizar aplicaciones Web, entonces allí la interfaz tampoco es "la ventana".
Con todo lo anterior, vemos que si estudiamos bien los objetos, la interfaz puede cambiar entre una y otra (y si esta bien hecho, debe poder cambiarse sin problemas) y puedo tener un mismo sistema en linea de comandos, en GUI y con interfaz web.


Ruby naturalmente permite realizar sistemas que interactúen con todas las interfaces. Naturalmente con las consolas de texto. Tiene Bindings para GTK, QT, WxWindows, etc... Y con Rails, su framework mas popular, se pueden desarrollar aplicaciones web.


Si se entiende bien el funcionamiento de un lenguaje, crear interfaces de usuario, sea web o sea GUI, es cuestión de agregar un modulo al lenguaje, aprender una API o mecanismo de interpretación adicional.


Editores de texto e IDEs para desarrollar con Ruby















Notepad++ (solo windows):
Es uno de los editores de software libre mas populares en plataformas Windows. Es de propósito general, con lo cual su integración con herramientas de Ruby es genérica (Resaltado de sintaxis y algún que otro plugin con funcionalidad menor).


Textmate (para rails y en OS X): Si se trabaja en plataformas MAC, Textmate es uno de los editores que mas se recomiendan para programar en Ruby, mas específicamente con Rails, por algunos elementos que hacen la tarea mucho mas sencilla. Es pago y de código cerrado.


Netbeans con plugins: Netbeans es el popular IDE desarrollado y mantenido por SUN, con una gran cantidad de plugins, entre ellos para Ruby y Rails, y también soporte para SVN nativo, ejecuciones de prueba del código, debbugin, etc... También es recomendado entre los desarrolladores de Ruby. Netbeans es multiplataforma.


Gedit con las mejoras de Textmate: Gedit es el bloc de notas del entorno de escritorio GNOME. En los últimos años este editor fue desarrollando mejoras orientadas a que se pueda usar como un editor para desarrollo. Al tener un sistema de plugins y agregados bastante interesante, desarrolladores se han orientado a mejorarlo para hacerlo mas potente. En particular, Jose ha hecho un trabajo excelente implementando plugins para que Gedit se acerque a Textmate en funcionalidad. La dirección del post principal en su blog es http://blog.nationcode.com/articles/2008/04/06/gedit-como-textmate-mejorado-para-rails-en-gnu-linux.


Komodo Editor: Editor OpenSource muy interesante. Es limitado porque hay otra versión paga y cerrada que es Komodo IDE. Se puede descargar desde su pagina http://www.openkomodo.com/


Geany: Editor ligero, bastante completo, y orientado a programadores. Otra buena alternativa a los editores usados comúnmente. Se puede descargar en http://www.geany.org/


VIM, Emacs: Clásicos editores de programación de entornos de desarrollo OpenSource. Son complicados para usuarios noveles, pero tienen muchos atajos y complementos que los hacen muy útiles para usuarios experimentados. La mayoría del desarrollo del Lenguaje Ruby fue hecho en Emacs.

En la próxima entrada, donde trataremos sobre métodos en Ruby, ya tendremos bastante mas código, así que pongan a punto esos editores ;-)

Fuentes consultadas:

http://rubytutorial.wikidot.com/introduccion

http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos

Sunday, October 11, 2009

Algo sobre el Lenguaje Ruby (II)

En esta segunda entrega, veremos algo sobre estilos de código en Ruby, y luego algunos ejemplos de programación de objetos básicos en Ruby, basándonos en algunos TPs de la materia Programación III.

Estilos de código:

Hay varias cuestiones a tener en cuenta a la hora de programar en objetos en Ruby. Como en Smalltalk, se sigue la convención de que la clases se definen con mayúscula en la primer letra, las instancias y sus variables con minúscula, así como los métodos.

Las constantes se escriben todo en mayúscula.

La diferencia principal con el estilo “smalltalkero” es que los nombres con mas de una palabra se escriben de manera diferente: Mientras que en Smalltalk una variable o métodos se escribe estoEsElNombreClasicoDeUnaVariableSmalltalk, Ruby tiene por convención que sea esto_es_un_nombre_tipico_en_ruby.

Las convenciones son importantes, dado que todos los métodos, funciones, módulos, clases y demás cosas de las librerías se escriben siguiendo estas reglas, con lo cual, no adaptarnos a ellas puede traer problemas.

Un ultimo detalle es que algunos nombres de métodos en Ruby terminan con el signo '?'. Cada vez que un método termina con el signo de interrogación significa que retorna siempre verdadero o falso. En el caso que el método termine con '!', implica que el objeto al cual le enviamos el mensaje sera modificado. Es como una advertencia de alerta, por decirlo de alguna manera.

Implementaciones y pruebas referidas al TP 2 de Programación III en Ruby

Abrimos nuestro editor de textos preferido y copiamos lo siguiente:

class Persona

# Definimos getters
def get_nombre()
return @nombre
end

def get_apellido()
return @apellido
end

def get_dni()
return @dni
end

def get_padre()
return @padre
end

def get_madre()
return @madre
end

# Definimos setters
def set_nombre(nombre)
@nombre = nombre
end

def set_apellido(apellido)
@apellido = apellido
end

def set_dni(dni)
@dni = dni
end

def set_padre(padre)
@padre = padre
end

def set_madre(madre)
@madre = madre
end

end


Observemos que los getters y los setters son similares, y solo cambia la variable a la que esta definida. Existen métodos dentro de Ruby que permiten automatizar la creacion de setters y getters. Ellos son:

attr_reader: Para creación de getters
attr_writer: Para creación de setters
attr_accessor: Para creación de getters y setters

El código anteriormente presentado se reduciría al siguiente

class Persona
attr_accessor :nombre, :apellido, :dni, :padre, :madre
end

Con esta ultima implementación abrimos un interprete interactivo (irb) y hacemos algunas pruebas(En negrita las lineas ingresadas por el usuario):

$ irb
irb(main):001:0> require 'Personas_con_accesors'

=> true
irb(main):002:0> p = Persona.new()

=> #
irb(main):005:0> p.methods

=> ["inspect", "tap", "clone", "public_methods", "__send__", "object_id", "instance_variable_defined?", "apellido", "equal?", "freeze", "extend", "apellido=", "send", "methods", "hash", "dup", "to_enum", "instance_variables", "dni", "eql?", "instance_eval", "id", "dni=", "singleton_methods", "taint", "enum_for", "frozen?", "instance_variable_get", "instance_of?", "padre", "display", "to_a", "method", "type", "padre=", "instance_exec", "protected_methods", "==", "===", "instance_variable_set", "kind_of?", "madre", "respond_to?", "to_s", "class", "madre=", "private_methods", "=~", "tainted?", "__id__", "nombre", "untaint", "nil?", "is_a?", "nombre="]
irb(main):010:0> p.public_methods(false)

=> ["padre", "madre=", "nombre=", "dni", "padre=", "apellido", "dni=", "madre", "nombre", "apellido="]
irb(main):011:0> p.nombre="Ana"

=> "Ana"
irb(main):012:0> p.apellido="Garcia"

=> "Garcia"
irb(main):013:0> p.dni=33221256

=> 33221256
irb(main):014:0> p.nombre

=> "Ana"
irb(main):015:0> p2 = Persona.new

=> #
irb(main):016:0> p2.nombre="Jose"

=> "Jose"
irb(main):017:0> p2.apellido="Taringa"

=> "Taringa"
irb(main):018:0> p.padre=p2

=> #
irb(main):019:0> p.inspect

=> "#>"
irb(main):020:0> exit

$

Hemos visto hasta aquí la implementación de métodos y clases en sus formas básicas.

Pasemos a definir ahora un método para inicializar el objeto. Sabemos que el método para inicializar un objeto es una función que asigna a las variables de instancia los valores adecuados para que el objeto funcione en el sistema sin problemas. Como todas las variables sin valor se inician con nil, sabemos que no es conveniente para operar, siempre es conveniente tener un mensaje de inicialización de los objetos.

class Persona

attr_accessor :nombre, :apellido, :dni, :padre, :madre

def initialize(nombre, apellido, dni, padre="", madre="")
@nombre = nombre
@apellido = apellido
@dni = dni
@padre = padre
@madre = madre
end
end

Un dato interesante es que el método initialize es automáticamente invocado cuando le enviamos el mensaje new a la clase. No debemos preocuparnos por la inicialización de los objetos una vez que implementamos el método de inicialización.

Si observamos la cabecera del método de inicialización

def initialize(nombre, apellido, dni, padre="", madre="")

vemos que padre y madre se asignan con cadenas vacías. Lo que estamos haciendo es asignar valores por defecto a esas dos variables. O sea, nombre, apellido y dni son obligatorios para crear un objeto de la clase Persona, pero padre y madre son opcionales.

$ irb
irb(main):001:0> require 'Personas_con_accesors_y_mensaje_de_inicializacion'

=> true
irb(main):002:0> p = Persona.new("Jose", "Taringa", 23456876)

=> #
irb(main):003:0> p.padre

=> ""
irb(main):004:0> p2 = Persona.new("Pedro", "Taringa", 14678384)

=> #
irb(main):005:0> p.padre= p2

=> #
irb(main):006:0> p.inspect()

=> "#>"
irb(main):007:0> exit

$

Por ultimo, observemos que la sentencia require se utiliza para importar módulos. Lo que va entre comillas simples es el nombre del archivo que desea importarse. Si encuentra un archivo con ese nombre en la carpeta local, lo carga (como en nuestro ejemplo), sino, busca en la librería estandar de Ruby. Si tampoco lo encuentra allí, lanza un error.

Recursos:

http://www.ruby-lang.org/es/documentation/quickstart/

http://tryruby.hobix.com/

Saturday, October 3, 2009

Algo sobre el Lenguaje Ruby (I)

Buenas a todos. A invitación de Alejandro, este es el primero de una serie de posts acerca de Ruby, un lenguaje interpretado y orientado a objetos que por varios motivos a cobrado renombre y se extendió su uso en el ultimo tiempo. Veamos de que se trata.

¿Que es Ruby?

Ruby es un lenguaje de alto nivel, interpretado, dinámico, de código abierto y orientado a objetos. Su autor, Yukihiro Matsumoto (Matz), se inspiro en lenguajes como Python, Perl, Lisp, Smalltalk y Eiffel, entre otros.

El lenguaje en si es un programa interprete y gran numero de bibliotecas que proveen todo tipo de funcionalidades aptas para ser usadas en desarrollo de sistemas profesionales, educativos y académicos.

Características:

  • Alto nivel: "Los lenguajes de programación de alto nivel se caracterizan por expresar los algoritmos de una manera adecuada a la capacidad cognitiva humana, en lugar de a la capacidad ejecutora de las máquinas"[1].

  • Interpretado: No es necesario un proceso de compilación. Existe un programa, llamado intérprete, el cual es invocado en el momento que se desea ejecutar un programa. Este intérprete va ejecutando cada una de las acciones programadas mediante un proceso de conversión de código Ruby a código entendible por la maquina. El proceso de interpretación se realiza a medida que se necesita ejecutar una instrucción.

  • Dinámico: Las variables en un mismo programa pueden tomar valores de diferentes tipos de datos. Si bien no es obligatorio, la gran mayoría de los lenguajes dinámicos son interpretados.

  • Software libre y código abierto: El interprete y las bibliotecas tienen una doble licencia: GPL y Ruby (Software libre y código abierto respectivamente).

  • Orientado a Objetos: Paradigma de la programación que usa estructuras conocidas como objetos, y las vincula de una manera especifica (mensajes) para establecer la construcción de un programa o sistema. La unidad mínima del paradigma es el “Objeto”, una entidad que reúne conocimiento y comportamiento. Un objeto provee un grupo de mensajes al “resto del mundo” (otros objetos) para interactuar con ellos. Los objetos se envían mensajes entre si, y dichos mensajes se vinculan con métodos específicos que implican una secuencia de acciones a realizar.

  • Multiparadigma: Se entiende con esta denominación, a toda una gama de lenguajes que permiten programar en un mismo momento en varios paradigmas de programación. Por ejemplo, usar estructuras de iteración como el while, y en otras partes del mismo programa usar objetos. Ruby es uno de los lenguajes que permite programar combinadamente en varios paradigmas de programación.

Posee una sintaxis muy similar a Python y Perl, con lo cual comenzar a trabajar con el lenguaje es muy intuitivo, pero también sirve para desarrollos avanzados.

Por ejemplo, el primer programa que podemos hacer con Ruby:

puts “hola mundo”

Si escribimos el texto anterior en un archivo, lo guardamos como “hola.rb” y desde una terminal escribimos:

$ ruby hola.rb
hola mundo
$

Como prerrequisito, se debe tener instalado el interprete Ruby y las bibliotecas del Lenguaje, el cual se descarga gratuitamente desde internet y esta soportado en diversas plataformas de desarrollo (Windows, Linux, etc...)

El interprete interactivo vs. el Workspace

Si se esta acostumbrado a trabajar en Smalltalk y su workspace, a la hora de desarrollar con Ruby se extrañara un lugar donde hacer pruebas paso a paso de un grupo de sentencias. Una solución a esto es el interprete interactivo llamado irb, el cual nos provee una interfaz para ejecutar código Ruby en el momento, y nos provee un entorno de trabajo temporal para realizar pruebas y pequeñas tareas.

Las diferencias entre el interprete interactivo y el workspace, es que en el primer caso se usa para tests y desarrollos puntuales menores, en cambio, el segundo se concibe como el ambiente donde una vez que todo funcione, quedara la aplicación definitiva. El workspace tiene además herramientas de debugging y toda una gama de aplicaciones que lo hace mucho mas completo. El interprete interactivo, por el contrario, provee por si mismo contadas instrucciones propias y facilita el ingreso de código y su evaluación.

Una sesión en el interprete interactivo[2]:

$ irb
irb(main):001:0> "Hola mundo"
=> "Hola mundo"
irb(main):002:0> puts "Hola mundo"
Hola mundo
=> nil
irb(main):003:0> 5 + 4
=> 9
irb(main):004:0> 5 * 5
=> 25
irb(main):005:0> Math.sqrt(9)
=> 3.0
irb(main):006:0> a = 3 ** 2
=> 9
irb(main):007:0> b = 4 ** 2
=> 16
irb(main):008:0> Math.sqrt(a+b)
=> 5.0
irb(main):009:0> Math.methods
=> ["private_class_method", "inspect", "name", "tap", "sinh", "clone", "public_methods", "__send__", "object_id", "method_defined?", "instance_variable_defined?", "exp", "equal?", "freeze", "acos", "extend", "ldexp", "send", "const_defined?", "methods", "instance_method", "ancestors", "module_eval", "hash", "tanh", "dup", "autoload?", "instance_variables", "to_enum", "atan2", "instance_methods", "public_method_defined?", "log", "class_variable_defined?", "eql?", "constants", "asin", "id", "instance_eval", "hypot", "singleton_methods", "module_exec", "const_missing", "acosh", "taint", "instance_variable_get", "frozen?", "enum_for", "private_method_defined?", "cos", "public_instance_methods", "display", "instance_of?", "log10", "method", "to_a", "included_modules", "atan", "const_get", "instance_exec", "type", "erf", "<", "protected_methods", "<=>", "class_eval", "==", "asinh", "class_variables", ">", "===", "instance_variable_set", "sin", "protected_instance_methods", "protected_method_defined?", "respond_to?", "kind_of?", "sqrt", ">=", "public_class_method", "to_s", "<=", "cosh", "const_set", "class", "erfc", "private_methods", "=~", "tainted?", "__id__", "class_exec", "autoload", "atanh", "untaint", "nil?", "private_instance_methods", "tan", "include?", "is_a?", "frexp"] irb(main):010:0> quit
$

El interprete es una gran herramienta para los desarrolladores, dado que permite ejecutar porciones de código mostrando sus resultados. Al igual que en Python, el uso del interprete interactivo a permitido a programadores elevar de manera notable la productividad, pues se realizan depuraciones parciales de código a medida que se tienen dudas sobre el mismo. Esto reduce la fase de depuración final que ocurría en los desarrollos con lenguajes estáticos.

Notas al pie:

[1]: http://es.wikipedia.org/wiki/Lenguaje_de_alto_nivel
[2]: Ejemplo extraído en su mayoría de http://www.ruby-lang.org/es/documentation/quickstart/