Espacio de tecnologia, software libre y sus derivados. Una horda de monos entrenados escriben de vez en cuando por aqui algunas noticias, opiniones e incluso alguna que otra cosa fuera del tema. Maqueros, favor de abstenerse que no somos lo suficientemente guapos.

Piano daemon

Archive for Linux

Hilos con C (Compilado en Linux)

Aqui les muestro como compilo un programita para ejemplificar el uso de hilos

[j4nusx@localhost ~]$ gcc hilos.c -lpthread -Wall -o hilos
[j4nusx@localhost ~]$ ./hilos
En Funcion main: Creando el Hilo 0
En Funcion main: Creando el Hilo 1
En Funcion main: Creando el Hilo 2
En Funcion main: Creando el Hilo 3
En Funcion main: Creando el Hilo 4
Hola esto se ejecuta en el hilo #0!
Hola esto se ejecuta en el hilo #1!
Hola esto se ejecuta en el hilo #2!
Hola esto se ejecuta en el hilo #3!
Hola esto se ejecuta en el hilo #4!

Aqui el codigo fuente

#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#define NUM_THREADS     5

// La funcion que es utilizada en un Hilo
// debera de retornar un puntero sin tipo
void *ImprimeSaludo(void *threadid){
   long tid;
   // Aqui se castea lo que le fue pasado
   // al hilo como atributos
   tid = (long)threadid;
   printf("Hola esto se ejecuta en el hilo #%ld!n", tid);
   pthread_exit(NULL);
}
// --- Aqui finaliza la funcion que
// sera llamada en el hilo

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t < NUM_THREADS; t++){
      printf("En Funcion main: Creando el Hilo %ldn", t);
      rc = pthread_create(&threads[t], NULL, ImprimeSaludo, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %dn", rc);
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

La función que nos permite crear un un nuevo hilo de ejcución es pthread_create() que admite cuatro parámetros:


pthread_t * es un puntero a un identificador de thread. La función nos devolverá este valor relleno, de forma que luego podamos referenciar al hilo para “hacerle cosas”, como matarlo, esperar por él,etc.
pthread_attr_t * son los atributos de creación del hilo. Hay varios atributos posibles, como por ejemplo la prioridad. Un hilo de mayor prioridad se ejecutará con preferencia (tendrá más rodajas de tiempo) que otros hilos de menor prioridad. Se puede pasar NULL, con lo que el hilo se creará con sus atributos por defecto y para nuestro ejemplo es suficiente. Si queremos un programa que cree y destruya hilos continuamente, no vale NULL, ya que con esta opción dejaremos memoria sin liberar cada vez que termine un hilo.
void *(*)(void *) es un tipo la mar de raro. Aunque asuste, no es más que el tipo de una función que admite un puntero void * y que devuelve void *. Eso quiere decir que a este parámetro le podemos pasar el nombre de una función que cumpla lo que acabamos de decir. Esta función es la que se ejecutará como un hilo aparte. El hilo terminará cuando la función termine o cuando llame a la función pthread_exit() (o que alguien lo mate desde otra parte del código). Es bastante habitual hacer que esta función se meta en un bucle infinito y quede suspendida en un semáforo o a la espera de una señal para hacer lo que tenga que hacer y volver a quedar dormida.
void * es el parámetro que se le pasará a la función anterior cuando se ejecute en el hilo aparte. De esta manera nuestro programa principal puede pasar un único parámetro (que puede ser cualquier cosa, como una estructura compleja) a la función que se ejecutará en el hilo. La función del hilo sólo tendrá que hacer el “cast” adecuado.

La función pthread_create() devuelve 0 si todo ha ido bien. Un valor distinto de 0 si ha habido algún problema y no se ha creado el thread.

Si deseas saber mas a detalle el asunto de los hilos en linux, te recomiendo la siguente liga

Relacion entre nodos, zonas y paginas (Administracion de la Memoria Virtual en linux)

Linux esta disponible para una gran gama de computadores, y a causa de esto, los desarrolladores encontraron una manera independiente a la arquitectura para describir lo que es la memoria.

CONCEPTOS QUE PREVALECEN EN LA ADMINISTRACION DE MEMORIA VIRTUAL (VM)

NUMA: Forma no uniforme de acceso a la memoria.

Bancos de MEmoria

En Maquina grandes la memoria puede ser agrupada en bancos de memoria, cada uno de estos bancos puede ser asignado a un CPU o a un DMA.

Cada banco de memoria es llamado NODO.

Un nodo en linux es representado por la estructura “pglist_data“, aun si la arquitectura es UMA.

UMA: Acceso Uniforme a memoria.
La Estructura “pglist_data” es siempre referenciada mediante su tipo “pg_data_t“.

Cada NODO en el sistema es albergado sobre una lista terminada en NULO, cuyo nombre es “pgdat_list” y cada nodo es linkeado al siguiente con el campo pg_data_t->node_next.

Para arquitecturas UMA (Las pcs de escritorio son de este tipo de arquitectura), solo existe una estructura estatica “pg_data_t” llamada “contig_page_data” que es usada.

Cada banco de memoria o NODO, es dividido en bloques llamados zonas. Las zonas representan rangos dentro de la memoria.

La Zona es definida por la estructura “zone_struct“, pero es siempre referenciada mediante el tipo de dato definido “zone_t“.
Las zonas pueden ser de 3 tipos:


- DMA
- NORMAL
- HIGHMEM

ZONA_DMA: Memoria en rangos bajos de memoria fisica, requerida por los dispositivos ISA.
ZONA_NORMAL: Ubicada en la posicion alta del espacio lineal de direcciones.
ZONA_HIGHMEM: Memoria restante en el sistema y no es directamente mapeada por el kernel.

La memoria del sistema es agrupada en lotes llamados “page frames“, Cada “page frame” es representado por la estructura “page” y todas las estructuras son mantenidas en un arreglo global llamado “mem_map“, el cual es usualmente almacenado al inicio de la ZONA_NORMAL o del area reservada para la imagen del kernel cargada en maquinas de poca memoria.

Relacion entre nodos, zonas y paginas (Administracion de la Memoria Virtual en linux)

Conoce a los creadores de C

Compilando Hola mundo en C

#include "stdio.h"

int main(){
	char *saludo = "Hola Mundo";
	printf("%s n",saludo);
	return 0;
}

Hola a todos, la razon de este programita, es manifestarles a todos mis amigos, mi interes por el lenguaje C.

Me canse de buscar en los frameworks de la WEB 2.0
Me canse de las novedades de .NET
Me canse de lo que te ofrece JAVA

Ahora estoy convencido que lo fundamental es todo!
Que clase de profesional de los sistemas soy, si no utilizo como navaja suiza a C. :)

La forma en que compile el anterior ejemplo sobre linux fue la siguiente:

[j4nusx@localhost ~]$  gcc hola_mundo.c -Wall -o hola_mundo

El parametro Wall … indica a gcc que debere mostrar todos los warnings durante la compilacion, y el parametro (menos o) especifica el nombre que le dare a mi salida de este proceso de compilacion….

Para ejecutar mi ejemplo, bastara con ejecutar:

[j4nusx@localhost ~]$ ./hola_mundo
Hola Mundo

JBOSS & POSTGRESQL & APACHE con HTTPS SUPPORT

http://www.geocities.com/j4nusx/manual_carrito.pdf

Buenas tardes a todos los que visitan gulsin…. ultimamente no he tenido mucho tiempo para escribir aqui… asi que les anexo un documento que le puede interesar a los javeros que implementan sus soluciones enlinux…

Aclaro… sigue sin gustarme java!

Importando funciones bash desde un archivo

Un colega el dia de ayer me comento (via email)…

Hey Edwin estoy preparando unos scripts en bash.. el detalle es que estos scripts ya estan bastante largos y me gustaria separar las funciones de los scripts que tengo en archivos independientes…
Con el fin de reutilizar codigo en otros scripts.. se puede..?
Como coños importo las funciones!

Este fue el correo que le conteste:

En la parte frontal (oseace la parte de arriba) de tu script principal (despues del #!/bin/bash)… agrega lo siguiente, teniendo en mente esto ( el punto en bash es lo mismo que una directiva include en lenguaje C):

. /ruta/a/fichero_con_funciones.sh

No pierdas de vista el espacio entre el punto y la ruta al fichero de funciones.

Ejemplo de todo lo anterior:

Primero definimos el fichero de variables(o bien tambien lo puedes llenar con funciones):

j4nusx@(none):~$ more variables.sh
X="3"
Y="3"

Ahora definimos un script que mande a llamar a dichas variables (aunque tambien podriamos mandar a llamar funciones!)

j4nusx@(none):~$ more ejemplo.sh
#!/bin/bash
. ./variables.sh
suma(){
        echo  "$X + $Y" | bc
}

resta(){
        echo "$X - $Y" | bc
}

multiplicacion(){
        echo "$X * $Y" | bc
}

#############################
# Aqui inicia nuestro programita shell
echo "La suma de X y Y es:"
suma

echo "La resta de X y Y es:"
resta

echo "La multiplicacion de X y Y es:"
multiplicacion

Ahora corramos nuestro ejemplo…..

j4nusx@(none):~$ chmod 755 ./ejemplo.sh && ./ejemplo.sh
La suma de X y Y es:
6
La resta de X y Y es:
0
La multiplicacion de X y Y es:
9
j4nusx@(none):~$

Tunning PostgreSQL 8.2 sobre GNU/LINUX

Autor: Ing.Edwin Plauchu
mail to: j4nusx@gmail.com

Instalando Postgresql
Antes de instalar “postgresql 8.2″ , verifiquemos que este, no este ya instalado, si esto no fuese asi utilice descargue las fuentes de postgresql de la ftp de postgres:


wget -c http://ftp7.de.postgresql.org/pub/ftp.postgresql.org/latest/postgresql-8.2.5.tar.bz2

Compilando Postgresql 8.2

Procedemos a desempaquetar nuestras fuentes

pianodaemon@pianodaemon:~> tar -xvjf ./postgresql-8.2.5.tar.bz2

Aplicaremos las opciones de compilacion que aqui se muestran:

./configure --prefix=/home/postgresql/ --without-zlib && make && make install

Explicacion de los parametros anteriormente citados:

–prefix=/home/postgresql/ <---- Instalara postgresql en el home del usuario del sistema "postgresql"

–without-zlib <---- Desactiva el uso de compresion en nuestras tablas, sacrificando espacio, pero ganando velocidad de lectura en archivo de disco.

El usuario postgresql

Postgresql solo podra ser ejecutado por el usuario postgresql, mismo que debera de pertenecer al grupo postgresql.
Asi que procederemos a la creacion del mismo y de su grupo, posteriormente asignaremos el directorio /home/postgresql, solo al usuario y grupo postgresql:

pianodaemon@pianodaemon:~> groupadd postgresql
pianodaemon@pianodaemon:~> useradd -d /home/postgresql/ -g postgresql -s /bin/bash postgresql
pianodaemon@pianodaemon:~> chown -R postgresql:postgresql /home/postgresql/

Configuración Post-Instalación

Vamos a crear un directorio data (directorio de archivos en disco que almancenan las tablas de nuestras bases de datos), esto lo haremos logeados como el usuario postgresql:

pianodaemon@pianodaemon:~> su - postgresql
postgresql@pianodaemon:~> pwd
/home/postgresql/
postgresql@pianodaemon:~> mkdir ./DATA

Inicializando el directorio data:

postgresql@pianodaemon:~> ./bin/initdb -D ./DATA/
The files belonging to this database system will be owned by user "postgresql".
This user must also own the server process.

The database cluster will be initialized with locale es_ES.UTF-8.
The default database encoding has accordingly been set to UTF8.

fixing permissions on existing directory ./DATA ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers/max_fsm_pages ... 32MB/204800
creating configuration files ... ok
creating template1 database in ./DATA/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating conversions ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the -A option the
next time you run initdb.

Success. You can now start the database server using:

    ./bin/postgres -D ./DATA
or
    ./bin/pg_ctl -D ./DATA -l logfile start

Si obtuviste la pantalla anterior, el directorio data fue inicializado con exito.

Shell Script requerido para el arranque y parada de Postgresql

El siguiente shell script, esta realizado en bash, para llevar a cabo su ejecucion:

#!/bin/sh
# Start/stop/restart postgresql.
#
# To start PostgreSQL automatically at boot, be sure this script is executable:
# chmod 755 /etc/rc.d/rc.postgres

# --> Before you can run PostgreSQL, you must have a database.  Use initd.
#
# Note that step one is becoming the 'postgres' user. It's important to do this
# before making any changes to the database, or postgres won't be able to write
# to it later

# Set up variables
PGROOT=/home/postgresql
PGDATA=/home/postgresql/DATA
PGUSER=postgresql
PGLOG="$PGDATA/postgres.log"
PGDAEMON="$PGROOT/bin/postmaster"
PGCTL="$PGROOT/bin/pg_ctl"

if echo 'c' | grep -s c >/dev/null 2>%1; then
  ECHO_N="echo -n"
  ECHO_C=""
else
  ECHO_N="echo"
  ECHO_C='c'
fi

set -e

# Start postgresql:
postgresql_start() {
  $ECHO_N "Starting PostgreSQL: "$ECHO_C
  su - $PGUSER -c "$PGDAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
  echo "ok"
}

# Stop postgresql:
postgresql_stop() {
  $ECHO_N "Stopping PostgreSQL: "$ECHO_C
  su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast" >>$PGLOG 
2>&1
  echo "ok"
}

# Restart postgreSQL:
postgresql_restart() {
  $ECHO_N "Restarting PostgreSQL: "$ECHO_C
  su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast" >>$PGLOG 
2>&1
  echo "ok"
  su - $PGUSER -c "$PGDAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
  echo "ok"
}

case "$1" in
  'start')
  postgresql_start
  ;;
  'stop')
  postgresql_stop
  ;;
  'restart')
  postgresql_restart
  ;;
  *)
  echo "Usage $0 {start|stop|restart}" 1>&2
  exit 1
  ;;
