Estructuras Java

| lunes, 30 de marzo de 2009
Enumeraciones

En cualquier clase de colección, debe haber una forma de meter cosas y otra de sacarlas; después de todo, la principal finalidad de una colección es almacenar cosas. En un Vector, el método addElement() es la manera en que se colocan objetos dentro de la colección y llamando al método elementAt() es cómo se sacan. Vector es muy flexible, se puede seleccionar cualquier cosa en cualquier momento y seleccionar múltiples elementos utilizando diferentes índices.

Si se quiere empezar a pensar desde un nivel más alto, se presenta un inconveniente: la necesidad de saber el tipo exacto de la colección para utilizarla. Esto no parece que sea malo en principio, pero si se empieza implementando un Vector a la hora de desarrollar el programa, y posteriormente se decide cambiarlo a List, por eficiencia, entonces sí es problemático.

El concepto de enumerador, o iterador, que es su nombre más común en C++ y OOP, puede utilizarse para alcanzar el nivel de abstracción que se necesita en este caso. Es un objeto cuya misión consiste en moverse a través de una secuencia de objetos y seleccionar aquellos objetos adecuados sin que el programador cliente tenga que conocer la estructura de la secuencia . Además, un iterador es normalmente un objeto ligero, lightweight, es decir, que consumen muy pocos recursos, por lo que hay ocasiones en que presentan ciertas restricciones; por ejemplo, algunos iteradores solamente se puede mover en una dirección.

La Enumeration en Java es un ejemplo de un iterador con esas características, y las cosas que se pueden hacer son:

* Crear una colección para manejar una Enumeration utilizando el método elements(). Esta Enumeration estará lista para devolver el primer elemento en la secuencia cuando se llame por primera vez al método nextElement().
* Obtener el siguiente elemento en la secuencia a través del método nextElement().
* Ver si hay más elementos en la secuencia con el método hasMoreElements().

Y esto es todo. No obstante, a pesar de su simplicidad, alberga bastante poder. Para ver cómo funciona, el ejemplo java412.java, es la modificación de anterior, en que se utilizaba el método elementAt() para seleccionar cada uno de los elementos. Ahora se utiliza una enumeración para el mismo propósito, y el único código interesante de este nuevo ejemplo es el cambio de las líneas del ejemplo original

for( int i=0; i < coches.size(); i++ )
(( Coche )coches.elementAt( i ) ).print();

por estas otras en que se utiliza la enumeración para recorrer la secuencia de objetos

while( e.hasMoreElements() )
(( Coche )e.nextElement()).print();

Con la Enumeration no hay que preocuparse del número de elementos que contenga la colección, ya que del control sobre ellos se encargan los métodos hasMoreElements() y nextElement().

Tipos de Colecciones

Con el JDK 1.0 y 1.1 se proporcionaban librerías de colecciones muy básicas, aunque suficientes para la mayoría de los proyectos. En el JDK 1.2 ya se amplía esto y, además, las anteriores colecciones han sufrido un profundo rediseño. A continuación se verán cada una de ellas por separado para dar una idea del potencial que se ha incorporado a Java.

Vector


El Vector es muy simple y fácil de utilizar. Aunque los métodos más habituales en su manipulación son addElement() para insertar elementos en el Vector, elementAt() para recuperarlos y elements() para obtener una Enumeration con el número de elementos del Vector, lo cierto es que hay más métodos, pero no es el momento de relacionarlos todos, así que, al igual que sucede con todas las librerías de Java, se remite al lector a que consulte la documentación electrónica que proporciona Javasoft, para conocer los demás métodos que componen esta clase.

Las colecciones estándar de Java contienen el método toString(), que permite obtener una representación en forma de String de sí mismas, incluyendo los objetos que contienen. Dentro de Vector, por ejemplo, toString() va saltando a través de los elementos del Vector y llama al método toString() para cada uno de esos elementos. En caso, por poner un ejemplo, de querer imprimir la dirección de la clase, parecería lógico referirse a ella simplemente como this (los programadores C++ estarán muy inclinados a esta posibilidad), así que tendríamos el código que muestra el ejemplo java413.java y que se reproduce en las siguientes líneas.

import java.util.*;

public class java413 {
public String toString() {
return( "Direccion del objeto: "+this+"\n" );
}

public static void main( String args[] ) {
Vector v = new Vector();

for( int i=0; i < 10; i++ )
v.addElement( new java413() );
System.out.println( v );
}
}

