Jorge Fernández (Planasa). INSPIRING SESSION. La anticipación y la I+D+i en l...
Cesnavarra 2008-boletín 7
1. Título Temas de Julio
Texto Como estamos en período post-sanferminero, las cosas que uno
pensaba hacer “antes de” se convierten en las que hay que
hacer porque nada funciona como debiera “después de”. Así que
este mes este artículo tratará sobre un par de temas con lo que
he tenido que lidiar tras las fiestas. Pobre de mí…
Problemas con Hyper-V en Windows Server2008 de Mayo
Recientemente hemos tenido que "padecer" unos problemas en
nuestros servidores Windows 2008, así como en algunos
equipos Windows Vista, causados por nuestro interés en
experimentar. A finales de Mayo o principios de Junio de 2008,
las versiones de evaluación de los distintos Sistemas
Operativos de Microsoft dejaron de ser utilizables, y para que
eso se notara reaccionaron de una manera un tanto extrema:
comenzaron a generar crashes, nuestros queridos "pantallazos
azules" cada cierto tiempo y de manera aleatoria.
Esto obligaba a un reinicio de las máquinas con estas versiones
de evaluación instaladas y si no disponemos de copia de lo que
estábamos haciendo… ¡adiós, muy buenas! Lógicamente hay
que admitir que al tratarse de versiones de evaluación esto es
normal y ya sabíamos que podía pasar. Además, Microsoft por
lo menos nos concede unos "períodos de gracia" durante los
cuales nuestros servidores y equipos funcionan y que podemos
emplear para extraer la información importante que tuviéramos
en ellos.
Una vez detectada la fuente de nuestros males, procedemos a
instalar las versiones correctas (y completas) de los sistemas
operativos, sin problemas. En ambos casos, y siempre que
dispongamos de espacio en nuestro disco duro, el instalador
creará una carpeta llamada “Windows.old” donde copiará el
contenido de nuestra instalación anterior que tuviéramos en las
carpetas “Archivos de programa”, “Usuarios” y “Windows”.
Normalmente lo que más nos interesará es el contenido de la
carpeta “Usuarios”, ya que en ella tendremos nuestros
Documentos, Descargas, Imágenes, Música, etc. que podremos
mover sin peligro a la carpeta que ha creado la nueva
instalación y casi todo volverá a ser como antes (casi todo,
porque deberemos reinstalar uno por uno los programas que
utilicemos, entre otras tareas).
Pero en nuestro caso existía una nueva “trampa”: la instalación
de Windows Server 2008 se realizó con la versión de Mayo, la
cual incluye el servicio Hyper-V versión 6.0.6001.18016 pero
en nuestra anterior versión empleábamos la
versión 6.0.6001.17101. Un ligero cambio de números… pero
un cambio que impide a nuestras antiguas máquinas virtuales
funcionar correctamente: al arrancar cualquiera de nuestras
máquinas virtuales se lanzaba el asistente de hardware nuevo
encontrado:
2. Y como el hardware virtual no está configurado correctamente,
el resultado es que la instalación es mala.
Como resultará habitual a aquellos que ya se hayan "peleado"
con las máquinas virtuales de Microsoft, a continuación
deberemos insertar el "Integration Services Setup Disk",
mediante el menú "Acción". Este lanzará el ejecutable que
pretende llevar a cabo la instalación, como se ve a
continuación:
3. Normalmente todo irá bien y se actualizará correctamente:
Para terminar, reiniciamos y todo estará listo a falta de unas
comprobaciones de IP y dominio. Pero si nuestro sistema
virtualizado dispone de alguna actualización o versión de los
drivers de VM que no gusta a nuestro instalador, nos devolverá
un mensaje de error tan poco explícito como "Error: Error
grave durante la instalación." Y nada más.
4. Para solucionarlo, en vez de ejecutar el programa “Setup.exe”
del “Integration Services Setup disk” tendremos que lanzar un
ejecutable del mismo disco pero un poco más oculto: se trata
del “update.exe” que reside en “supportx86en-usupdate”.
En
esta imagen se puede ver que también he ejecutado el
Administrador de tareas de Windows, pero sólo como soporte
desde el que lanzar el “explorer.exe” mediante su menú
“Archivo”, ya que los problemas con la instalación de los
5. Servicios de Integración para esta versión de Hyper-V impiden
el uso del ratón… algo bastante molesto, la verdad. Una vez
lanzado este update, tendremos que reiniciar nuestro servidor
virtual y todo habrá vuelto a funcionar normalmente, sobre
todo nuestro ratón y la tarjeta de red.
Finalmente sólo tendremos que corregir nuestra asignación de
IPs a la máquina virtual si no utilizamos asignación dinámica:
Recibiremos un aviso sobre si queremos asignar una dirección
6. IP diferente ya que la anteriormente asignada todavía está
asociada a un dispositivo anterior (aunque sea a un dispositivo
oculto porque ya no existe más en el sistema, la anterior tarjeta
de red virtualizada). Respondemos "No" para que confirme los
valores que acabamos de introducir y recuperaremos la
conectividad de nuestra máquina virtual.
Por último, sólo tendremos que volver a agregar el servidor al
dominio si era parte de alguno y listo (bueno, para 12 máquinas
se hace un poco pesado… pero funciona).
Microsoft Office OneNote 2007
Como nota final, quería hablar un poco sobre una herramienta
que he descubierto este mes, oculta en la licencia de Office
2007 completa y que tenía olvidada por ahí, llamada Microsoft
Office OneNote.
La idea de Microsoft es que este producto pueda sustituir al
montón de pequeños papelitos y notas que al final del día,
reuniones, llamadas, mails, etc. vamos recopilando y que luego
no hay manera de encontrar. OneNote es como un bloc de
notas con esteroides (se carga muy rápido) ya que nos
permite hacer mucho mucho más que el viejo y querido bloc:
- la capacidad de buscar información en todas nuestras
notas al estilo de la que ofrece Outlook 2007
- si eso por sí sólo ya es una bendición, añadiré que
OneNote nos permite emplear en cualquier nota
imágenes obtenidas desde cámaras o escaneadas (por
ejemplo, tarjetas de negocio…), archivos, recortes de
pantalla e incluso grabaciones de audio y video
- pero es que además su búsqueda nos permite buscar
en los contenidos de estos elementos también. Es
7. decir, podemos buscar en un archivo o imagen
importados.
OneNote ofrece por defecto una organización de notas dividida
en profesionales y personales, de manera que nos permite
emplear la aplicación para todo nuestro día a día. Dentro de
cada una establece unas sub-categorías como Notas de la
reunión, Viajes, Proyectos, etc. pero que son totalmente
modificables a nuestro gusto. Incorpora también una serie de
plantillas para nuevas notas, que se puede ampliar descargando
nuevas versiones desde la web de Microsoft Office. Además, la
gestión de las notas es totalmente automática, es decir que no
perderemos nunca lo que estamos editando. Además, mediante
un icono que sitúa en nuestra barra de tareas, tenemos acceso
inmediato a OneNote desde cualquier aplicación.
Por último, OneNote permite compartir notas con otros
usuarios, exportarlas a Word (donde por ejemplo acabaré de
editar este artículo tras haberlo esbozado en
OneNote), enviarlas como correo en Outlook a cualquier
destinatario, o publicarlas en nuestros sitios de SharePoint para
tener una versión colaborativa en Web. Y algunas otras
"extravagancias" como generar una Tarea de Outlook desde una
nota de OneNote automáticamente para sincronizarla con todos
nuestros dispositivos o asignar tiempo para hacer la tarea,
etiquetar nuestras notas con gran flexibilidad para poder
localizarlas luego más fácilmente
8. Y por ultimo y no menos importante, llevar a cabo sesiones de
trabajo compartidas entre varios miembros de un equipo sobre
una misma nota remotamente (una manera muy útil de llevar a
cabo "tormentas de ideas"), etc.Por eso
Por eso, podemos llamar a OneNote la "navaja suiza" de los
productos Office y recomiendo su utilización.
Categorí CES Microsoft
as
Tema Varios
Autor Rafael Flores Yoldi
Mes Julio
Año 2008
Boletín 07
Título Strings, StringBuffers… y Ropes.
Texto El manejo de las cadenas de caracteres es un aspecto fundamental en cualquier
lenguaje de programación. En este artículo daremos un breve repaso al manejo
de cadenas en Java y a las clases más importantes del lenguaje en este aspecto,
como son String, StringBuffer y StringBuilder.
Además, introduciremos una librería para el manejo avanzado de
9. cadenas: Ropes For Java.
La clase String
La clase String representa una cadena de caracteres con una característica
fundamental: es inmutable. Es decir, una vez creado un String no es posible
modificarlo. Los métodos que concatenan, reemplazan caracteres, etc.
devuelven otro objeto con las modificaciones realizadas.
Por ejemplo, tras ejecutar el siguiente código
String str = “La clase String es “;
str.concat(“inmutable”);
el valor de la variable str sigue siendo “La clase String es “.
En cambio, si hacemos
String str2 = str.concat(“inmutable”);
el nuevo String str2 ya contendrá la cadena completa, “La clase String
es inmutable“;
Por esta característica, la clase String no es adecuada si lo que se necesita es
realizar muchas modificaciones sobre el texto, ya que supone la creación de
muchos objetos temporales.
StringBuffer y StringBuilder
La clase StringBuffer es la variante mutable de String. Permite modificar su
contenido, concatenar cadenas, etc. de forma mucho más eficiente que la
claseString.
En la versión 5 de Java se incluyó la clase StringBuilder, que es igual que la
clase StringBuilder pero no sincronizada. Si el objeto no va a ser accedido por
más de un hilo simultáneamente, se recomienda el uso de StringBuilder ya que
al no ser sincronizado mejora ligeramente el rendimiento.
Al utilizar StringBuffer o StringBuilder, hay un aspecto que muchas veces no se
tiene en cuenta y que puede tener un impacto importante en el rendimiento: la
capacidad inicial.
Estos objetos almacenan un array de caracteres, que debe ser regenerado
cuando las operaciones hacen que se sobrepase la capacidad del array.
10. Inicializar el objeto a un valor adecuado puede mejorar el rendimiento global
del objeto. Por defecto se inicializan con una capacidad de 16 caracteres.
Cada vez que debe crecer, el nuevo tamaño es: 2 + 2*TamañoActual. Si el
tamaño no va a ser muy grande, la diferencia de rendimiento será inapreciable,
pero esta inicialización debe ser tenida en cuenta para el manejo de grandes
cadenas.
Cadenas en tiempo de compilación y en tiempo de
ejecución
Como curiosidad, cabe destacar la labor del compilador de Java en el manejo de
cadenas. A veces, para mejorar la legibilidad, se escribe código de este tipo:
String sql = "select col1, col2, col3 "+
"from table1 t1"+
"join table2 t2 on t1.col1 =
t2.col1"+
"join table3 t3 on t2.col3 =
t3.col2"+
"where t1.col1 = ? and t3.col3 =
?";
ó
StringBuffer sbsql = new StringBuffer("select
col1, col2, col3 ");
sbsql.append("from table1 t1");
sbsql.append("join table2 t2 on t1.col1 =
t2.col1");
sbsql.append(""join table3 t3 on t2.col3 =
t3.col2");
sbsql.append(""where t1.col1 = ? and t3.col3 =
?" );
String sql = sbsql.toString();
En este caso, la primera opción, con la suma de cadenas, ofrece mejor
rendimiento que la que utiliza el StringBuffer. La explicación está en el
compilador de Java, que realiza la suma de las cadenas en tiempo de
compilación.
Cuando la concatenación se realiza en tiempo de ejecución (concatenación de
variables, no de cadenas constantes), el rendimiento mejora
utilizandoStringBuffer como se ha comentado en el punto anterior. En este
caso, si se suman Strings, el compilador genera un StringBuffer para cada suma
de cadenas, penalizando el rendimiento frente a la utilización de un solo
objeto StringBuffer.
11. Las tres preguntas
Podemos resumir lo visto hasta ahora en tres preguntas que deberíamos
hacernos antes de escribir: String str = …..
¿Voy a modificar esta cadena?
Si la repuesta es 'no', o simplemente voy a concatenar cadenas constantes para
mejorar la legibilidad del código, usaré String.
Si voy a modificarla en función de la ejecución,
usaré StringBuffer o StringBuilder.
¿Va a acceder más de un hilo a mi cadena
simultáneamente?
Si es así, usaré un StringBuffer, que asegura la sincronización.
Si no es así, algo que sucederá en la mayor parte de los casos,
usaré StringBuilder, ya que es más eficiente.
¿Puedo estimar la máxima longitud de la cadena?
Si es así, inicializaré mi StringBuffer o StringBuilder con esa capacidad, para
evitar que el objeto deba regenerar su buffer interno cada vez que sobrepase su
capacidad.
Un paso más: Ropes
En aplicaciones donde el rendimiento es fundamental en el uso de cadenas,
puede ser conveniente el uso de otro tipo de estructuras de datos para su
representación y manejo.
Un ejemplo de ello es la estructura de datos denominada Rope.
Este concepto no es nuevo: se introdujo en un artículo de 1995(2) y representa
las cadenas con una estructura de árbol, de forma que mejora el rendimiento
en operaciones como la inserción y la concatenación de cadenas. El precio a
pagar por estas mejoras de rendimiento viene en forma de uso de memoria,
que es sensiblemente superior usando Ropes frente al uso de Strings o
StringBuffers.
Existe una implementación en Java de esta estructura, llamada Ropes For
Java(4). Como ejemplo, estas son algunas gráficas del rendimiento de esta
13. Referencias
1 - Performance improvement techniques in String and StringBuffer
2 - Ropes: an Alternative to Strings
3 - Ropes: Theory and practice
4 - Ropes For Java
Categorí CES OpenSouce/Java
as
Tema Desarrollo
Autor Miguel Bacaicoa
Mes Julio
Año 2008
Boletín 07
Título Herramientas de gestión de proyectos Open Source
Texto Hará unos meses, nos vimos en la tesitura de buscar una
14. herramienta de gestión de proyectos para el Centro Java y Open
Source.
Hasta el momento, habíamos estado trabajando con dotproject,
un sistema con bastante capacidad y funcionalidades. No
obstante, resultó ser una herramienta algo pesada en la creación
de planificaciones y tediosa en el mantenimiento día a día.
Buscábamos principalmente una herramienta que no solo
gestionase la parte de planificación, sino también la parte de
seguimiento posterior para mantener el control sobre el proyecto.
Además, deseábamos un entorno colaborativo, multi-usuario y
participativo entre nosotros y cualquier colaborador externo. Lo
cual, más que un requerimiento funcional supone un cambio
cultural, la parte más compleja.
Todo esto, en principio, decantaba la decisión por una opción on-
line en detrimento de una de escritorio. No obstante, decidimos
valorar también las de escritorio, no fuera que por empecinarnos
en unas funcionalidades descartásemos otras importantes.
A continuación describiré brevemente algunas de las
herramientas valoradas:
De escritorio:
GanttProject
Aplicación de escritorio muy extendida y útil que permite
planificar tareas y recursos sobre un diagrama Gantt. Se trata de
una herramienta similar a MS Project pero más sencilla lo cual
puede ser en algunos casos una ventaja. Otra característica
interesante es que funciona tanto en Linux como en Windows y
tiene diversos formatos de exportación e importación.
15. Planner
Aplicación de escritorio bastante extendida y algo más completa
a la anterior (a pesat de tener menos opciones de importación y
exportación), pero muy similar. En este caso está desarrollada
para Linux, aunque existe versión beta para Windows.
Open Workbench
Aplicación de escritorio muy completa. Al igual que las anteriores
permite gestionar tareas y recursos sobre un diagrama Gantt,
aunque también permite otros diagramas como Pert, camino
crítico y funcionalidades más avanzadas. Se vanagloria de ser
incluso mejor que MS Project.
TaskJuggler
Se trata de una herramienta de escritorio disponible tanto para
Windows como para Linux un tanto peculiar. Genera una serie de
informes bastante completos a partir de un fichero de texto. El
interfaz es bastante amigable, pero el hecho de andar editando
un fichero de texto que contiene la planificación no resulta muy
cómodo.
OpenProj
Otro programa de escritorio sustitutivo de MS Project y de
apariencia muy similar. Tiene versiones para Linux, Unix, Mac y
Windows y es compatible con ficheros MS Project y con todas sus
funcionalidades. No obstante, parece no estar indicado para
proyectos de grupo. En estos casos te ofrecen una versión on-
line (Project-ON-Demand) bajo demanda y de pago bastante
interesante.
Entorno web:
TeamSCOPE
Team Software for Collaborative Project Environments es una
herramienta web de colaboración. Desarrollado para funcionar
16. sobre Debian, fue creado por una universidad pero parece
haberse quedado bastante anticuado.
NetOffice
Herramienta web basada en PHP sobre MySQL para gestionar
proyectos, tareas, registros de tiempos, incidencias/errores,
diagramas de Gantt (aunque un poco escondidos), etc, similar
pero algo más agradable que dotProject. Tiene ciertos tintes de
herramienta de colaboración en grupo (groupware).
phpCollab
Herramienta web basada en PHP que ha sufrido un desarrollo
intermitente por lo que parece. Sirve tanto para la gestión de
tareas como para el seguimiento de incidencias/errores. Tiene un
aspecto similar a netOffice lo cual hace pensar que uno de los
dos proyectos deriva del otro. Quizás por esa razón, de elegir una
de las dos, sea más recomendable netOffice.
Achievo
Herramienta web PHP sobre MySQL para la gestión de proyectos,
tareas, recursos, registro de tiempos, agenda, generación de
informes, etc. Bastante completo, además parece incluir sección
presupuestaria.
XPlanner
Herramienta web Java sobre MySQL para la gestión de proyectos
mediante XP y Scrum. No obstante parece estancada en una
versión beta desde el 2006.
PPTS
Project Planning and Tracking System (PPTS) es una herramienta
Web para la gestión de proyectos con metodologías XP y Scrum
al igual que la anterior. Esta desarrollada en PHP contra MySQL
aunque parece también largo tiempo abandonada.
17. XPWeb
Al igual que las anteriores es una herramienta web para la
gestión de proyectos ágiles, incluyendo gestión de tareas,
calendarios, informes, etc. También parece estancada.
Trac
Herramienta web ampliamente extendida en la comunidad open
source para, fundamentalmente, el seguimiento proyectos. Se
centra en la gestión de incidencias y errores, aunque tiene
funcionalidades añadidas interesantes como Wiki e integración
con Subversión. Hay que reseñar que se trata de una
herramienta mono-proyecto y que no cuenta con Gantt.
OpenProject
Herramienta web de gestión de proyectos muy completa. Posee
todo lo necesario, tanto que uno llega a perderse. No obstante,
pueden configurarse los módulos que desean usarse y descartar
aquellos que no son necesarios: calendario, gestión de tareas,
seguimiento de incidencias, control presupuestario, Wiki, foros,
integración con ERPs, diagramas Gantt y una larga lista de
funcionalidades.
Tutos
The Ultimate Team Organization Software, o eso pretende. Se
trata de una herramienta web LAMP con muchas funcionalidades:
calendario y agenda, seguimiento de incidencias y errores,
gestión de tareas, diagramas Gantt, gestión documental, gestión
de correos, facturas e informes. Interesante pero austera de
aspecto y un poco anticuada.
Project Dune
Herramienta web desarrollada en Java contra MySQL que parecía
prometer bastante. Tiene lo necesario: gestión de tareas,
recursos, incidencias, gestión documental, registro de tiempos,
informes, calendario y agenda, RSS, inspección de código,
importación de MS Project, etc. No obstante, en su evaluación,
18. dejó bastante que desear resultando poco práctica y manejable.
Collabtive
Se trata de una herramienta web LAMP para la gestión de
proyectos. Según se indica en la web cubre la gestión de tareas e
incidencias, gestión documental y mensajería. Es muy limpia,
sencilla y ágil. No obstante, no parece contar con diagramas
Gantt, ni con registro de tiempos o informes de estado. En la
práctica parece quedarse un poco justa, pero prometedora.
Mindquarry
Herramienta web desarrollada en Java que pretende ser la
alternativa open source de soluciones propietarias como
Basecamp o Sharepoint para la gestión de proyectos y grupos de
trabajo de forma colaborativa. Tiene una versión open source
para descarga y otra como servicio bajo demanda. La pega es
que la empresa parece haber dejado de desarrollar su actividad.
ClockingIT
Se trata de una herramienta Web desarrollada en Ruby como
servicio bajo demanda. Permite una gestión de tareas, agenda
siguiendo el estándar iCal, seguimiento de tiempos, generación
de informes, notificaciones, RSS, foros, Chat y Wiki, repositorio
de ficheros, etc.
LibreSource
Se trata de una plataforma web colaborativa para el desarrollo de
software, lo que se suele denominar forja y funcionalidades de
groupware, archivado y publicación web. Es open source y
altamente ajustable. Permite alojar múltiples proyectos, varios
grupos de usuarios, etc. Está desarrollada en J2EE e incorpora
entre otras cosas: Wiki, integración con Subversion, zonas de
descarga, gestión documental, mensajería instantánea con
Jabber, gestión de incidencias, etc. No fue evaluada al ser
descubierta posteriormente a la implantación de la herramienta
elegida pero parece una buena alternativa.
19. Aunque existen infinidad más, de entre todas nos decantamos
por dos que valoramos más en profundidad:
TeamWork
Se trata de una herramienta web desarrollada en Java por unos
Italianos. Entre sus funcionalidades cabe destacar la gestión de
proyectos y tareas con diversos diagramas de Gantt muy
logrados, gestión de incidencias, gestión documental, entorno
colaborativo tipo groupware, control de costes, registros de
tiempos, etc.
Es muy completo, rápido de respuesta y posee características
muy interesantes como una interesante y útil navegación
contextual entre tareas del proyecto, perfiles de usuario según
proyecto, importación de planificaciones desde MS Project o
asociación entre incidencias y tareas.
Cuenta con wizards para la configuración de la herramienta de
forma rápida y sencilla, incluyendo la posibilidad de generar
plantillas para aplicar metodologías ágiles (Scrum).
El registro de horas por tarea para un desarrollador se realiza de
forma muy cómoda y rápida, desde una simple vista, facilitando
la participación del mismo.
Se trataba de una aplicación muy completa, quizás demasiado,
un poco compleja de entender en un comienzo pero con muchas
posibilidades.
No obstante, tenía alguna que otra pega, aunque es open source,
posee una licencia de pago para su uso que en cualquier caso era
muy pequeña. Tiene una versión de evaluación de 30 días para
quien desee probarla antes de decidir. Por otro lado no distingue
proyectos, existe una tarea padre que agrupa toda la
planificación asociada, tampoco cuenta con Wiki y no gestiona las
20. vacaciones del personal.
La otra herramienta valorada más en profundidad fue:
Redmine
Se trata de otra herramienta web, en este caso desarrollada en
Ruby on Rails con una gran cantidad de funcionalidades que la
acerca bastante a una forja pero sin tener la complejidad de la
misma. Entre sus características cabe destacar la gestión de
tareas, incidencias, diagramas de Gantt, calendario de
actividades, noticias, foros, wikis, gestión de ficheros y
documentos, integración con Subversión, control de tiempos,
generación de informes, etc, todo esto por proyecto. Por
similitudes del interfaz y funcionalidades parece estar basado en
Trac pero con un lavado de cara y de código importante, además
de ser multi-proyecto.
Al igual que la anterior también poseía una serie de
características que la hacía diferente, como la posible navegación
anónima de lectura, si así se desea, sobre los proyectos alojados.
Interesante desde el punto de vista de filosofía open source.
Posibilidad de definir un perfil distinto por usuario según el
proyecto en el que participa.
También cuenta con sindicación de RSS para las secciones de
noticias, tareas, incidencias, etc y exportación a ficheros de texto
y HTML desde la Wiki, los informes generados, e incluso el
diagrama de Gantt.
A parte, se trata de un interfaz muy limpio, intuitivo, sencillo de
usar y rapidísimo.
La configuración de la herramienta resulta, así mismo, muy
21. sencilla, con un par de clics puedes empezar a funcionar.
Cada proyecto puede configurarse con los módulos que desees
que tenga, además de poder definir campos personalizados por
proyecto y tarea para permitir una mayor adaptación.
Cabe destacar que para esta herramienta existe un único
concepto denominado petición que puede ser de tres tipos:
tareas, soporte o incidencia. De esta forma todo se gestiona de
igual forma, lo cual lo simplifica pero a su vez puede convertirse
en un volumen ingestionable de tareas. Para evitar esto, se
pueden definir categorías a las que pertenece una petición y
realizar posteriormente filtrados de peticiones en las vistas según
este y otros parámetros.
No obstante, no todo iba a ser color de rosa, tiene una serie de
limitaciones como el sistema un tanto engorroso de enlazar
peticiones, o el hecho de que una vez creada una petición, su
nombre y descripción no se pueden modificar, tan solo ir
añadiendo nuevas descripciones.
En este punto nos encontrábamos en una difícil decisión puesto
que ambas herramientas nos gustaban, cubrían lo necesario pero
se trataban de herramientas muy distintas en concepción. Para
facilitar la decisión realizamos un cuadro comparando las
características y priorizándolas según nuestro interés. El
resultado fue el siguiente:
Prioridad Característica Redmine TeamWork
9 Integración con Si Si
LDAP
8 Integración con Si Si
Subversion
8 Traducido al Si No
español
7 Importación desde No Si
Project
22. 7 Exportación a No Si
Project
7 Centros de coste Posible mediante Si
los campos
personalizados.
7 Wikis de proyectos Si
7 Personalización / Si Si
extensión
6 Gestión de No Vacaciones a
vacaciones nivel de
empresa
6 Vida de la Indeterminado al Algo más
herramienta ser una seguro
herramienta porque hay
open source. una empresa
detrás.
5 Facilidad de Si
configuración
5 Usuarios multi- Si Si
perfil
4 Acceso restringido Si Si
a usuarios
3 Sencillez de Si
manejo
2 Seguimiento de Si Si
incidencias
1 Asignación de Si Si
tareas
1 Imputación a Si Si
tareas asignadas
Tras una difícil reflexión, puesto que ambas se encontraban muy
parejas, decidimos decantarnos por Redmine, primando la
sencillez y rapidez. Existía la posibilidad de que terceros la
empleasen y veíamos que Redmine permitía una mayor facilidad
en su manejo y resultaba más intuitiva de cara a aprender a
utilizarla. Posteriormente tras su uso hemos detectado algunos
inconvenientes importantes como la imposibilidad de asignar una
petición a más de un usuario, pero es que, no hay herramienta
perfecta.
Bibliografía
23. http://www.navegapolis.net/content/view/56/49/
http://www.simpleprojectmanagement.com/home.html
http://www.web-based-software.com/project/
http://en.wikipedia.org/wiki/Comparison_of_issue_tracking_syste
ms
http://en.wikipedia.org/wiki/List_of_project_management_softwa
re
http://www.pmdigest.com/software/
Categoría CES OpenSouce/Java
s
Tema Varios
Autor Raúl Sanz de Acedo
Mes Julio
Año 2008
Boletín 07
Título Lexers, parsers, JavaCC (y II).
Texto En este artículo vamos a utilizar JavaCC como herramienta para
implementar un módulo que resuelva la casuística de la
impresión de las diversas páginas de un fichero. Esto es lo que se
refleja en esta imagen:
24. Para ello en el artículo anterior definimos esta gramática a la que
asociamos unas acciones semánticas:
inicio --> {inicializacionVariables}
listaElementos
{procesarDatos}
listaElementos --> elemento
restoListaElementos
elemento --> ENTERO
{num1 = valor(ENTERO);
Si (num1 > maxPaginas)
or (num1==0) ent error}
restoListaElementos2
restoListaElementos --> SEPARADOR
{insertarElemento(num1,
num2);
inicializacion(num1);
25. inicializacion(num2);}
listaElementos
| {}
{insertarElemento(num1,
num2);
inicializacion(num1);
inicializacion(num2);}
restoListaElementos2 --> GUION ENTERO
{ num2 = valor(ENTERO);
Si (num2 > maxPaginas)
or (num2==0) ent error}
| {}
JavaCC es una herramienta que dado un fichero de extensión
.jj, que describe la gramática y sus acciones semánticas
asociadas, genera los ficheros .java que la implementan:
Estos ficheros .java pueden luego, obviamente, incluirse en
aquéllos que conforman el resto de nuestra aplicación:
26. JavaCC es una herramienta gratuita, que puede descargarse
desde aquí. Existe también un plugin para Eclipse. Y, asimismo,
existe una task de Ant para JavaCC.
Vamos, pues, a construir nuestro parser.
Lo denominaremos parserImprimePaginasCC y por lo tanto
vamos a editar el fichero parserImprimePaginasCC.jj
Indicaremos cómo se traducen los tokens y las producciones a
formato JavaCC:
TOKEN:{
<ENTERO:(["0"-"9"])+>
| <GUION: "-">
| <SEPARADOR:([" "])+ | ","([" "])*>
}
Los tokens se describen prácticamente como lo indicamos en la
gramática.
void inicio()throws elementoFueraLimitesException:{}{
{
resultado = new Vector();
num1 = -1;
num2 = -1;
27. inicializaFlags();
}
listaElementos()
}
void listaElementos()throws elementoFueraLimitesExcept
ion:{}{
elemento() restoListaElementos()
}
void elemento()throws elementoFueraLimitesException:{}
{
<ENTERO>{
num1 = Integer.valueOf(token.image).intValue();
if ((num1>maximo)|| (num1 ==
0))throw new elementoFueraLimitesException("Introdujo
un numero superior al maximo:" +
Integer.toString(num1));
}
restoListaElementos2()
}
void restoListaElementos()throws elementoFueraLimitesE
xception:{}{
<SEPARADOR>{
insertaElemento(num1, num2);
num1 = -1;
num2 = -1;
}
listaElementos()
| {}{
insertaElemento(num1, num2);
28. num1 = -1;
num2 = -1;
}
}
void restoListaElementos2()throws elementoFueraLimites
Exception:{}{
<GUION><ENTERO>{
num2 = Integer.valueOf(token.image).intValue();
if ((num2>maximo)|| (num2 ==
0))throw new elementoFueraLimitesException("Introdujo
un numero superior al maximo:" +
Integer.toString(num2));
}
|{}
}
Las producciones son algo diferentes: lo que era
elemento --> ENTERO
{num1 = valor(ENTERO);
Si (num1 > maxPaginas)
or (num1==0) ent error}
restoListaElementos2
ahora es
void elemento()throws elementoFueraLimitesException:{}
{
<ENTERO>{
num1 = Integer.valueOf(token.image).intValue();
if ((num1>maximo)|| (num1 ==
0))throw new elementoFueraLimitesException(Integer.toS
tring(num1));
29. }
restoListaElementos2()
}
El no terminal elemento se describe como void elemento() y
además le hemos asociado una excepción para controlar el hecho
de que un usuario coloque 0 o un número mayor que el
permitido. Lo que en la parte derecha es ENTERO se indica
como <ENTERO> y la invocación de restoListaElementos2
es restoListaElementos2().
Las acciones semánticas
{num1 = valor(ENTERO);
Si (num1 > maxPaginas) or (num1==0) ent error}
se indican en JavaCC así:
{
num1 = Integer.valueOf(token.image).intValue();
if ((num1>maximo)|| (num1 ==
0))throw new elementoFueraLimitesException("Introdujo
un numero superior al maximo:" +
Integer.toString(num1));
}
El valor del token actual es accesible a través de token.image
Si deseamos tener código Java adicional fuera de las
producciones lo podemos añadir de esta forma, con la palabra
reservada JAVACODE:
JAVACODE void insertaElemento(int num1, int num2){
int aux, i, iFlag;
if ((num1 != -1) && (num2 != -1)){
if (num1>num2){
aux = num1;
30. num1 = num2;
num2 = aux;
}
for (i = num1;
i <= num2;
i++){
iFlag = i-1;
if (flags[iFlag] == false){
resultado.addElement(new Integer(i));
flags[iFlag] = true;
}
}
}
else if (num1 != -1){
iFlag = num1-1;
if (flags[iFlag] == false){
resultado.addElement(new Integer(num1));
flags[iFlag] = true;
}
}
else if (num2 != -1){
iFlag = num2-1;
if (flags[iFlag] == false){
resultado.addElement(new Integer(num2));
flags[iFlag] = true;
}
}
}
JAVACODE void inicializaFlags(){
int i;
31. flags = new boolean [maximo];
for (i = 0;
i<maximo;
i++){
flags[i] = false;
}
}
Además podemos inicializar el parser e instanciarlo de esta
forma:
PARSER_BEGIN(parserImprimePaginasCC)
import java.io.*;
import java.util.Vector;
public class parserImprimePaginasCC{
public static int maximo;
public static Vector resultado;
private static int num1, num2;
private static boolean flags[];
public static void main(String[]args)throws Exceptio
n{
Reader r = new StringReader(args[0]);
parserImprimePaginasCC p
= new parserImprimePaginasCC(r);
try {
p.maximo = 50;
System.out.println("Máximo: "+p.maximo);
p.inicio();
System.out.println("OKn");
for (int j = 0;
j<p.resultado.size();
j++){
32. System.out.print(p.resultado.elementAt(j)+"
");
}
System.out.println();
}
catch (ParseException e){
System.out.println("Error de sintaxis.");
}
catch (TokenMgrError e){
System.out.println("Error léxico.");
}
catch (elementoFueraLimitesException e){
System.out.println(e.getMessage());
}
}
}
PARSER_END(parserImprimePaginasCC)
En este caso tomaremos la entrada de lo que el usuario
introduzca por teclado pero se pueden tomar los datos a través
de ficheros o pasarlos como variables.
Se hace referencia a una excepción que hemos definido así en un
fichero llamado elementoFueraLimitesException.java:
public class elementoFueraLimitesException extends Exc
eption
{
/**
* Constructor
*/
public elementoFueraLimitesException()
33. {
super();
}
public elementoFueraLimitesException(String msg)
{
super(msg);
}
}
Una vez salvado el fichero parserImprimePaginasCC.jj podemos
generar la documentación de la gramática, en formato HTML, de
esta forma:
Nota: en la ejecución de estos ejemplos se ha utilizado la línea de comandos de
Windows pero se podría haber hecho a través de cualquier sistema que soporte
el lenguaje Java.
>jjdoc parserImprimePaginasCC.jj
Java Compiler Compiler Version 4.0 (Documentation
Generator Version 0.1.4)
(type "jjdoc" with no arguments for help)
Reading from file parserImprimePaginasCC.jj . . .
Grammar documentation generated successfully in
parserImprimePaginasCC.html
Se genera el fichero parserImprimePaginasCC.html,cuyo
contenido es:
BNF for parserImprimePaginasCC.jj
NON-TERMINALS
inicio ::= listaElementos
listaElementos ::= elemento restoListaElementos
elemento ::= <ENTERO> restoListaElementos2
restoListaElementos ::= <SEPARADOR> listaElementos
34. |
restoListaElementos2 ::= <GUION> <ENTERO>
|
insertaElemento ::= java code
inicializaFlags ::= java code
Nota: BNF es el tipo de notación que estamos utilizando a lo largo de estos
artículos.
Compilamos el parser:
>javacc parser ImprimePaginasCC.jj
Java Compiler Compiler Version 4.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file parserImprimePaginasCC.jj . . .
File "TokenMgrError.java" does not exist. Will create
one.
File "ParseException.java" does not exist. Will
create one.
File "Token.java" does not exist. Will create one.
File "SimpleCharStream.java" does not exist. Will
create one.
Parser generated successfully.
y entonces se generan estos ficheros:
ParseException.java -->
Excepción generada por el parser cuando un error es encontrado.
parserImprimePaginasCC.java --> La
traducción de nuestro fichero .jj a .java
parserImprimePaginasCCConstants.java --> Los
valores de los tokens.
parserImprimePaginasCCTokenManager.java --> El
analizador léxico.
35. SimpleCharStream.java -->
Contiene código para leer caracteres de cualquier
implementación de java.io.InputStream o java.io.Reader
Token.java -->
Definición de la clase Token
TokenMgrError.java -->
Diversos errores que puede producir el lexer.
Ahora los compilamos y añadimos el fichero
elementoFueraLimitesException.java en dicha compilación:
javac *.java
Y vamos a ejecutar el parser, suponiendo que el máximo número
de páginas a impmir es 50 (como hemos indicado con p.maximo =
50).
Lo que obtenemos como salida es la lista de páginas a imprimir o
un mensaje de error.
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "2,5-8"
Num. paginas: 50
OK
2 5 6 7 8
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "28-30,4,6"
Num. paginas: 50
OK
28 29 30 4 6
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "43-51"
Num. paginas: 50
Introdujo un numero superior al maximo:51
36. java -classpath "...laboratorioParsers"
parserImprimePaginasCC "43--51"
Num. paginas: 50
Error de sintaxis:Encountered "-" at line 1,
column 4.
Was expecting:
<ENTERO> ...
¿Qué pasa si algo ha ido mal? ¿Podemos depurar el parser de
alguna forma?
Por supuesto: podemos compilar el parser así para obtener una
traza de la ejecución.
javacc -DEBUG_PARSER parserImprimePaginasCC.jj
Java Compiler Compiler Version 4.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file parserImprimePaginasCC.jj . . .
Parser generated successfully.
javac *.java
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "2,5-8"
Num. paginas: 50
Call: inicio
Call: inicializaFlags
Return: inicializaFlags
Call: listaElementos
Call: elemento
Consumed token: <<ENTERO>: "2" at line 1 column
1>
Call: restoListaElementos2
37. Return: restoListaElementos2
Return: elemento
Call: restoListaElementos
Consumed token: <<SEPARADOR>: "," at line 1
column 2>
Call: insertaElemento
Return: insertaElemento
Call: listaElementos
Call: elemento
Consumed token: <<ENTERO>: "5" at line 1
column 3>
Call: restoListaElementos2
Consumed token: <"-" at line 1 column 4>
Consumed token: <<ENTERO>: "8" at line 1
column 5>
Return: restoListaElementos2
Return: elemento
Call: restoListaElementos
Call: insertaElemento
Return: insertaElemento
Return: restoListaElementos
Return: listaElementos
Return: restoListaElementos
Return: listaElementos
Return: inicio
OK
2 5 6 7 8
En la traza vemos cómo el parser va invocando la diferentes
producciones.
38. Podemos también depurar el lexer:
javacc -DEBUG_TOKEN_MANAGER parserImprimePaginasCC.jj
Java Compiler Compiler Version 4.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file parserImprimePaginasCC.jj . . .
Parser generated successfully.
javac *.java
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "2,5-8"
Num. paginas: 50
Current character : 2 (50) at line 1 column 1
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 2 (50) at line 1 column 1
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
Current character : , (44) at line 1 column 2
Currently matched the first 1 characters as a
<ENTERO> token.
Putting back 1 characters into the input stream.
****** FOUND A <ENTERO> MATCH (2) ******
Current character : , (44) at line 1 column 2
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : , (44) at line 1 column 2
39. Currently matched the first 1 characters as a
<SEPARADOR> token.
Possible kinds of longer matches : { <SEPARADOR> }
Current character : 5 (53) at line 1 column 3
Currently matched the first 1 characters as a
<SEPARADOR> token.
Putting back 1 characters into the input stream.
****** FOUND A <SEPARADOR> MATCH (,) ******
Current character : 5 (53) at line 1 column 3
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 5 (53) at line 1 column 3
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
Current character : - (45) at line 1 column 4
Currently matched the first 1 characters as a
<ENTERO> token.
Putting back 1 characters into the input stream.
****** FOUND A <ENTERO> MATCH (5) ******
Current character : - (45) at line 1 column 4
No more string literal token matches are possible.
Currently matched the first 1 characters as a "-"
token.
****** FOUND A "-" MATCH (-) ******
Current character : 8 (56) at line 1 column 5
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
40. <SEPARADOR> }
Current character : 8 (56) at line 1 column 5
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
****** FOUND A <ENTERO> MATCH (8) ******
Returning the <EOF> token.
OK
2 5 6 7 8
O combinar ambas trazas:
javacc -DEBUG_PARSER -
DEBUG_TOKEN_MANAGER parserImprimePaginasCC.jj
Java Compiler Compiler Version 4.0 (Parser Generator)
(type "javacc" with no arguments for help)
Reading from file parserImprimePaginasCC.jj . . .
Parser generated successfully.
javac *.java
java -classpath "...laboratorioParsers"
parserImprimePaginasCC "2,5-8"
Num. paginas: 50
Call: inicio
Call: inicializaFlags
Return: inicializaFlags
Call: listaElementos
Call: elemento
41. Current character : 2 (50) at line 1 column 1
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 2 (50) at line 1 column 1
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
Current character : , (44) at line 1 column 2
Currently matched the first 1 characters as a
<ENTERO> token.
Putting back 1 characters into the input stream.
****** FOUND A <ENTERO> MATCH (2) ******
Consumed token: <<ENTERO>: "2" at line 1 column
1>
Call: restoListaElementos2
Current character : , (44) at line 1 column 2
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : , (44) at line 1 column 2
Currently matched the first 1 characters as a
<SEPARADOR> token.
Possible kinds of longer matches : { <SEPARADOR> }
Current character : 5 (53) at line 1 column 3
Currently matched the first 1 characters as a
<SEPARADOR> token.
Putting back 1 characters into the input stream.
****** FOUND A <SEPARADOR> MATCH (,) ******
Return: restoListaElementos2
42. Return: elemento
Call: restoListaElementos
Consumed token: <<SEPARADOR>: "," at line 1
column 2>
Call: insertaElemento
Return: insertaElemento
Call: listaElementos
Call: elemento
Current character : 5 (53) at line 1 column 3
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 5 (53) at line 1 column 3
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
Current character : - (45) at line 1 column 4
Currently matched the first 1 characters as a
<ENTERO> token.
Putting back 1 characters into the input stream.
****** FOUND A <ENTERO> MATCH (5) ******
Consumed token: <<ENTERO>: "5" at line 1
column 3>
Call: restoListaElementos2
Current character : - (45) at line 1 column 4
No more string literal token matches are possible.
Currently matched the first 1 characters as a "-"
token.
****** FOUND A "-" MATCH (-) ******
Consumed token: <"-" at line 1 column 4>
43. Current character : 8 (56) at line 1 column 5
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 8 (56) at line 1 column 5
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
****** FOUND A <ENTERO> MATCH (8) ******
Consumed token: <<ENTERO>: "8" at line 1
column 5>
Return: restoListaElementos2
Return: elemento
Call: restoListaElementos
Returning the <EOF> token.
Call: insertaElemento
Return: insertaElemento
Return: restoListaElementos
Return: listaElementos
Return: restoListaElementos
Return: listaElementos
Return: inicio
OK
2 5 6 7 8
Conclusión: los generadores de parsers son herramientas
potentes que sirven para resolver problemas de una manera
„limpia‟ y elegante. Puede que su nombre retraiga a los
desarrolladores (“¿Para qué quiero un generador de
compiladores?”) pero es una opción a tener en cuenta.
44. Ficheros para descargar.
Referencias:
- Generating Parsers with JavaCC.
- The JavaCC FAQ.
Si quieres enviar algún comentario o sugerir temas a tratar en otros artículos, escribe a:
curtasun[simboloArroba]cein.es
Categor CES OpenSouce/Java
ías
Tema Desarrollo
Autor Carlos Urtasun
Mes Julio
Año 2008
Boletín 07
Título XSL-FO (Parte 1).
Texto XSL-FO Introducción
El estándar XSL, tal y como está definido actualmente, se
divide en dos grandes partes:
-XSLT: transformación de un documento de entrada XML en
algún tipo de documento de salida, ya sea XML, HTML, PDF,
etc.
-Formatting Objects (FO): definen la visualización final del
resultado de la transformación. Son una implementación
específica de un determinado XSLT y aplicados a un
fichero XML nos proporcionan otro fichero con la información
de éste, renderizada a algún formato de visualización
impresa. Ésta es quizá la principal diferencia entre un FO y
otros XSLT: ambos transforman un documento XML en otro
documento XML, pero FO está pensado para generar
directamente una renderización.
45. XSL-FO construye un documento que se crea de fuera para
adentro.
Con XSL-FO se puede definir el tamaño físico de la hoja para
imprimir, y controlar propiedades de la página: márgenes,
cabecera, pie… La paginación se produce de forma
automática. Se pueden definir distintos modelos de páginas,
se pueden insertar diferentes elementos como por ejemplo
imágenes, posee propiedades compatibles con CSS y más
posibilidades no contempladas en CSS, se pueden hacer
referencias cruzadas, etc.
Los FO están divididos formalmente en cuatro tipos de áreas
rectangulares:
- block-container: es la estructura de mayor nivel. Se
puede colocar de manera precisa, por coordenadas
dentro de su propio contenedor. Puede contener block-
container, blocks, tablas y listas.
- block: es un párrafo. Lleva al final un salto de línea.
Puede contener más blocks, imágenes, líneas, tablas,
listas… Se corresponde con el <div> de HTML
- inline-container: cada línea de texto.
- inline: caracteres dentro de una línea. Se suele usar
para cambiar su color de fondo, su tamaño de fuente y
otros atributos afines.
Estas cuatro categorías forman una jerarquía muy estricta.
Estas áreas pueden contener atributos para dar estilo a su
contenido.
Existen cuatro atributos muy utilizados en el elemento
block:
space-before
space-after
margin
border
46. padding
content
Space-before y space-after es el espacio vacío que separa el
block de otros block.
Margin es el área vacía en la parte externa del block.
Border es el borde del block.
Padding es el área comprendida entre el border y el contenido
del block.
Content lleva el contenido real: texto, imágenes, tablas...
Dentro de un elemento fo:block se puede hacer un corte de
página:
<fo:block font-size="9pt" break-before="page">
Texto perteneciente al block
</fo:block>
En este caso, el corte se producirá antes de pintarse el block.
En el siguiente caso, el corte se producirá después de pintarse
el contenido del block:
<fo:block font-size="9pt" break-after="page">
Texto perteneciente al block
</fo:block>
Además de poder definir la estructura del documento
generado a partir de los FO, podemos usar propiedades para
especificar más concretamente la renderización que producirá
un determinado fichero. Así, por ejemplo, el tamaño de la
página, color de texto, etc., pueden ser explicitadas mediante
el uso de atributos de los FO.
Por lo tanto XSL-FO es la tecnología que nos permite
transformar ficheros XML en formato pdf, lo que hace que
adquiera una gran potencia ya que según las exigencias del
usuario podremos adaptar la información contenida en
nuestro XML al gusto del usuario que al final va a ser el que
haga uso de la información disponible.
Categorías General
Tema Desarrollo
Autor Raquel Urdangarin
Mes Julio
Año 2008
Boletín 07
Título ¿Qué es Subversion?
Texto Subversion es un sistema gratuito y open
47. source de control de versiones iniciado en 2000
por CollabNet Inc. Emplea licencia Apache/BSD. Se usa
para mantener versiones actuales e históricas y los
cambios de archivos tales como los de código fuente,
páginas web y/o documentación. Esto permite recuperar
versiones antiguas de los datos o examinar cómo han ido
evolucionando estos. Por eso, se podría pensar que un
sistema de control de versiones es una especie de
“máquina del tiempo”. Su objetivo es ser un sucesor
prácticamente compatible del ampliamente
usado Concurrent Versions System(CVS).
Subversion puede trabajar a través de redes, lo que
permite que personas que estén en diferentes
ordenadores puedan usarlo. De cierta manera, la
posibilidad de que varias personas modifiquen y
gestionen el mismo conjunto de datos desde sus
respectivos sitios promueve la colaboración. Y como el
trabajo está versionado, no hace falta temer que la
calidad del mismo empeore como consecuencia de perder
un conducto que los revisara, ya que si se produce algún
cambio incorrecto de los datos, sólo hace falta
deshacerlo.
Ventajas
Se sigue la historia de los archivos y directorios a
través de copias y renombrados.
Las modificaciones (incluyendo cambios a varios
archivos) son atómicas.
La creación de ramas y etiquetas es una operación
más eficiente; Tiene costo de complejidad
constante (O(1)) y no lineal (O(n)) como en CVS.
Se envían sólo las diferencias en ambas direcciones
(en CVS siempre se envían al servidor archivos
completos).
Puede ser servido mediante Apache,
sobre WebDAV/DeltaV. Esto permite que clientes
WebDAV utilicen Subversion de forma transparente
Maneja eficientemente archivos binarios (a
diferencia de CVS que los trata internamente como
si fueran de texto).
48. Permite selectivamente el bloqueo de archivos. Se
usa en archivos binarios que, al no poder fusionarse
fácilmente, conviene que no sean editados por más
de una persona a la vez.
Cuando se usa integrado a Apache permite utilizar
todas las opciones que este servidor provee a la
hora de autentificar archivos (SQL, LDAP, PAM,
etc.).
Los programas asociados a Subversion que se
ejecutan por línea de comandos tales como svn
pueden ejecutarse tanto en plataformas Unix,
Linux, Solaris o Microsoft Windows. La forma de
ejecutarlos es igual en cualquier sistema salvo por
el hecho de tener en cuenta unas pequeñas
excepciones como el uso de contra-barras () en
vez de barras (/) si fuera necesario.
Carencias
El manejo de cambio de nombres de archivos no es
completo. Lo maneja como la suma de una
operación de copia y una de borrado.
No resuelve el problema de aplicar repetidamente
parches entre ramas, no facilita el llevar la cuenta
de qué cambios se han trasladado. Esto se resuelve
siendo cuidadoso con los mensajes de commit. Esta
carencia ha sido corregida en la versión 1.5.
49. Figura 1. Arquitectura de subversion
Comparativa entre Subversion y CVS
En CVS los números de revisión se dan a cada
archivo, en Subversion los números de revisión se
dan a todos los archivos. Por cada revisión que se
hace, se genera un nuevo árbol de directorios que
contiene todos los cambios de la revisión.
En CVS un tag o branch es una anotación en un
archivo o en la información de la versión de ese
archivo, mientras que en Subversion, es una copia
del árbol completo en un directorio. Por convenio
se usan /branches o /tags, que se encuentran en la
50. raíz del repositorio.
Subversion tiene en cuenta las estructuras de
directorios, no sólo el contenido de los
archivos. Sin embargo, hasta que no se haga un
update, el número de revisión asignado al directorio
no será correcto.
Subversion permite ejecutar más operaciones sin
conexión que CVS porque guarda una copia de sólo
lectura de los archivos sin modificaciones. Permite
ejecutar operaciones de status, de diff (ver las
diferencias entre revisiones) o revertir los
cambios. Además cuando se conecta al repositorio
manda las diferencias.
Subversion modifica los comandos update y status
para clarificar su uso. En CVS, el comando status
sirve para mostrar las modificaciones de la copia
local y para ver qué ficheros no están
sincronizados. Esta información es bastante
complicada de leer. Para obtenerla de forma más
sencilla se puede usar la opción update –n. La
opción de update, sirve también para actualizar el
repositorio. En Subversion, status te muestra los
archivos locales que tienen cambios (por defecto
sin contactar con el repositorio) y update actualiza
tu copia local del repositorio, mostrando sólo los
cambios que se han actualizado, no las
modificaciones de los archivos locales.
Para Subversion, los branches y tags son solamente
directorios, mientras que en CVS son un espacio
aparte.
En Subversion se pueden añadir propiedades a
archivos y directorios, mientra que en CVS no.
Para resolver conflictos, Subversion en vez de
añadir una C para indicar que hay un conflicto y
permitir luego hacer cambios, no permite las
operaciones de commit hasta que no se resuelva
explícitamente el conflicto. Además, a partir de la
versión 1.5 los permite resolver interactivamente,
así conforme van descubriéndose se pueden
resolver y se continuará con la operación de
commit.
CVS, sólo puede guardar archivos de texto, así que
51. si se guardan archivos binarios los debe
transformar a texto, mientras que Subversion
distingue entre archivos binarios y texto.
CVS utiliza RCS para guardar las revisiones,
mientras que Subversion utiliza una base de datos.
Subversion considera que un módulo en un
conjunto de archivos y directorios, así que si esto
se cambia, todos los usuarios se enterarán,
mientras que en CVS eso no será posible.
CVS exige autentificación para todas las
operaciones, aunque el acceso sea anónimo,
mientras que en Subversion, si se utiliza Apache
para contactar con el repositorio, y el repositorio
tiene acceso universal de lectura, entonces no te
pedirá ningún tipo de autentificación para hacer
operaciones de lectura. Sólo la exigirá para hacer
las operaciones para lo que se haya configurado la
necesidad de autentificación. El único caso en el
que siempre solicitará contraseña Subversion será
cuando el acceso se hace mediante svnserve y está
configurado con ssh. En ese momento, para
comenzar la comunicación pedirá una contraseña.
Para obtener más información sobre el tema, se pueden
consultar la documentación siguiente:
ENLACES DE INTERÉS:
Subversion
http://en.wikipedia.org/wiki/Subversion_(software)
http://es.wikipedia.org/wiki/Subversion
http://subversion.tigris.org/
http://www.1x4x9.info/files/subversion/html/online
-chunked/index.html
http://svn.collab.net/repos/svn/trunk/INSTALL
Version Control with Subversion, Ben Collins-
Sussman, Brian W. Fitzpatrick, C. Michael Pilato. -
> http://svnbook.red-bean.com/
52. http://www.pushok.com/soft_svn_vscvs.php
Categoría CES OpenSouce/Java
s
Tema Varios
Autor Blanca Cubas Cruz
Mes Julio
Año 2008
Boletín 07