esac
exit 0

Optimizando PostgreSQL

El reto de nuestra afinación va a consistir en optimizar el uso de memoria para postgres, minimizando en lo posible el número de intercambios con la swap (pagein). El mejor ajuste de los parámetros de configuración será aquél que obtenga la máxima disponibilidad en memoria para la BD, sin perjudicar al resto de elementos, que también deben permanecer en memoria.

SHARED_BUFFERS

El número de shared_buffers es el parámetro que más afecta al rendimiento de PostgreSQL. Este valor, de tipo entero, indica el número de bloques de memoria o buffers de 8KB (8192 bytes) que postgres reservará, como zona de trabajo, en el momento del arranque para procesar las consultas. De forma predeterminada (en postgresql.conf), su valor es de 1000. Un número claramente insuficiente para conseguir un rendimiento mínimamente aceptable.

Estos buffers se ubican dentro de los denominados segmentos de memoria compartida. Es importante saber que el espacio ocupado por el número de buffers que pretendamos asignar, nunca podrá exceder al tamaño máximo que tengan los segmentos de memoria. En caso contrario, postgres se negará a arrancar avisando con un error que no puede reservar el espacio solicitado.

Una buena recomendación (lee el artículo de B. Momjian[1]) es la de empezar asignando un 10% del total de la memoria RAM para shared_buffers y a partir de ahí, ir aumentando o disminuyendo dicho porcentaje en función del rendimiento y la paginación.