El ejemplo no puede ser más sencillo, simplemente crea un objeto de tipo java413 y lo imprime; sin embargo, a la hora de ejecutar el programa lo que se obtiene es una secuencia infinita de excepciones. Lo que está pasando es que cuando se le indica al compilador:

"Direccion del objeto: "+this

el compilador ve un String seguido del operador + y otra cosa que no es un String, así que intenta convertir this en un String. La conversión la realiza llamando al método toString() que genera una llamada recursiva, llegando a llenarse la pila.

Si realmente se quiere imprimir la dirección del objeto en este caso, la solución pasa por llamar al método toString() de la clase Object. Así, si en vez de this se coloca super.toString(), el ejemplo funcionará. En otros casos, este método también funcionará siempre que se esté heredando directamente de Object o, aunque no sea así, siempre que ninguna clase padre haya sobreescrito el método toString().

BitSet

Se llama así lo que en realidad es un Vector de bits. Lo que ocurre es que está optimizado para uso de bits. Bueno, optimizado en cuanto a tamaño, porque en lo que respecta al tiempo de acceso a los elementos, es bastante más lento que el acceso a un array de elementos del mismo tipo básico.

Además, el tamaño mínimo de un BitSet es de 64 bits. Es decir, que si se está almacenando cualquier otra cosa menor, por ejemplo de 8 bits, se estará desperdiciando espacio.

En un Vector normal, la colección se expande cuando se añaden más elementos. En el BitSet ocurre los mismo pero ordenadamente. El ejemplo java414.java, muestra el uso de esta colección.

Se utiliza el generador de números aleatorios para obtener un byte, un short y un int, que son convertidos a su patrón de bits e incorporados al BitSet.

Stack


Un Stack es una Pila, o una colección de tipo LIFO (last-in, first-out). Es decir, lo último que se coloque en la pila será lo primero que se saque. Como en todas las colecciones de Java, los elementos que se introducen y sacan de la pila son Object, así que hay que tener cuidado con el moldeo a la hora de sacar alguno de ellos.

Los diseñadores de Java, en vez de utilizar un Vector como bloque para crear un Stack, han hecho que Stack derive directamente de Vector, así que tiene todas las características de un Vector más alguna otra propia ya del Stack. El ejemplo siguiente, java415.java, es una demostración muy simple del uso de una Pila que consisten en leer cada una de las líneas de un array y colocarlas en un String.

Cada línea en el array diasSemana se inserta en el Stack con push() y posteriormente se retira con pop(). Para ilustrar una afirmación anterior, también se utilizan métodos propios de Vector sobre el Stack. Esto es posible ya que en virtud de la herencia un Stack es un Vector, así que todas las operaciones que se realicen sobre un Vector también se podrán realizar sobre un Stack, como por ejemplo, elementAt().

Hashtable

Un Vector permite selecciones desde una colección de objetos utilizando un número, luego parece lógico pensar que hay números asociados a los objetos. Bien, entonces ¿qué es lo que sucede cuando se realizan selecciones utilizando otros criterios? Un Stack podría servir de ejemplo: su criterio de selección es "lo último que se haya colocado en el Stack". Si rizamos la idea de "selección desde una secuencia", nos encontramos con un mapa, un diccionario o un array asociativo. Conceptualmente, todo parece ser un vector, pero en lugar de acceder a los objetos a través de un número, en realidad se utiliza otro objeto. Esto nos lleva a utilizar claves y al procesado de claves en el programa. Este concepto se expresa en Java a través de la clase abstracta Dictionary. El interfaz para esta clase es muy simple:

* size(), indica cuántos elementos contiene,
* isEmpty(), es true si no hay ningún elemento,
* put( Object clave,Object valor), añade un valor y lo asocia con una clave
* get( Object clave ), obtiene el valor que corresponde a la clave que se indica
* remove( Object clave ), elimina el par clave-valor de la lista
* keys(), genera una Enumeration de todas las claves de la lista
* elements(), genera una Enumeration de todos los valores de la lista

Todo es lo que corresponde a un Diccionario (Dictionary), que no es excesivamente difícil de implementar. El ejemplo java416.java es una aproximación muy simple que utiliza dos Vectores, uno para las claves y otro para los valores que corresponden a esas claves.

import java.util.*;

