jueves, 31 de enero de 2013

Experiencia de Usuario (UX)

Según la wikipedia, la Experiencia de Usuario (UX por sus siglas en ingles); se define como:

... "el conjunto de factores y elementos relativos a la interacción del usuario, con un entorno o dispositivo concretos, cuyo resultado es la generación de una percepción positiva o negativa de dicho servicio, producto o dispositivo.

La experiencia de usuario depende no sólo de los factores relativos al diseño (hardware, software, usabilidad, diseño de interacción, accesibilidad, diseño gráfico y visual, calidad de los contenidos, buscabilidad o encontrabilidad, utilidad, etc) sino además de aspectos relativos a las emociones, sentimientos, construcción y transmisión de la marca, confiabilidad del producto, etc".

Desde esta definición, se hace sencillo (mucho en realidad) de entender la importancia que este concepto debe tener para todo desarrollador. En este sentido, me permito compartir un articulo que ha llegado a mi correo y que nos reúne 21 libros gratuitos que hablan sobre el tema. Pueden consultar la lista acá.

martes, 1 de mayo de 2012

Editores CSS

Las hojas de estilos llegaron a la web y están para quedarse, la idea de la web semántica, unida a la flexibilidad que estas brindan tiene una recepción tal que ya son parte casi obligatoria en cualquier desarrollo web. Dada esta importancia y la difundida presencia, en el articulo de hoy, voy a analizar algunos editores web, con especial enfacis en su manejo de CSS.

Debo aclarar, que todas estas pruebas las realizo en base a mi trabajo en plataforma libre, así que el articulo se adapta a entornos operativos libres, no descarto que tenga posible utilidad para aquellos que están en otras plataformas, pero tampoco puedo afirmarlo...

Teoría Please !!!


CSS :

El termino forma parte del día a día de todos los desarrolladores que están en el mundo web, pero a ciencia cierta, que es una CSS ???, bien wikipedia nos dice que:




El nombre hojas de estilo en cascada viene del inglés Cascading Style Sheets, del que toma sus siglas. CSS es un lenguaje usado para definir la presentación de un documento estructurado escrito en HTML o XML2 (y por extensión en XHTML). El W3C (World Wide Web Consortium) es el encargado de formular la especificación de las hojas de estilo que servirán de estándar para los agentes de usuario o navegadores.


La idea que se encuentra detrás del desarrollo de CSS es separar la estructura de un documento de su presentación. La información de estilo puede ser adjuntada como un documento separado o en el mismo documento HTML. En este último caso podrían definirse estilos generales en la cabecera del documento o en cada etiqueta particular mediante el atributo "

CSS se ha creado en varios niveles y perfiles. Cada nivel de CSS se construye sobre el anterior  y en la actualidad ya van 4, los cuales -generalmente- van añadiendo funciones al previo; estos perfiles son, generalmente, parte de uno o varios niveles de de CSS definidos para un dispositivo o interfaz particular y en la actualidad los perfiles pueden usarse para dispositivos móviles, impresoras o televisiones.

El ultimo nivel de CSS disponible es CSS 3, el cual -en diferencia a CSS2- está dividida en varios documentos separados, llamados "módulos". En este nivel, cada módulo añade nuevas funcionalidades a las definidas en CSS2, de manera que se preservan las anteriores para mantener la compatibilidad.

Debido a la modularización del CSS3, diferentes módulos pueden encontrarse en diferentes estados de su desarrollo,para noviembre de 2011, hay alrededor de cincuenta módulos publicados, tres de ellos se convirtieron en recomendaciones oficiales de la W3C en 2011: "Selectores", "Espacios de nombres" y "Color", otros módulos, como "Fondos y colores", "Consultas de medios" o "Diseños multicolumna" están en fase de "candidatos", y considerados como razonablemente estables.

Al grano, los editores

Amaya :

Es una herramienta destinada a la creación y la edición directamente en la Web; es desarrollada por W3C (Los mismos creadores del estandar CSS) en base a la concepción de Internet como espacio para la colaboración, en vez del ambiente para la publicación unilateral. Originariamente la idea tras es software era crear un editor HTML + CSS, pero hoy en dia Amaya permite trabajar documentos XML, XHTML, MathML, SVG y SMIL.