Comenzamos:

El 10% de 1 GB: (1048576 KB/10) = 104857 KB
shared_buffers: (104857 KB/8 KB) = 13107

Asignamos este valor a la variable shared_buffers (postgresql.conf)

En Linux, de forma predeterminada, el tamaño de un segmento de memoria compartida es de 32MB. Podemos comprobarlo haciendo (el resultado es en nº de bytes):

postgresql@pianodaemon:~> cat /proc/sys/kernel/shmmax
33554432

El espacio que requiere el número de buffers, es superior al tamaño del segmento:

13107 buffers ocupan 107372544 bytes (13107 * 8192 bytes/bloque)
107372544 > 33554432

Asi que asignaremos al kernel de linux un nuevo tamaño de segmento por default(agregue esta linea en /etc/sysctl.conf).

kernel.shmmax=107372544

Para comprobar el rendimiento, aplica EXPLAIN[2] a tus consultas. Para ver la paginación del servidor, puedes usar herramientas como vmstat o ipcs (consulta sus páginas man).
[editar] WORK_MEM

Este parámetro configura el espacio de memoria que postgres utiliza para realizar ordenaciones de tablas o de resultados parciales de consultas, sobre todo en cláusulas ORDER BY, CREATE INDEX o MERGE JOIN.

Este valor es más dificil de configurar porque depende, por un lado, de lo grande que sean las tablas o resultados que hay que ordenar, y por otro, del número de peticiones simultáneas para esa misma consulta (para cada una se empleará la misma cantidad de memoria).