public class java416 extends Dictionary {
private Vector claves = new Vector();
private Vector valores = new Vector();
public int size() {
return( claves.size() );
}
public boolean isEmpty() {
return( claves.isEmpty() );
}

public Object put( Object clave,Object valor ) {
claves.addElement( clave );
valores.addElement( valor );
return( clave );
}

public Object get( Object clave ) {
int indice = claves.indexOf( clave );
// El metodo indexOf() devuelve -1 si no encuentra la clave que se
// esta buscando
if( indice == -1 )
return( null );
return( valores.elementAt( indice ) );
}

public Object remove(Object clave) {
int indice = claves.indexOf( clave );

if( indice == -1 )
return( null );
claves.removeElementAt( indice );
Object valorRetorno = valores.elementAt( indice );
valores.removeElementAt( indice );
return( valorRetorno );
}

public Enumeration keys() {
return( claves.elements() );
}

public Enumeration elements() {
return( valores.elements() );
}

// Ahora es cuando se prueba el ejemplo
public static void main( String args[] ) {
java416 ej = new java416();
for( char c='a'; c <= 'z'; c++ )
ej.put( String.valueOf( c ),String.valueOf( c ).toUpperCase() );

char[] vocales = { 'a','e','i','o','u' };
for( int i=0; i < vocales.length; i++ )
System.out.println( "Mayusculas: " +
ej.get( String.valueOf( vocales[i] ) ) );
}
}

La primera cosa interesante que se puede observar en la definición de java416 es que extiende a Dictionary. Esto significa que java416 es un tipo de Diccionario, con lo cual se pueden realizar las mismas peticiones y llamar a los mismos métodos que a un Diccionario. A la hora de construirse un Diccionario propio todo lo que se necesita es rellenar todos los métodos que hay en Dictionary. Se deben sobreescribir todos ellos, excepto el constructor, porque todos son abstractos.

Los Vectores claves y valores están relacionados a través de un número índice común. Es decir, si se llama al método put() con la clave "león" y el valor "rugido" en la asociación de animales con el sonido que producen, y ya hay 100 elementos en la clase java416, entonces "león" será el elemento 101 de claves y "rugido" será el elemento 101 de valores. Y cuando se pasa al método get() como parámetro "león", genera el número índice con claves.indexOf(), y luego utiliza este índice para obtener el valor asociado en el vector valores.

Para mostrar el funcionamiento, en main() se utiliza algo tan simple como mapear las letras minúsculas y mayúsculas, que aunque se pueda hacer de otras formas más eficientes, sí sirve para mostrar el funcionamiento de la clase, que es lo que se pretende por ahora.

La librería estándar de Java solamente incorpora una implementación de un Dictionary, la Hashtable. Esta Hashtable tiene el mismo interfaz básico que la clase del ejemplo anterior java416, ya que ambas heredan de Dictionary, pero difiere en algo muy importante: la eficiencia. Si en un Diccionario se realiza un get() para obtener un valor, se puede observar que la búsqueda es bastante lenta a través del vector de claves. Aquí es donde la Hashtable acelera el proceso, ya que en vez de realizar la tediosa búsqueda línea a línea a través del vector de claves, utiliza un valor especial llamado código hash. El código hash es una forma de conseguir información sobre el objeto en cuestión y convertirlo en un int relativamente único para ese objeto. Todos los objetos tienen un código hash y hashCode() es un método de la clase Object. Una Hashtable coge el hashCode() del objeto y lo utiliza para cazar rápidamente la clave. El resultado es una impresionante reducción del tiempo de búsqueda. La forma en que funciona una tabla Hash se escapa del Tutorial, hay muchos libros que lo explican en detalle, por ahora es suficiente con saber que la tabla Hash es un Diccionario muy rápido y que un Diccionario es una herramienta muy útil.

Para ver el funcionamiento de la tabla Hash está el ejemplo java417.java, que intenta comprobar la aleatoriedad del método Math.random(). Idealmente, debería producir una distribución perfecta de números aleatorios, pero para poder comprobarlo sería necesario generar una buena cantidad de números aleatorios y comprobar los rangos en que caen. Una Hashtable es perfecta para este propósito al asociar objetos con objetos, en este caso, los valores producidos por el método Math.random() con el número de veces en que aparecen esos valores.

En el método main() del ejemplo, cada vez que se genera un número aleatorio, se convierte en objeto Integer para que pueda ser manejado por la tabla Hash, ya que no se pueden utilizar tipos básicos con una colección, porque solamente manejan objetos. El método containsKey() comprueba si la clave se encuentra ya en la colección. En caso afirmativo, el método get() obtiene el valor asociado a la clave, que es un objeto de tipo Contador. El valor i dentro del contador se incrementa para indicar que el número aleatorio ha aparecido una vez más.