Amaya es un proyecto Open Source, en el que cualquiera puede colaborar, esta escrito en C y esta disponible para Windows, Plataformas Unix y MacOS X. Cuenta con su propio canal IRC (#amaya) disponible en el servidor irc.w3c.org

Kompozer :



Su nombre original era  "Composer", era un editor de paginas desarrollado por Netscape pero abandonaron su desarrollo. A partir de ese proyecto surgió Nvu (software que debo admitir use hace tiempo), el cual que mejoró Composer, pero también tuvo un final como el de su predecesor; finalmente llego "Kompozer", que es básicamente una versión más estable de Nvu, y aunque no lleva un ritmo vertiginoso de desarrollo por lo menos ha recibido algunos trabajos.


Kompozer es un editor gráfico de HTML que te permite crear paginas web de forma sencilla sin demasiada dificultad. Tiene varias pestañas para poder editar la página, ver los elementos (tags) y scripts, editar directamente el código o previsualizar el resultado, también te permite editar varias páginas simultaneamente y sincronizar las versiones guardadas con la de tu servidor web FTP, de forma que se publiquen los archivos automaticamente. Otras cosas que incluye son validador de código HTML, editor CSS, soporte para complementos, posibilidad de insertar código PHP, etc... Ahora, aun con todo eso el programa no está pensado para profesionales, por lo que se puede quedar un poco pequeño. Por lo demás, merece la pena probarlo.

CSSED :

Es un software muy comentado en la Web, es un editor y validador pequeño -según sus desarrolladores- el cual se enfoque en tratar de hacer mas sencilla la tarea de editar CSS. Entre sus características destacan  el resaltado de sintaxis, inserción rápida de propiedades y valores para CSS y autocompletación basada en diálogos.

Lo interesante de este proyecto, es que aunque sus desarrolladores le llamen pequeño, no se limita exclusivamente a CSS, cuenta con cierto soporte para HTML, JavaScript, XML, Java, PHP, JSP, C, C++, Archivos de Configuración de Apache, Python, Perl, SQL, entre otros lenguajes; lo que lo hace un editor multiproposito.

Es un desarrollo Open Source, al cual le podemos agregar nuevas capacidades mediante plugins y scripts desarrollados en Python.

Aptana Studio:

Aptana Studio es un completísimo IDE basado en Eclipse; se orienta al desarrollo web y cuenta con numerosas funciones que facilitan el desarrollo de un sitio web. Ademas de eso cuenta con un gran número de plugins (gratuitos), los cuales proporcionan numerosas funciones más. 

Gracias a los plugins es posible hacer que Aptana Studio trabaje con PHP, Jaxer, Ruby on Rails, Python, Adobe AIR, Apple iPhone y Nokia S60.

Entre las funciones de Aptana Studio destacan: 
  • Resalte de sintaxis.
  • Herramientas para trabajar con bases de datos.
  • Librerías para Ajax.
  • Conexión FTP, SFTP, FTPS y Aptana Cloud.
  • Compatibilidad con las extensiones de Eclipse.
Aptana Studio es gratuito, libre y multiplataforma. Es posible instalarlo en Linux, Windows o Mac y para hacernos con el basta con ir a la página oficial y descargarlo.

Quanta Plus:


Quanta Plus tiene tanto un editor de código (Source editor) como un editor gráfico (VPL Editor) y permite usar ambos editores a la vez, para ver previsualizaciones del resultado. Tiene las barras de herramientas separadas según su función: Standard con los formatos de texto, Style con opciones CSS, Tables, Lists, Forms para crear formularios y Other.

Además incluye integrado otras aplicaciones como KImageMapEditor para editar HTML image maps, Kompare para comparar las diferencias entre dos archivos, Verificador de enlaces, scripts y Cervisia para manejar CVS.

Finalmente, si quieren ir mas allá con alguna de estas aplicaciones, en esta entrada de mi blog linux comento como instalarlas... Que las disfruten !!!

lunes, 30 de abril de 2012

Estructuras de Decisión

Normalmente, cuando se escribe codigo de manera secuencial llegara el momento en el deberemos dividir la ejecución en nuestro programa, algo así como si pasa "a" sigo este camino, pero si pasa "b" entonces sigo este otro camino diferente.

Para permitir ese tipo de cosas, los lenguajes de programación cuentan con una serie de estructuras llamadas estructuras de decisión, y basicamente lo que permiten es vifurcar la ejecución del código haciendo uso de una condicional.

Según wikipedia estas estructuras permiten:

La estructura selectiva permite que la ejecución del programa se bifurque a una instrucción (o conjunto) u otra/s, según un criterio o condición lógica establecida, sólo uno de los caminos en la bifurcación será el tomado para ejecutarse.

Estructura de decisión Básica:

Las estructuras de decisión básicas, evalúan simplemente si se cumple una condición... Si la condición se cumple ejecutan una o mas instrucciones y continúan con normalidad, así:

si A > B entonces
  escribir "a mayor que b"
fin si

Estructuras de decisión Anidada:

Es una forma mas compleja, en ella se evalúan una serie de condiciones de forma seguida para asi poder determinar un curso de acciones... Así:

si A > B entonces
     escribir "a mayor que b"
de lo contrario
      escribir "a no es mayor que b"
fin si

Alternativamente, es posible escribir una suerte de estructura anidada mas compleja empleando "de lo contrario si" veamos como continuando el ejemplo anterior...

Si comparamos 2 números podemos obtener 3 tipos diferentes de resultados:
  • A es mayor que B,
  • B es mayor que A (alternativamente se puede decir a no es mayor que b),
  • A y B son iguales.
Para ese caso, el planteamiento de la estructura quedaría así:

si A > B entonces
     escribir "a mayor que b"
de lo contrario si B > A
      escribir "b es mayor que a"
de lo contrario
      escribir "a y b son iguales"
fin si

En la mayoría de los lenguajes, estas estructuras se construyen haciendo uso de las palabras reservadas  IF, THEN, ELSE, y END IF aunque esto puede variar.

  • IF señala el comienzo de la instrucción condicional, y se espera que después siga la condición lógica de control de la instrucción.
  • THEN señala el fin de la condición, y después estará la instrucción o conjunto de instrucciones a ejecutar si la condición es verdadera.
  • ELSE es opcional, se emplea para indicar que instrucciones se ejecutaran en caso de que la condición expuesta en IF sea falsa.
  • ELSEIF también es opcional, y se espera que luego de usarla siga una condición lógica; se emplea para indicar que instrucciones se ejecutaran en caso de que la condición expuesta en el IF sea falsa y se cumpla la condicion expuesta luego del ELSEIF.
  • END IF indica el final de la estructura, luego de ésta el programa seguirá su curso.

Estructuras Repetitivas

Una situación común en la actividad de un desarrollador, es la necesidad de hacer que una parte (o la totalidad) de la aplicación se repita, esta nececidad, por lo general eviene en base a una condición que actúa como bandera, la interacción con un usuario, o la ocurrencia de un suceso.

Ahora bien, incluir estos segmentos de codigos tantas veces como sea necesario representa un problema ya que (por ejemplo) que ocurre si debemos ejecutar unas mil veces, o que pasaria si debemos ejecutar hasta que el usuario decida ????. Bueno, para lidiar con estos problemas, existen estructuras de programación llamadas Bucles.

La wikipedia define un bucle como :

Un bucle o ciclo, en programación, es una sentencia que se realiza repetidas veces a un trozo aislado de código, hasta que la condición asignada a dicho bucle deje de cumplirse.
Generalmente,un bucle es utilizado para hacer una acción repetida sin tener que escribir varias veces el mismo código, lo que ahorra tiempo, deja el código más claro y facilita su modificación en el futuro.
El bucle y los condicionales representan la base de la programación estructurada. Es una evolución del código ensamblador, donde la única posibilidad de iterar un código era establecer una sentencia jump (que en los lenguajes de programación fue sustituida por el "ir a" o GOTO).

Existen diferentes tipos de Bucles, y cada lenguaje determina la estructura o formatos para utilizarlos, ahora bien se puede en un nivel de abstranccion mas bajo decir que los bucles mas usados son Mientras, Hasta, y Hacer (Repetir, Hacer).


La realidad es que cada lenguajes de programación emplean sus propias estructuras o formatos para la implementación de un bucle (la estructura es intrínseca de cada lenguaje) pero se pueden resumir a:

Mientras:


Es una estructura cuyo propósito es repetir un bloque de código mientras una condición se mantenga verdadera.

En Diagrama de Flujo queda así:

Mientras tanto, en Pseudocódigo seria algo así:

Mientras Condición hacer
       Bloque de Instrucciones
Fin Mientras

Ahora bien, que es la condición..... Wikipedia nos dice que:

La condición ha de ser una sentencia que devuelva un valor booleano, y esta puede ser el valor booleano en sí, verdadero(true) si la condición se cumple, o falso si esta no se cumple(false). También puede contener el nombre de una variable booleana, y el valor de la expresión dependerá de su contenido. Se debe tener en cuenta que además de las variables también puede haber llamadas a funciones que devuelvan un valor.

Enredado ?, la verdad no... La condición es otra cosa mas que "Aquello que se debe cumplir" para que se ejecute el bloque siguiente...

Condiciones Booleanas: son un tipo de condicion en el que se evalua una expresión para determinar si es verdadera o falsa, en terminos sencillos son estructuras similares a "Si hay error" "Si se ejecuta" "Si pasa que..."

Condiciones Comparativas: son la forma más obvia -tal vez-, y la más usada -sin duda-, para generar condiciones, estas se basan en el uso de los operandos igual, diferente, menor o igual, mayor o igual, menor y mayor para generar comparaciones entre dos o mas variables.

Hasta:

La wikipedia nos dice que esta estructura es:

es una estructura de control en la que se puede indicar el número minimo de iteraciones. Está disponible en casi todos los lenguajes de programación imperativos.

En palabras sencillas esto seria como decir, "repite hasta que ocurra tal condición",  y la condición es de tipo Comparativa.

En pseudo condigo seria:

Para i = x hasta n incrementos de s hacer
       Instrucciones
Fin Para

Donde:

  • i = es la variable bandera.
  • x = es el valor inicial de la variable bandera.
  • n = es el valor maximo o final que puede tomar la variable bandera.
  • s = la forma como ira cambiando (aumentando o decreciendo) la variable bandera.
Complicado... veamos mejor un ejemplo en el que planteamos un bucle para que se ejecute 10 veces, en el que la bariable "i" es la bandera y esta aumenta de 1 en 1:

para i = 0 hasta i <= 9, con i aumentando 1
       Instrucciones
fin para

Hay que aclarar, que existen diferentes formas de plantear el incremento o decremento de la variable según el lenguaje de programación que se este usando.


Repetir:

La wikipedia lo define como:

El bucle repetir comprueba la condición de finalización al final del cuerpo del bucle, y si ésta es cierta continua con el resto del programa, a veces esto resulta más adecuado.

En general, podemos decir que "repetir" es una suerte de bucle mientras -y no estaríamos del todo mal, el detalle esta que en "repetir" se evalua la condición al final de la primera interación, entonces el bloque de instrucciones se ejecuta al menos una vez.

Esta forma de estructura es ampliamente útil, para programas lineales que terminan con el típico Prompt de "desea continuar", "continuar" , "ejecutar nuevamente"...

En diagrama de flujo esta estructura queda así:

Y en Pseudocódigo seria:

Repetir
       Instrucciones
Hasta que Condición

Como dije anteriormente, suele ser muy útil en programación lineal para ejecutar el programa completo una primera vez y luego preguntar a el usuario si desea continuar, también es muy útil para realizar la validación de datos, ya que si no se cumple la condición se mantiene solicitando el dato y no se interrumpe el programa por un error.

Hacer:

Básicamente es materia de estructura es igual al anterior, ambas se diferencian es la evaluación de la condición en repita es "hasta condición" y en hacer es "mientras condición". Es decir en el caso de un "hacer" el bucle se continua ejecutando luego de la primera interacción si la condición se cumple; pero en un "repita" si la condición es verdadera se termina el ciclo.

Bucle Infinito: 

Según wikipedia es:


en programación es aquel ciclo que se repite de forma indefinida ya que su condición para finalizar nunca se cumple.
Por definición un bucle debe contener condiciones que establezcan cuándo empieza y cuándo acaba, de manera que, mientras las condiciones se cumplan, ejecute una secuencia de código de manera repetitiva. En el caso de ciclo infinito, como la condición de finalización no se alcanza, el bucle sigue ejecutando el segmento de código indefinidamente.

En general podemos decir que es la pesadilla de todo programador y la forma mas sencilla de colapsar un computador, un bucle infinito es aquel en la que no se logra la salida y el programa queda en un ciclo sin fin.


lunes, 2 de mayo de 2011

Jugando con las APIS (GAE)

Continuando con el tema de Gae, ahora voy a comentar el ejemplo de uso de las API's, nuevamente se trabajara con el archivo main.py y el archivo app.yaml queda tal cual como estataba.

Al Grano:


main.py


#Realizamos las importaciones correspondientes:

#importamos la api para los usuarios:
from google.appengine.api import users
#importamos webApp
from google.appengine.ext import webapp
#importamos la instancia de solicitudes
from google.appengine.ext.webapp.util import run_wsgi_app

#Definimos la Clase principal:

class MainPage(webapp.RequestHandler):
  def get(self):
    #Determinamos el Valor del usuario
    user = users.get_current_user()

    if user: #Si hay una sesión Iniciada
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write('Hello, ' + user.nickname())
    else: #Si no hay sesión Iniciada
      self.redirect(users.create_login_url(self.request.uri))      
      #Redirijimos a la pagina de creacion de Login (API)
#Deestar corriendo en AppEngine, se redijije a la pag login de Google

#Instanciamos el manejador de la aplicacion
application = webapp.WSGIApplication(
                                     [('/', MainPage)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
Por el contrario, el archivo app.yaml queda igual:


app.yaml


application: holamundo
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: main.py

Google App Engine

Como parte de un nuevo proyecto de trabajo, me he visto en la necesidad de iniciar estudios en la plataforma GAE de Google y dado que ya voy entendiendo un par de cosas, me permitiré ir comentando mis avances y desarrollos por acá, para mantener un registro y compartir la experiencia.

Lo primero que debo decir, es que a posterior dejare por acá un Post de Instrucciones para la Instalación de todo lo necesario. Lo segundo que debo decir, es que por ahora y para continuar un poco lo que creo es la linea de trabajo de la empresa que contrata mis servicios, todo lo que hago lo estoy probando en la plataforma Windows, en su version 7. 

Primeros Pasos:

Bien, como no es mi intención documentar lo que es GAE, iré directo al grano con los primeros Ejemplos de Códigos que he realizados (Estos códigos son los mismos del tutorial GAE que estoy siguiendo, pero con ligeras modificaciones mías).

GAE + WebApp Ejemplo 1:

Archivo main.py


#realizo las invocaciones necesarias:

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

#defino la clase que procesara las solicitudes
class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hola, webapp mundo!')

#defino el manejador de solicitudes, este se encargara de pasar la solicitud a la clase procesadora
#dependiendo de en que categoría este la solicitud entrante

application = webapp.WSGIApplication(
                                     [('/', MainPage)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

Ahora vemos el Archivo de control de la aplicación:


Archivo app.yaml


application: holamundo #nombre de la aplicacion
version: 1 #version de la aplicacion
runtime: python #Rutines
api_version: 1 #Version de las Apis

handlers: #Manejador de solicitudes,
- url: /.* #Para todas las Solicitudes URL usar main.py
  script: main.py
* los comentarios no deben colocarse, el archivo no los acepta


Esta sencilla aplicaciones no es mas que un hola mundo que emplea webApp y sus tres partes básicas:

  • una o varias clases RequestHandler que procesan solicitudes y generan respuestas,
  • una instancia de WSGIApplication que dirige las solicitudes entrantes a los controladores en función de su URL,
  • una rutina principal que ejecuta WSGIApplication con un adaptador de CGI.

martes, 20 de abril de 2010

Desarrollo Incremental Orientado a Python


Para trabajar con programas cada vez más complejos, una técnica muy útil y sugerida es la del desarrollo incremental, el objetivo de esta técnica es el de evitar largas sesiones de depuración, al añadir y probar solamente una pequeña cantidad de código a la vez. 

Siempre es mas sencillo ver las cosas con un ejemplo asi que:

Supongamos que quieres hallar la distancia entre dos puntos, determinada por las coordenadas (x1, y1) y (x2, y2) en python. 

Lo primero que debes saber es que según el teorema de Pitágoras, la distancia es:

distancia =

(x2 - x1)2 + (y2 - y1)2

Ya a partir de eso, lo que debemos tener en cuenta es qué aspecto debería tener una función de distancia en Python. En otras palabras, ¿cuáles son las entradas (parámentros) y cuál es el resultado (valor de retorno)? 

En este caso, los dos puntos son las entradas, que podemos representar usando cuatro parámetros. El valor de retorno es la distancia, que es un valor en coma flotante. 

A sabiendas de esto podemos escribir un esbozo de la función:

>>> def distancia(x1, y1, x2, y2):
....       return 0.0



Evidentemente, esta versión de la función no calcula distancias y siempre da cero, sin embargo, es sintácticamente correcta y funcionará, lo que significa que podemos probarla antes de hacerla más complicada. 

Para probar la nueva función, la llamamos con valores de muestra:


>>> distancia(1, 2, 4, 6)
0.0



Elegimos estos valores para que la distancia horizontal sea igual a 3 y la vertical sea igual a 4, de esta manera, el resultado es 5 (la hipotenusa de un triángulo cuyos lados miden 3, 4 y 5) 

Nota: Cuando se prueba una función, es útil saber el resultado correcto. 

Hasta el momento, hemos confirmado que la función es sintácticamente correcta y podemos empezar a escribir líneas de código. Después de cada cambio incremental, probamos la función nuevamente y si se produce un error en cualquier momento, sabemos dónde debe estar -en la última línea que añadimos-. 

Un primer paso lógico en el cálculo es hallar las restas x2 - x1 y y2 - y1. Almacenaremos esos valores en variables temporales denominadas dx y dy, y las presentaremos en pantalla. 

def distancia(x1, y1, x2, y2):
  dx = x2 - x1
  dy = y2 - y1
  print "dx es", dx
  print "dy es", dy
  return 0.0 



Si la función es correcta, los resultados deberían ser 3 y 4. Si es así, sabemos que la función tiene los parámetros adecuados y que ha realizado el primer cálculo correctamente. En caso contrario, solo hay que comprobar algunas líneas. 

A continuación, calcularemos la suma de los cuadrados de dx y dy

def distancia(x1, y1, x2, y2):
  dx = x2 - x1
  dy = y2 - y1
  dsquared = dx**2 + dy**2
  print "dsquared es: ", dsquared
  return 0.0


Es importante destacar que se retiraron las instrucciones print que escritas en el paso anterior ya que solo eran andamio -Los códigos como éste se llaman de andamio porque ayudan a construir el programa pero no forman parte del producto final. 

De nuevo, lo que hay que hacer es ejecutar el programa y comprobar el resultado (que debería ser 25 en estos momentos). 

Por último, si ha importado el módulo de matemáticas, ya se puede usar la función sqrt para hacer el cálculo y obtener el resultado: 

def distancia(x1, y1, x2, y2):
  dx = x2 - x1
  dy = y2 - y1
  dsquared = dx**2 + dy**2
  result = math.sqrt(dsquared)
  return result 



Si funciona de manera adecuada, lo has logrado. De lo contrario, puede que quieras presentar en pantalla el valor de resultado antes de la instrucción de retorno. 

De esta forma, cuando se inicia, solo se deben añadir unas pocas lineas a la vez y a medida que se adquiera más experiencia, se podrá escribir y depurar fragmentos mayores. 

De cualquier manera, el proceso de desarrollo incremental puede ahorrar un montón de tiempo de depuración y es una buena constumbre....

Los aspectos clave de este proceso son:
  1. Iniciar con un programa que ya funcione y hacer pequeños cambios incrementales. En cualquier momento, si hay algún error se sabe exactamente dónde está.
  2. Utiliza variables temporales para mantener valores intermedios para que puedas obtenerlos y comprobarlos.
  3. Una vez que el programa esté funcionando, puede que quieras quitar algo del andamiaje o consolidar las múltiples instrucciones en expresiones compuestas, pero sólo si esto no hace que el programa sea más difícil de leer.