Una buen comienzo es asignar entre un 2% y un 4% del total de la memoria si prevemos pocos accesos simultáneos a grandes sesiones de ordenación y mucho menor, si esperamos muchos accesos simultáneos a sesiones de ordenación pequeñas. Como antes, lo mejor es ir probando distintos valores y ver en qué pueden afectar a la paginación adversa. El valor hay que expresarlo en KB.

En nuestro ejemplo, hemos optado por usar un 4% de la memoria:

El 4% de 1 GB: 41943 KB   (1048576 KB*4)/100
work_men = 41943

Como instalar Oracle 11g sobre Centos 5

Lo primero sera ajustar los siguiente parametros en el kernel… para esto, bastara con modificar el fichero /etc/sysctl.conf.
Y agregar la siguientes lineas.

# Parametros requeridos para Oracle
kernel.shmall =  2147483648
kernel.shmmax  =  2147483648
kernel.sem    = 1024 64000 1024 1024
kernel.shmmni = 4096
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_default=4194304
net.core.rmem_max=4194304
net.core.wmem_default=262144
net.core.wmem_max=262144

Para que linux tome los cambios el kernel debemos ejecutar

$ sysctl -p

listo… si la anterior accion no te reporto ningun error, entonces podemos continuar.

Editemos tambien el archivo /etc/security/limits.conf :