Si la clave no se encuentra en la colección, el método put() colocará el nuevo par clave-valor en la tabla Hash. Como Contador inicializa automáticamente su variable i a 1 en el momento de crearla, ya se indica que es la primera vez que aparece ese número aleatorio concreto.

Para presentar los valores de la tabla Hash, simplemente se imprimen. El método toString() de Hashtable navega a través de los pares clave-valor y llama a método toString() de cada uno de ellos. El método toString() de Integer está predefinido, por lo que no hay ningún problema en llamar a toString() para Contador. Un ejemplo de ejecución del programa sería la salida que se muestra a continuación:

%java java417
{19=526, 18=533, 17=460, 16=513, 15=521, 14=495, 13=512, 12=483,
11=488, 10=487, 9=514, 8=523, 7=497, 6=487, 5=489, 3=509, 2=503,
1=475, 0=505}

Al lector le puede parecer superfluo el uso de la clase Contador, que parece que no hace nada que no haga ya la clase Integer. ¿Por qué no utilizar int o Integer? Pues bien, int no puede utilizarse porque como ya se ha indicado antes, las colecciones solamente manejan objetos, por ello están las clases que envuelven a esos tipos básicos y los convierten en objetos. Sin embargo, la única cosa que pueden hacer estas clases es inicializar los objetos a un valor determinado y leer ese valor. Es decir, no hay modo alguno de cambiar el valor de un objeto correspondiente a un tipo básico, una vez que se ha creado. Esto hace que la clase Integer sea inútil para resolver el problema que plantea el ejemplo, así que la creación de la clase Contador es imprescindible. Quizás ahora que el lector sabe que no puede colocar objetos creados a partir de las clases correspondientes a tipos básicos en colecciones, estas clases tengan un poco menos de valor, pero... la vida es así, por un lado da y por otro quita... y Java no va a ser algo diferente.

En el ejemplo se utiliza la clase Integer, que forma parte de la librería estándar de Java como clave para la tabla Hash, y funciona perfectamente porque tiene todo lo necesario para funcionar como clave. Pero un error muy común se presenta a la hora de crear clases propias para que funcionen como claves. Por ejemplo, supóngase que se quiere implementar un sistema de predicción del tiempo en base a objetos de tipo Oso y tipo Prediccion, para detectar cuando entra la primavera. Tal como se muestra en el ejemplo java418.java, la cosa parece muy sencilla, se crean las dos clases y se utiliza Oso como clave y Prediccion como valor.

Cada Oso tendrá un número de identificación, por lo que sería factible buscar una Prediccion en la tabla Hash de la forma: "Dime la Prediccion asociada con el Oso número 3". La clase Prediccion contiene un booleano que es inicializado utilizando Math.random(), y una llamada al método toString() convierte el resultado en algo legible. En el método main(), se rellena una Hashtable con los Osos y sus Predicciones asociadas. Cuando la tabla Hash está completa, se imprime. Y ya se hace la consulta anterior sobre la tabla para buscar la Prediccion que corresponde al Oso número 3.

Esto parece simple y suficiente, pero no funciona. El problema es que Oso deriva directamente de la clase raíz Object, que es lo que ocurre cuando no se especifica una clase base, que en última instancia se hereda de Object. Luego es el método hashCode() de Object el que se utiliza para generar el código hash para cada objeto que, por defecto, utiliza la dirección de ese objeto. Así, la primera instancia de Oso(3) no va a producir un código hash igual que producirá una segunda instancia de Oso(3), con lo cual no se puede utilizar para obtener buenos resultados de la tabla.

Se puede seguir pensando con filosofía ahorrativa y decir que todo lo que se necesita es sobreescribir el método hashCode() de la forma adecuada y ya está. Pero, esto tampoco va a funcionar hasta que se haga una cosa más: sobreescribir el método equals(), que también es parte de Object. Este es el método que utiliza la tabla Hash para determinar si la clave que se busca es igual a alguna de las claves que hay en la tabla. De nuevo, el método Object.equals() solamente compara direcciones de objetos, por lo que un Oso(3) probablemente no sea igual a otro Oso(3).

Por lo tanto, a la hora de escribir clases propias que vayan a funcionar como clave en una Hastable, hay que sobreescribir los métodos hashCode() y equals(). El ejemplo java419.java ya se incorporan estas circunstancias.

import java.util.*;