* soft nproc 2047
* hard nproc 16384
* soft nofile 1024
* hard nofile 65536

En una consola de línea de comandos crear los directorios, usuarios y grupos requeridos por oracle:

$ mkdir /oracle && mkdir /oraInventory
$ groupadd dba && groupadd oinstall
$ useradd -c "Oracle software owner" -g oinstall -G dba oracle -d /home/oracle -s /bin/bash && passwd oracle
$ chown -R oracle.oinstall /oracle
$ chown -R oracle.oinstall /oraInventory

Una vez creado este usuario nos logeamos como el y procedemos a settear ( otro maldito verbo que no existe ) las variables de entorno que ha de requerir nuestra instalacion de Oracle y la ejecucacion de la base de datos en si. Asi que debemos adicinar estos valores en el archivo .bash_profile del usuario oracle.

export ORACLE_BASE=/oracle
export ORACLE_SID=ORA11
export ORACLE_HOME=$ORACLE_BASE/product/11.1.0/
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
export NLS_LANG=SPANISH_SPAIN.UTF8
unset USERNAME

Centos 5 no es una versión certificada, para que Oracle piense que se está instalando en un Oracle Linux Enterprise hacemos lo siguiente:

echo "Enterprise Linux Enterprise Linux AS release 4 (October Update 4)" > /etc/redhat-release

Ejecutamos la instalación ejecutando ./runInstaller y ahí es como una instalación normal.
Una vez finalizada la instalación dejaremos el archivo /etc/redhat-release como estaba con:

echo "CentOS release 5 (Final)" > /etc/redhat-release

Instalacion de Tomcat 6.0.16 en Slackware 12.1 con Java SE Development Kit 6u10 Beta b25

Instalando Java en el directorio HOME de un usuario
En ocaciones se ha desarrollado una app … que corre con cierta version de tomcat y cierta version de java..
Entonces… si tenemos un servidor que corra diferentes aplicaciones tomcat con diferentes versiones de java…
Entonces para que instalar un java global(me refieron a un version java que sea general para todos los usuarios)… por que no instalar un java para cada usuario que corra una aplicacion que requiere una version de tomcat y java especifica…

Aqui en este articulo blogero pedalero… les mostrare el como instalarce una version de java y tomcat recientes para un usarlo solo en el entorno que respecta al usuario llamado j4nusx


Nota:
he usado slackware… ya que es una distro muy sencilla y la corro en xen sin problemas… ademas… ademas de que slackware te permite adquirir un conocimiento total sobre el software que operas o compilas sobre el….

Bueno empecemos…