// Si se crea una clase que utilice una clave en una Tabla Hash, es
// imprescindible sobreescribir los metodos hashCode() y equals()
// Utilizamos un oso para saber si está hibernando en su temporada de
// invierno o si ya tine que despertarse porque le llega la primavera
class Oso2 {
int numero;
Oso2( int n ) {
numero = n;
}

public int hashCode() {
return( numero );
}

public boolean equals( Object obj ) {
if( (obj != null) && (obj instanceof Oso2) )
return( numero == ((Oso2)obj).numero );
else
return( false );
}
}

// En función de la oscuridad, o claridad del día, pues intenta saber si
// ya ha la primavera ha asomado a nuestras puertas
class Prediccion {
boolean oscuridad = Math.random() > 0.5;

public String toString() {
if( oscuridad )
return( "Seis semanas mas de Invierno!" );
else
return( "Entrando en la Primavera!" );
}
}

public class java419 {
public static void main(String args[]) {
Hashtable ht = new Hashtable();

for( int i=0; i < 10; i++ )
ht.put( new Oso2( i ),new Prediccion() );
System.out.println( "ht = "+ht+"\n" );

System.out.println( "Comprobando la prediccion para el oso #3:");
Oso2 oso = new Oso2( 3 );
if( ht.containsKey( oso ) )
System.out.println( (Prediccion)ht.get( oso ) );
}
}

El método hashCode() devuelve el número que corresponde a un Oso como un identificador, siendo el programador el responsable de que no haya dos números iguales. El método hashCode() no es necesario que devuelva un identificador, sino que eso es necesario porque equals() debe ser capaz de determinar estrictamente cuando dos objetos son equivalentes.

El método equals() realiza dos comprobaciones adicionales, una para comprobar si el objeto es null, y, en caso de que no lo sea, comprobar que sea una instancia de Oso, para poder realizar las comparaciones, que se basan en los números asignados a cada objeto Oso. Cuando se ejecuta este nuevo programa, sí se produce la salida correcta. Hay muchas clases de la librería de Java que sobreescriben los métodos hashCode() y equals() basándose en el tipo de objetos que son capaces de crear.

Las tablas Hash son utilizadas también por muchas clases de la librería estándar de Java, por ejemplo, para obtener las propiedades del sistema se usa la clase Properties que hereda directamente de Hashtable. Y además, contiene una segunda Hashtable en donde guarda las propiedades del sistema que se usan por defecto.

Firefox 3.0.8 disponible

| sábado, 28 de marzo de 2009


Hace solamente dos días fue noticia una vulnerabilidad en Firefox considerada como crítica por Mozilla. La misma, descubierta por el hacker italiano Giudo Landi, provocaba un fallo en el navegador al ejecutar un archivo XML malicioso. A raiz de ello la gente de Mozilla se ha adelantado y acaba de ser publicado Firefox 3.0.8 que soluciona este y otros problemas de seguridad.

Seguramente te aparezca un mensaje de actualización durante las próximas horas, o puedes ir al menú Ayuda - Buscar actualizaciones para realizar la actualización manualmente. Si no quieres esperar ya puedes descargarte la nueva versión desde el siguiente enlace:

Descargar Firefox 3.0.8

Crea contraseñas más seguras

|


La elección de una buena contraseña para cualquier cosa, especialmente en la web, siempre es un pequeño dolor de cabeza. Las características que debe tener una buena contraseña para que sea segura (es decír, difícil de averiguar ya sea por medios técnicos o por ingeniería social) son:

* Que sea fácil de recordar.
* Que sea larga (casi todos los servicios piden, como mínimo, 8 caracteres)
* Que alterne signos, números y letras en mayúsculas y minúsculas.
* Que no contenga información personal tuya que sea pública (es decir, que hayas publicado en Internet) o que sea fácil de obtener (“Estamos haciendo una encuesta…”).
*
Que sea rápida de escribir (esto no se comenta mucho, pero… ¿a qué prefieres no tardar mucho cada vez que entras en tu servicio web favorito?)

Estas características casi son excluyentes entre ellas. ¿Cómo alcanzar un equilibrio combinándolas para que crear una contraseña que sea fácil de recordar al tiempo que sea segura y relativamente corta, para que no nos lleve horas (y varios errores) entrar a un servicio?

En Make use of, Damien Oh nos propone un método muy curioso para ello. Veámoslo resumido (o pásate por allí para leer la entrada original) y con alguna que otra aportación del que suscribe.

- Elige un término personal, que no vayas a olvidar. Preferiblemente, que sea corto. Sí, sí, ya sé que he dicho que una contraseña debe ser larga… Déjame terminar. Yo voy a elegir uno poco original: mi casa.