Lo primero sera agregar las siguientes variables al fichero $HOME/.bash_profile, en este fichero reside todo lo que respecta a la declaracion de variables del entorno que se cargaran cuando el usuario inicie una sesion.

export JAVA_HOME=/home/j4nusx/jdk1.6.0_10
export JRE_HOME=${JAVA_HOME}/jre
export PATH=$PATH:${JAVA_HOME}/bin
# La variable de tomcat la agregamos aqui para evitarnos el tener que agregarla despues..
export TOMCAT_HOME=${HOME}/apache-tomcat-6.0.16

Ahora me descarglo las version de jdk y apache tomcat que usare

j4nusx@mayte:~$ ls
apache-tomcat-6.0.16.tar.gz  jdk-6u10-beta-linux-i586.bin*  jdk1.6.0_10/

Procedo a instala jdk

j4nusx@mayte:~$  ./jdk-6u10-beta-linux-i586.bin

Si todo salio bien… podras ver algo como esto… si te has logeado una vez mas con el usuario j4nusx

j4nusx@mayte:~$ java -version
java version "1.6.0_10-beta"
Java(TM) SE Runtime Environment (build 1.6.0_10-beta-b25)
Java HotSpot(TM) Client VM (build 11.0-b12, mixed mode, sharing)

Bien.. bueno ya esta instalado y sin contratiempos…. ahora procedemos a instalar tomcat ( eres tu don gato ? )

Instalar la Versión Binaria de Tomcat

j4nusx@mayte:~$ tar -xvzf apache-tomcat-6.0.16.tar.gz

Arrancando Tomcat

j4nusx@mayte:~$ $TOMCAT_HOME/bin/startup.sh

Si arrancaste tomcat podras ver lo siguiente:

j4nusx@mayte:~/apache-tomcat-6.0.16/bin$ ./startup.sh
Using CATALINA_BASE:   /home/j4nusx/apache-tomcat-6.0.16
Using CATALINA_HOME:   /home/j4nusx/apache-tomcat-6.0.16
Using CATALINA_TMPDIR: /home/j4nusx/apache-tomcat-6.0.16/temp
Using JRE_HOME:       /home/j4nusx/jdk1.6.0_10/jre

Y en la tabla de procesos podras ver esto otro

/home/j4nusx/jdk1.6.0_10/jre/bin/java -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager

Parando Tomcat
Si desea para tomcat… bastara con invocar el siguiente script

j4nusx@mayte:~$ $TOMCAT_HOME/bin/shutdown.sh

Para verificar que tomcat esta ahi … de una manera visual… bastara con meter esta url a firefox http://localhost:8080

En mi Experiencia con Ruby on rails

Mucha gente se centra en procesos de ingeniería de requerimientos para conseguir mejores requerimientos con la esperanza de que esto prevenga la necesidad de cambiar el diseño más tarde. Pero incluso esta dirección no lleva a ninguna cura. Muchos cambios de requerimientos imprevistos ocurren debido a cambios del negocio. Aquellos no pueden ser prevenidos, incluso con un cuidadoso proceso de ingeniería de requerimientos.

Entonces todo esto hace que el diseño planificado parezca imposible. Seguramente estos son desafíos grandes. Pero no me inclino a decir que el diseño planificado es peor que el diseño evolutivo comúnmente practicado de la forma “codificar y arreglar “. De verdad prefiero el diseño planificado al ” codificar y arreglar “. Sin embargo soy consciente de los problemas del diseño planificado y busco una nueva dirección.

A razon de esto la propuesta de Rails me parece algo muy cercano a la utopica idea de un diseño que permita prevenir cualquier cambio en el futuro de un App web. Hago incapie en la palabra aplicacion web.En ningun momento lo recomiendo como una solucion general a toda la solucion tecnologica que se proponga a grandes necesidades.

Rails me parece perfecto. Para ser el participante ideal… en todas aquellas aplicaciones que deberian fungir como mecanismo de captura de los datos del dia a dia de los negocios que asi lo requieren…

Las aplicaciones en Java tienen la capacidad de formar parte de una solucion y a su vez ser todas partes de la misma.

Aunque rails nos permite crear aplicaciones web de una manera muy rapida este no cubrira todos las posibles encomiendas de una solucion.

« Entradas anteriores · Entradas mas recientes »