- Sustituye las letras de tu término elegido de la siguiente manera:

* las “a” por @
* las “s” por $
* Los espacios por %
* Las “o” por 0 (cero)
* Las “i” por ¡ (en el original dice “!”, pero ya que en español tenemos signo de apertura en las exclamaciones, aprovechémoslo).

De esta forma, mi casa se transforma en m¡%c@s@.

- A continuación, añade el nombre del servicio para el cual creas la contraseña. Por ejemplo, si la contraseña anterior fuera para Gmail, podría ser m¡%c@s@gm@¡l.

Y eso es todo. Damien propone también cambiar el orden de los términos (el término elegido y el nombre del servicio), y aunque a mí me parece rizar el rizo, no me parece mal tenerlo en cuenta por si acaso, que los ladrones de cuentas andan al acecho de cualquier descuido que tengamos.

Proyecto Autodidacta

Qué significan los emoticonos más usados

|


Un emoticono es un conjunto de signos de puntuación que, agrupados, tratan de reflejar el matiz de una frase que puede ser difícil de apreciar pero que, si la misma fuese realizada verbalmente, podríamos distinguir gracias a la entonación.

Aunque no sean perfectos, sirven para aligerar la carga de una frase o para enfatizar una de las maneras en que puede ser interpretada. El texto puede resultar en ocasiones muy frío y una simple frase puede interpretarse de muchas maneras. Por ejemplo, la frase…

Ya era hora de que terminaras




… puede parecer una recriminación y “sonar” algo brusca. Pero si le añadimos un emoticono…

Ya era hora de que terminaras :)



… estamos ayudando a matizar que la frase es dicha sin acritud, de buen humor y sin que “suene” a reprimenda.

Para interpretarlos, todo lo que tenemos que hacer es girarlos imaginariamente hacia la derecha en nuestra cabeza. De esa forma, un :) se transformará en una cara sonriente.

Los emoticonos más comunes suelen construirse con dos o tres signos, dependiendo de la persona. Los de tres signos lo que suelen hace es añadir una nariz para que resulte más claro. De esa forma, a la cara sonriente :) se le añade una nariz :-) para que parezca más una cara que dos puntos seguidos de un paréntesis.

A pesar de la gran variedad de emoticonos que existe, tan sólo se utilizan unos pocos de manera regular. La imaginación de los usuarios ha hecho que aparezcan muchos que, aunque ingeniosos, son de difícil interpretación. A continuación, veamos qué emoticonos se suelen usar habitualmente en las conversaciones, correos e incluso entradas de blogs con más asiduidad:








































:)


:-)

Sonrisa: emplealo cuando la frase pueda ser malinterpretada.
;)


;-)

Guiño: úsalo cuando quieras reflejar complicidad o ironía.
:D


:-D

Carcajada: refleja que lo que se ha dicho o lo que dices te causa mucha risa.
XD


X-D

Muerto de la risa: pues eso, que te mueres de risa con lo que se ha dicho o con lo que dices.
:(


:-(

Tristeza: lo que dices, lo dices con pena; o demuestras tu pesar ante lo que se dice.
:o


:-o

Sorpresa: lo que dicen te sorprende, te asombra.
:p


:-p

Sacando la lengua: úsalo cuando quieras añadir algo de burla, broma, cachondeo…
^_^Felicidad: úsalo para demostrar que te sientes contento.


Proyecto Autodidacta

Como ser un buen autodidacta

|



No importa que tan largo, intensivo o profundo sea el curso que sigamos: en esto de la informática la formación debe ser continua. A cada rato aparecen nuevos programas y nuevas tecnologías que nos exigen actualizarnos con rapidez para poder sacarles el mayor rendimiento. Por ello, es necesario contar con una cierta “vena” autodidacta, un impulso que nos lleve a tratar de aprender las cosas por nosotros mismos, con nuestros propios recursos.

En esta entrada, reciclada de una que escribí hace tiempo para una de las encarnaciones pasadas de esta web, vamos a ver algunos consejos que te pueden ser útiles a la hora de enfrentarte a un programa o hasta a todo un sistema operativo de manera que aprendas a manejarlo de una manera que te resulte productiva, entretenida e interesante.

Aunque recibir clases formales siempre resulta de utilidad, aprender algo por nosotros mismos es, en muchos casos, más enriquecedor. El proceso de descubrimiento y aplicación permite que el conocimiento se afiance más y, algo nada desdeñable, nos sentimos mucho más orgullosos de nosotros mismos.

Entonces, hagamos un ejercicio de imaginación: estás frente a un programa cuyas posibilidades te entusiasman y al que quieres sacarle partido de manera que chorree bits por sus costados. Acabas de instalarlo y entonces…

1.- Explora el programa, haz clic por todas partes, cambia valores y configuraciones. Si estás explorando el sistema operativo, ten cuidado con algunas cosas. Generalmente, los sistemas suelen avisar cuando se van a realizar cambios importantes que pueden dejarle inservible o producir problemas, así que ten mucho ojo y lee los cuadros de aviso que vayan apareciendo (esto es sobre todo para Windows).

2.- Usa la ayuda del programa. Si bien explorar es una actividad sumamente productiva, en ocasiones nos vamos a topar con que no encontramos la función que buscamos en el programa, a pesar de que sabemos que la tiene o, por lo menos, lo suponemos (por ejemplo, un procesador de textos casi seguro que ha de contar con una opción para cambiar el tipo de letra). En ese momento es cuando debemos recurrir a la ayuda del programa. Es increíble la cantidad de veces que nos olvidamos o deseñamos las ayudas que acompañan al software. Si están ahí es para algo.

3.- Anota todo lo que descubras. Sí, ANOTA. Se puede decir más alto pero no más claro. Apunta en un cuaderno o en un archivo de texto todos los descubrimientos que vayas haciendo, sobre todo si estamos hablando de cambiar configuraciones y cosas así. No hace falta que te explayes en detalles. Anota simplemente el camino que hayas seguido para hacer determinada cosa y, si has cambiado algún valor, apunta el valor que has utilizado.

Cada uno tiene su propia manera de anotar. Personalmente, suelo usar un cuaderno donde anoto todo, cualquier cosa, una detrás de otra. En lugar de dividirlo en secciones, lo tengo dividido en páginas. Por ejemplo, lo relacionado con el blog, le pongo como título "Blog" en la parte superior de la página y comienzo a escribir. Si de pronto necesito hacer anotaciones sobre, por decir algo, programas, en la segunda hoja (que sería la tercera página) le pongo "Programas" en la parte de arriba y escribo. Cuando termine la primera hoja de blogs, paso a la tercera hoja del cuaderno, le pongo el título "Blog" y continúo escribiendo. Y así continúo, creando una nueva sección a medida que voy avanzando por el cuaderno.

En otras ocasiones, recurro a un archivo de texto, especialmente cuando quiero registrar cosas que he leído en otras webs y que, tras probarlas, deseo conservar. Lo suelo hacer principalmente en materia de sistemas operativos (principalmente GNU/Linux) a los que no estoy acostumbrado.

En cuanto a las instrucciones o características de un programa concreto, sencillamente escribo primero el nombre del programa en mayúsculas y a continuación las instrucciones o los valores que quiero conservar, o cualquier tontería que pueda necesitar después.

Una manera muy práctica de anotar la manera de hacer determinada cosa en un programa es apuntando todos los sitios donde debes hacer clic o seleccionar separados por el signo ">" (mayor qué): Formato > Caracter > Fuente.

Anotar produce un curioso efecto que más de uno tiene que haber notado alguna vez: si lo escribimos, no se nos olvida (o tarda más en olvidarse); si no lo escribimos, lo olvidamos con rapidez. Esto puede atribuirse (aunque, por lo que he leído, no está del todo comprobado) a que en nuestro cerebro exista una zona que retiene el recuerdo del sonido y la imagen pero no el pensamiento puro, de manera que el acto de escribir lo que queremos recordar se retiene mejor (lo leí en "Los dragones del edén", de Carl Sagan). Sea por lo que sea, es un efecto que ocurre muy habitualmente, así que no hay que desdeñarlo: anota.

4.- Hazlo todo con un objetivo concreto y útil. Explora, usa la ayuda y anota tus descubrimientos pero hazlo con un objetivo. El problema de explorar es que si no se tiene un objetivo concreto, nos aburrimos con rapidez. Planteate hacer algo, lo que sea, y si es posible que te sea útil de alguna manera. Por ejemplo, si tienes un nuevo programa de gráficos, proponte hacer un montaje fotográfico con esas fotos que tomaste en las vacaciones o con esas imágenes que tanto te gustan y luego úsalo como papel tapiz. Se aprende el triple cuando se tiene un objetivo que cuando se explora sin rumbo fijo.

5.- Recurre a Internet. Cuando te atasques en un procedimiento, busca por la red de redes. Preferiblemente, busca tutoriales y manuales. Y si son descargables, mejor. Así podrás consultarlos cuando no estés conectado e incluso compartirlos. A la hora de hacer la búsqueda, escribe siempre un verbo en infinitivo, algunas características de lo que quieres hacer, el nombre del programa (a veces es necesaria hasta la versión); por ejemplo: crear botón Gimp. Si lo que quieres es algo que hable de muchas características del programa, escribe el nombre del programa y la palabra tutorial o manual; por ejemplo: Gimp manual. ¡Ah! y no te olvides realizar la búsqueda primero en tu idioma, pero si no encuentras lo que buscas, intenta con el inglés: hay mucho material en el idioma de Shakespeare.

Advertencia sobre los sistemas operativos:



Aunque resulta de mucha utilidad la exploración, a la hora de efectuarla en un sistema operativo los resultados pueden ser desastrosos si no sabemos a ciencia cierta qué estamos haciendo, especialmente en GNU/Linux. Por eso, quisiera resaltar los siguientes puntos:

Anota lo que haces y los valores originales que cambias. No será la primera vez que explorando me cargo una configuración. Ahórrate lamentos y apunta los pasos que sigues y los valores originales cuando vayas a cambiar algo de importancia. Una manera de identificar algo muy importante es porque es difícil llegar hasta ello (pero no tomes esto como una regla inalterable).

Documéntate primero: a menos que sea un sistema muy reciente, seguro que encuentras abundante información en la web acerca de lo que quieres hacer. Y, como no, recurre primero a la ayuda del sistema antes de conectarte.

Cubre las necesidades a medida que aparecen: explorar un sistema es algo muy aburrido, y como nos cansamos pronto, eso nos puede ayudar a alejarnos de peligros innecesarios. Un sistema se aprende usándolo, eso suele ocurrir en el día a día, durante el transcurso de diferentes tareas. Un sistema operativo es, al fin y al cabo, tan sólo la base donde se colocan lo que nos permite realizar nuestro trabajo: los programas. Por eso, lo mejor que puedes hacer es ir descubriendo como se hacen determinadas cosas a medida que lo necesitas, en lugar de tratar de averiguarlas sin más. Por ejemplo, si después de unos días descubres que el tamaño de la hora que muestra el reloj te molesta porque no puedes verla bien, averigua como cambiarlo.

Usa un live CD: esto es aplicable para distribuciones GNU/Linux. Los live CD permiten cargar un sistema operativo en una computadora sin necesidad de instalarlo. Generalmente, si luego así lo queremos, podemos dejarlo instalado sin mucha complicación. Esto nos permite probar nuevos sistemas con facilidad y sin correr ningún riesgo.

Fuente:Proyecto Autodidacta

No Te Quedes En El 2001 , Usa Linux

| viernes, 27 de marzo de 2009
Una de las cosas que argumento a mis amigos para dar el paso de cambiarse a Windows es la antiguedad de este sistema, todos sabemos que en el mundo de las tecnologias hay que mantenerse inovadores, en medio año muchas de las cosas que conocemos se vuelven practicamente obsoletas.

Entonces ¿Por qué seguir usando Windows? Todos sabemos que Windows Vista es un mal sistema operativo, no tiene nada de innovador, por el contrario es lento, exige grandes recursos y provoca incompatibilidades serias con programas y hardware, muchos por ello deciden regresarse a Windows XP ya que es el unico que conocen.

Pero Windows XP salio al mercado en el año 2001, es decir han pasado ya casi 8 años desde su salida, por lo que lógicamente estamos hablando de un sistema operativo obsoleto. En cambio GNU/Linux es un sistema que cuenta con cientos de distribuciones, cada una actualizandose cada pocos meses con nuevas versiones y nuevas caracteristicas.

Esto lo he visto reflejado en un video de Facundo Arena que explica el porque pasarse a Linux:

RedUSERS TV: "No te quedes en el 2001, usá Linux" from Sergio Vallejo on Vimeo

Vídeo: ¿Qué es Linux?

|
He encontrado un vídeo que explica a grandes rasgos lo que es Linux para los que no lo conocen aún.



Como dicén en el video, siendo un sistema operativo que promete ser mejor que el que seguramente utilizas actualmente (Windows) y siendo gratuito y de facíl instalación, ¿por qué no probarlo? Solo dale una oportunidad para aprender un poco más, y olvidarte de los virus y la inestabilidad.