27
Dec 16

Pildoritas de POO y Java: Polimorfismo

pildoras poo java
Llevo casi desde que comencé con las pildoritas de POO anunciando que "el polimorfismo va a llegaaaaar" y nada, que no llegaba...¡hasta hoy!

El polimorfismo va muy ligado a la herencia, y se apoya en ella para poder generalizar comportamientos de diferentes clases, como si de una se tratara, siendo para nosotros transparente su tipo, siempre y cuando éste herede de una clase Padre común que define la funcionalidad generalizada.

Polimorfismo

El Polimorfismo es el envío de mensajes a objetos de tipos diferentes utilizando la misma sintaxis. En lenguajes con un sistema de tipos dinámicos, es decir, que una variable puede contener todo tipo de valores y su tipo se setea en tiempo de ejecución. No es necesario el uso de herencia para aplicar el polimorfismo pero en lenguajes fuertemente tipados como Java es necesario utilizar una clase común padre de la cual heredarán todos los objetos polimórficos.

Por ejemplo, basándonos en el ejemplo de nuestra anterior pildorita de Herencia, las clases Profesor y Alumno heredan de Persona varios métodos comunes, como el método toString, que además reimplementan de forma específica cada clase hijo a través de la anotación @Override.

Ahora imaginemos que tenemos un método auxiliar en nuestra aplicación que se dedica a mostrar los datos por pantalla de cualquier persona vinculada a la Escuela, Universidad...¿Cómo lo haríamos de forma general utilizando polimorfismo?

public void mostrarDatos() {
		Profesor profe1 = new Profesor(1, "Antonio", "Brena", "1111111K", 52, "M");
		Profesor profe2 = new Profesor(2, "Alicia", "Hernandez", "2222222K", 45, "F");
		Alumno alumno1 = new Alumno(1, "Mar", "Millan", "44444444K", 29, "F");
		Persona trabajador1 = new Persona("Francisco", "García", "33333333K", 39, "M");
		
		List<Persona> lsPersonas = new ArrayList<Persona>();
		lsPersonas.add(profe1);
		lsPersonas.add(profe2);
		lsPersonas.add(alumno1);
		lsPersonas.add(trabajador1);

		for (Persona per : lsPersonas) {
			System.out.println(per.toString());
		}		
	}

El resultado de ejecutar este método es el siguiente:

DATOS DEL PROFESOR:
Nombre: Antonio
Apellidos: Brena
DNI: 1111111K
Edad: 52
Sexo: M

DATOS DEL PROFESOR:
Nombre: Alicia
Apellidos: Hernandez
DNI: 2222222K
Edad: 45
Sexo: F

DATOS DEL ALUMNO:
Nombre: Mar
Apellidos: Millan
DNI: 44444444K
Edad: 29
Sexo: F

DATOS DE LA PERSONA:
Nombre: Francisco
Apellidos: García
DNI: 33333333K
Edad: 39
Sexo: M

Como se puede observar, para nosotros es indiferente el tipo del objeto que estemos invocando, ya que sabemos que todos esos objetos al heredar de la clase padre Persona tendrán obligatoriamente el método toString. Así mismo, si uno de esos objetos tiene una implementación propia de dicho método, ejecutará la implementación especifica de forma transparente para nosotros.

Aquellos lenguajes que tengan interfaces (como es el caso de Java), pueden también implementar el polimorfismo utilizando este recurso, lo que se conoce como composición de objetos. Esta alternativa se considera mejor práctica a la hora de aplicar polimorfismo que el uso de herencia, ya que este solución sólo obliga a que las diferentes clases compartan el tipo y obligatoriedad de implementar los métodos del interfaz, pero no se comparten comportamientos ni atributos. Pero, ¿qué es una interfaz?

Interfaces y Clases Abstractas

Cuando queremos unificar atributos y métodos en una clase padre, como hemos hecho en la clase Persona, pero no queremos que ésta sea instanciable, crearíamos nuestra clase Persona como clase abstracta:

public abstract class Persona {
	 
    private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
    
    Persona() {
    	super();
    }
    
    public Persona(String nombre, String apellidos, String dni, Integer edad, String sexo) {
    	super();
    	this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
    }
    
    public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    public String getApellidos() {
        return apellidos;
    }
 
    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }
 
    public String getDni() {
        return dni;
    }
 
    public void setDni(String dni) {
        this.dni = dni;
    }
 
    public Integer getEdad() {
        return edad;
    }
 
    public void setEdad(Integer edad) {
        this.edad = edad;
    }
 
    public String getSexo() {
        return sexo;
    }
 
    public void setSexo(String sexo) {
        this.sexo = sexo;
    }
    
    @Override 
    public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DE LA PERSONA: " + nuevalinea + 
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
    }
    
	@Override
	public boolean equals(Object object) {
		final Persona aux = (Persona) object;
		if (this == object)
	           return true;
		else if (object == null)
	           return false;
		else if (getClass() != object.getClass())
	           return false;
		else if (this.dni.equals(aux.getDni())) {
			return true;
		} else {
			return false;
		}
	}

     public abstract void metodoAbstracto();
}

Por tanto, en nuestro anterior ejemplo tendríamos un error al crear el objeto Persona trabajador1, ya que, como hemos dicho, las clases abstractas no pueden ser instanciadas:

También podemos añadir métodos abstractos. Un ejemplo de ello es el último método que hemos creado en el ejemplo de la clase abstracta Persona, el método metodoAbstracto(), que como se puede observar siquiera tiene cuerpo. Si creamos un método abstracto estaremos obligados a definir la implementación de dicho método en las clases hijas.

¿Y qué es una interfaz? Pues una clase completamente abstracta, es decir, una clase en la que no se implementan métodos, ni hay atributos, excepto aquellos que sean estáticos y/o constantes.

Los interfaces tienen como finalidad definir la forma y comportamiento de una clase.

Por ejemplo, podríamos tener una interfaz IMamifero, que implemente Persona:

public interface IMamifero {
	public void crecer();
	public void reproducirse();
	public void morir();
}

Para que nuestra clase implemente este interfaz, lo indicaremos a través de la palabra reservada implements.

Al hacer esto, como se puede ver en la anterior imagen, tendremos un error en la mayoría de entornos que nos indicará que tenemos que implementar forzosamente los métodos definidos en el interfaz IMamifero:

public class Persona implements IMamifero {
	 
    private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
    
    Persona() {
    	super();
    }
    
    public Persona(String nombre, String apellidos, String dni, Integer edad, String sexo) {
    	super();
    	this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
    }
    
    public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    public String getApellidos() {
        return apellidos;
    }
 
    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }
 
    public String getDni() {
        return dni;
    }
 
    public void setDni(String dni) {
        this.dni = dni;
    }
 
    public Integer getEdad() {
        return edad;
    }
 
    public void setEdad(Integer edad) {
        this.edad = edad;
    }
 
    public String getSexo() {
        return sexo;
    }
 
    public void setSexo(String sexo) {
        this.sexo = sexo;
    }
    
    @Override 
    public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DE LA PERSONA: " + nuevalinea + 
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
    }
    
	@Override
	public boolean equals(Object object) {
		final Persona aux = (Persona) object;
		if (this == object)
	           return true;
		else if (object == null)
	           return false;
		else if (getClass() != object.getClass())
	           return false;
		else if (this.dni.equals(aux.getDni())) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void crecer() {
		System.out.println("Crece");
		
	}

	@Override
	public void reproducirse() {
		System.out.println("Fornicia");
		
	}

	@Override
	public void morir() {
		System.out.println("R.I.P.");	
	}
}

Al hacer esto, ya sí que podremos ejecutar nuestra aplicación sin errores y, si queremos, hacer polimorfismo con los métodos definidos por la interfaz:

Profesor profe1 = new Profesor(1, "Antonio", "Brena", "1111111K", 52, "M");
		Profesor profe2 = new Profesor(2, "Alicia", "Hernandez", "2222222K", 45, "F");
		Alumno alumno1 = new Alumno(1, "Mar", "Millan", "44444444K", 29, "F");
		Persona trabajador1 = new Persona("Francisco", "García", "33333333K", 39, "M");
		
		List<Persona> lsPersonas = new ArrayList<Persona>();
		lsPersonas.add(profe1);
		lsPersonas.add(profe2);
		lsPersonas.add(alumno1);
		lsPersonas.add(trabajador1);

		for (Persona per : lsPersonas) {
			per.reproducirse();
		}

Consola:

Fornicia
Fornicia
Fornicia
Fornicia

Como veis, el Polimorfismo no es más que el uso más potente de la herencia, pero no es, ni mucho menos, complejo, al igual que tampoco lo son las ideas de clase abstracta e interfaz una vez se entiende el concepto general de Herencia.

Así que nada, si habéis seguido estas pildoritas al pie de la letra podemos ya afirmar (con extremada timidez, eso sí) que comprendéis y entendéis las bases de lo que es la Programación Orientada a Objetos. A partir de ahora, sólo necesitaréis tiempo y práctica para poder desarrollar cualquier aplicación que deseéis con este paradigma y, eso sí, teniendo claros los conceptos fundamentales que os harán desarollar como las personitas, y no como muchos: con los pies.

Y aunque ésta sí será nuestra última pildorita de POO, ni mucho menos será la última de Java. En las próximas semanas os hablaré de las excepciones (un concepto de Java que escapa a la POO pero fundamental a la hora de programar y realizar un correcto tratamiento de errores) y a partir de ahí, ya se verá. Tenía pensado hacer un programa básico como ejemplo resumen de todo lo que hemos visto, y tras esto, seguir entrando en chicha con conceptos de programación más avanzados.

Índice de Pildoritas

Share
20
Dec 16

Pildoritas de POO y Java: Herencia

pildoras poo java
Como ya dejé entrever en anteriores posts de esta serie de artículos, la pildorita de hoy era la madre de todos los corderos. En ella veríamos un concepto fundamental en POO, la Herencia, y el Polimorfismo, un potente recurso que nos servirá para que la herencia adquiera su máximo potencial a partir de la sobrecarga.

De nuevo del dicho al hecho hay un trecho, y dejo patente una vez más lo noob que soy aún en el terreno de los manuales y tutoriales: La segunda parte de la pildorita, el Polimorfismo, al final va a tener su propio post dedicado, ya que se me iba a ir de las malos su extensión y ya se sabe que mejor separar en trocitos cortos, abarcables y fácilmente comprensibles, que en tochos insufribles y con mil ideas de golpe.

Así que nada, tendréis que esperar a la próxima semana para saber que es eso del Polimorfismo.

En fin, al lío.

Herencia

La herencia tiene como meta la extensión y reutilización de código por lo que se utiliza cuando varias clases tienen funcionalidades comunes, en cuyo caso éstas pueden heredar de una clase padre la funcionalidad común.

Por ejemplo, si volvemos a la imagen de la pildorita de introducción a POO, todas las entidades de la imagen son mamíferos, es decir, todos ellos caminan y maman, no obstante, una Persona podrá, por ejemplo, plantearse el sentido de la vida, mientras un Delfín (que sepamos) no. Así mismo, aunque tanto el Delfín como el Humano pueden desplazarse, uno lo hace nadando con su aleta, mientras otro caminando sobre sus dos piernas, por lo que, aunque sus funcionalidad es igual, se implementa de distinta forma.

mamiferos

Para implementar la herencia entre clases en Java se utiliza la palabra reservada extends. Así mismo, veremos por primera vez una anotación, una muy importante a la hora de utilizar herencia, @Override, y la palabra reservada super.

Para entender mejor la herencia partiremos de nuestro socorrido ejemplo de la clase Alumno.

public class Alumno {
	private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
	
	private int codAlumno;
	private Lis<Asignatura> asignaturas;
	
	public Alumno (int codAlumno, String nombre, String apellidos, String dni, Integer edad, String sexo, List<Asignatura> lsAsignaturas) {
		this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
		this.codAlumno = codAlumno;
		this.asignaturas = lsAsignaturas;
	}

        public void setCodAlumno(int codAlumno) {
		this.codAlumno = codAlumno;
	}
	public int getCodAlumno() {
		return codAlumno;
	}
	public void setAsignaturas(List<Asignatura> asignaturas) {
		this.asignaturas = asignaturas;
	}
	public List<Asignatura> getAsignaturas() {
		return asignaturas;
	}
	
	public void asignarAsignatura(Asignatura asignatura) {
		asignaturas.add(asignatura);
	}

	public double getNotaMedia() {
		double resultado = 0;
		for (int i = 0; i < asignaturas.size(); i++) {
			Asignatura asig = asignaturas.get(i);
			resultado += asig.getNota();
		}
		return Math.round((resultado != 0 ? resultado / asignaturas.size(): 0));
	}
}

Imaginemos por otra parte, que tenemos una clase Profesor, definida tal que:

public class Profesor {
	private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
	
	private int codAlumno;
	
	public Alumno (int codAlumno, String nombre, String apellidos, String dni, Integer edad, String sexo) {
		this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
	this.codAlumno = codAlumno;
	}

        public void setCodAlumno(int codAlumno) {
		this.codAlumno = codAlumno;
	}
	public int getCodAlumno() {
		return codAlumno;
	}

 public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    public String getApellidos() {
        return apellidos;
    }
 
    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }
 
    public String getDni() {
        return dni;
    }
 
    public void setDni(String dni) {
        this.dni = dni;
    }
 
    public Integer getEdad() {
        return edad;
    }
 
    public void setEdad(Integer edad) {
        this.edad = edad;
    }
 
    public String getSexo() {
        return sexo;
    }
 
    public void setSexo(String sexo) {
        this.sexo = sexo;
    }
 
}

Como se puede ver, las clases Alumno y Profesor comparten mucho código replicado. Los campos nombre, apellidos, DNI, sexo y edad, por tanto, se pueden encapsular en una clase padre, que llamaremos Persona y haremos que ambas clases hereden de ella toda esa funcionalidad común.

public class Persona {
	 
    private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
    
    Persona() {
    	super();
    }
    
    public Persona(String nombre, String apellidos, String dni, Integer edad, String sexo) {
    	super();
    	this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
    }
    
    public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
 
    public String getApellidos() {
        return apellidos;
    }
 
    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }
 
    public String getDni() {
        return dni;
    }
 
    public void setDni(String dni) {
        this.dni = dni;
    }
 
    public Integer getEdad() {
        return edad;
    }
 
    public void setEdad(Integer edad) {
        this.edad = edad;
    }
 
    public String getSexo() {
        return sexo;
    }
 
    public void setSexo(String sexo) {
        this.sexo = sexo;
    }

@Override     
public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DE LA PERSONA: " + nuevalinea + 
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
    }
    
	@Override
	public boolean equals(Object object) {
		final Persona aux = (Persona) object;
		if (this == object)
	           return true;
		else if (object == null)
	           return false;
		else if (getClass() != object.getClass())
	           return false;
		else if (this.dni.equals(aux.getDni())) {
			return true;
		} else {
			return false;
		}
	}
}


public class Alumno extends Persona {
	
	private int codAlumno;
	private List<Asignatura> asignaturas;
	
	public Alumno (int codAlumno, String nombre, String apellidos, String dni, Integer edad, String sexo) {
		super(nombre, apellidos, dni, edad, sexo);
		this.codAlumno = codAlumno;
		this.asignaturas = new ArrayList<Asignatura>();
	}
	public void setCodAlumno(int codAlumno) {
		this.codAlumno = codAlumno;
	}
	public int getCodAlumno() {
		return codAlumno;
	}
	public void setAsignaturas(List<Asignatura> asignaturas) {
		this.asignaturas = asignaturas;
	}
	public List<Asignatura> getAsignaturas() {
		return asignaturas;
	}
	
	public void asignarAsignatura(Asignatura asignatura) {
		asignaturas.add(asignatura);
	}

	public double getNotaMedia() {
		double resultado = 0;
		for (int i = 0; i < asignaturas.size(); i++) {
			Asignatura asig = asignaturas.get(i);
			resultado += asig.getNota();
		}
		return (resultado != 0 ? resultado / asignaturas.size(): 0);
	}

@Override 
    public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DEL ALUMNO: " + nuevalinea + 
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
    }
}


public class Profesor extends Persona {
	private int codProfesor;
	
	public Profesor (int codProfesor, String nombre, String apellidos, String dni, Integer edad, String sexo) {
		super(nombre, apellidos, dni, edad, sexo);
		this.codProfesor = codProfesor;
	}
	public void setCodProfesor(int codProfesor) {
		this.codProfesor = codProfesor;
	}

	public int getCodProfesor() {
		return codProfesor;
	}

@Override 
    public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DEL PROFESOR: " + nuevalinea + 
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
}

Por tanto, la clase Persona encapsula toda la funcionalidad común, la cual heredan las clases Profesor y Alumno. Cualquier hijo de la clase Persona, ya sea Profesor o Alumno, podrá invocar a los métodos heredados por su clase padre.

Es importante aclarar, eso sí, que sólo se heredarán aquellos elementos con visibilidad Protected o Public, como vimos en la pildora de visibilidad muy por encima. Por ejemplo, desde la clase Alumno no podemos acceder directamente al DNI con un super.dni, pero sí que podemos hacerlo a través de los métodos setDNI y getDNI, los cuales son públicos.

Hemos creado dos nuevos métodos comunes, equals y toString, que como se puede ver llevan una anotación, @Override. Esto significa que es un método heredado que se va a reescribir para tener una conducta específica y adaptada a la clase hijo. Por ejemplo, los métodos toString de Alumno y Profesor, como se puede ver, devuelven un texto personalizado para esas clase, es decir, sobrescribe el método heredado genérico para cualquier Persona.

Y os preguntareis, ¿y los métodos equals y toString de la clase padre Persona? ¿Por qué tienen también la anotación @Override? Pues porque estos métodos también son heredados. En Java todos los objetos heredan de la clase Object y la clase Object tiene definidos métodos básicos, como toString o equals.

Por último, otra palabra reservada en herencia que utilizaremos mucho es super, la cual tiene una funcionalidad similar a this. Mientras que this, la que ya conocemos, hace mención a la clase en sí, super hacer mención a su clase padre. Por eso, para llamar al constructor de la clase Persona utilizamos la palabra super. De la misma forma, si por ejemplo quisiéramos utilizar el método toString de la clase padre dentro de un método de, por ejemplo, Alumno, utilizaríamos la sentencia super.toString().

Y ya está, no hay más misterio. Como veis, la herencia, aunque potente, es muy sencilla de implementar y entender. En la próxima pildorita veremos la herencia en todo su esplendor con el Polimorfismo y ya con eso, podremos decir que ya sí que sí entendéis la Programación Orientada a Objetos y podéis animaros sin miedo a empezar a programar vuestras propias aplicaciones en Java, C#, o cualquier otro lenguaje POO. No obstante, hay algunas cosas ajenas a la POO pero muy importantes en Java, como las Excepciones, que daremos en otra pildorita extra y con los que no sólo podremos programar en POO, sino tener un buen control de los errores.

Índice de Pildoritas

Share
14
Dec 16

Pildoritas de POO y Java: Relaciones entre Clases

pildoras poo java
En la anterior pildorita os dije que hablaríamos de la Herencia y el Polimorfismo, y aunque esa pildorita está prácticamente terminada en borradores, dándole vueltas a las siguientes pildoritas, me daba cuenta que la que tenía planteada como continuación debía de ir antes, es decir, ésta, sobre relaciones entre clases. Así que nada, esto significa más espera entre la anterior pildorita y ésta, pero el lado bueno es que la siguiente la sacaré en breves.

Llevo unos 7 años trabajando en el desarrollo software y he pasado por multitud de proyectos de gran envergadura. Si algo tengo claro en todos estos años, es que se hace muy mal código - por diversos motivos que no vienen al caso - y que dónde más se falla es, precisamente, en las relaciones de clases: códigos espagueti, pésima modularización y encapsulación... Todos esos problemas vienen, en la mayoría de casos, porque no se tienen del todo claro las relaciones entre clases en la parte más importante del desarrollo, el diseño. Es por eso que antes de entrar en temas de Herencia (algo que muchos desarrollores sí que comprenden bien), creo que es mejor para el aprendizaje de los anteriores conceptos que veamos este tema, que permite asentarlos. Ya habrá tiempo de entrar en la siguiente relación, la generalización, ya que la Herencia no deja de ser también una relación de dos clases.

En la anterior pildorita vimos lo que era un mensaje, y que cuando un objeto lanza un mensaje a otro, estos se comunican y colaboran entre sí. Se dice que existe una Relación entre dos clases si dos objetos de las respectivas clases colaboran entre sí.

Hay tres tipos de relaciones entre clases que a continuación veremos de forma más detallada: Composición, asociación y uso.

Para mayor comprensión de las mismas, utilizaremos el siguiente ejemplo, donde se pueden ver los tres tipos de relaciones:

public class Alumno {
	private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
	
	private int codAlumno;
	private Lis<Asignatura> asignaturas;
	
	public Alumno (int codAlumno, String nombre, String apellidos, String dni, Integer edad, String sexo, List<Asignatura> lsAsignaturas) {
		this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
		this.codAlumno = codAlumno;
		this.asignaturas = lsAsignaturas;
	}

        public void setCodAlumno(int codAlumno) {
		this.codAlumno = codAlumno;
	}
	public int getCodAlumno() {
		return codAlumno;
	}
	public void setAsignaturas(List<Asignatura> asignaturas) {
		this.asignaturas = asignaturas;
	}
	public List<Asignatura> getAsignaturas() {
		return asignaturas;
	}
	
	public void asignarAsignatura(Asignatura asignatura) {
		asignaturas.add(asignatura);
	}

	public double getNotaMedia() {
		double resultado = 0;
		for (int i = 0; i < asignaturas.size(); i++) {
			Asignatura asig = asignaturas.get(i);
			resultado += asig.getNota();
		}
		return Math.round((resultado != 0 ? resultado / asignaturas.size(): 0));
	}
}

 

Composición

Es la relación que se constituye entre el todo y la parte. En otras palabras, existe una relación de composición entre la clase A y la clase B, cuando la clase A "tiene un" objeto de la clase B.

Esta colaboración se traduce en la delegación de la clase todo a las partes de ciertas acciones determinadas para implementar la funcionalidad global.

Con esta colaboración se respetará el principio de encapsulación y modularidad por parte de las clases que componen a la clase A.

A la hora de plasmar en código esta relación con los conceptos que hemos visto en las anteriores pildoritas, esto se traduce en un atributo de la clase B en la clase A. Por tanto, tendrá una visibilidad privada y no es versátil, es decir, no puede ser intercambiable por otros objetos. Así mismo, tendrá una duración en la colaboración no momentánea en el tiempo.

Es el caso del atributo codAlumno de nuestra Clase de ejemplo Alumno. Si hiciéramos una clase Profesor, no tendría sentido introducir un código de alumno, por tanto, no es una entidad versátil. Así mismo, el código de alumno se utilizará en muchas funcionalidades de la clase Alumno, ya que es un identificador único similar al DNI. Así mismo ocurre con el resto de atributos que identifican inequívocamente a un Alumno, como nombre, apellidos, DNI...todos aquellos datos que se inicializan a la hora de construir el objeto y que existirán durante todo el ciclo de vida del objeto Alumno.

 

Uso

Es la relación que se establece de forma momentánea entre un objeto cliente (pide algo) y un objeto servidor (suministra ese algo). Por tanto, el objeto de la clase A enviará un mensaje a un objeto de la clase B en un momento dado sin dependencias futuras. Así mismo, el uso de la clase B no dependerá únicamente de la clase A, sino que podrá ser utilizada por otras muchas clases.

Esto significa que la clase A, la cliente, tendrá como parámetro o valor devuelto de un método un objeto de la clase servidora B si esa colaboración es pública, y como un objeto local dentro de un método si es una colaboración privada. La versatilidad de ser intercambiada la clase B por otra, es, por tanto, elevada.

Por ejemplo, el método getNotaMedia() de la clase Alumno, redondea el resultado final utilizando la clase Math e invocando a su método round. Esta clase no es necesaria obviamente para ese cálculo. Podríamos decidir no redondear, o redondear nosotros creando un método propio que realice esta funcionalidad.
 

Aociación

La asociación es una relación de uso donde la relación entre la clase A y la clase B sí que perdura en el tiempo, es decir, se realiza en diversos momentos del ciclo de vida del objeto A, por lo que se crea una relación de dependencia entre ambos objetos. Al igual que la relación de uso, la responsabilidad de manejar ese objeto B no dependerá únicamente del objeto A, sino que podrá ser utilizado por más objetos de diferentes clases.

La asociación, al ser una relación pública generalmente y de una temporalidad no momentánea, pero teniendo una versatilidad reducida, se traducirá en un atributo en la clase A cliente que apuntará a la clase B servidora.

Un ejemplo de este tipo de relación sería la existente entre el Alumno y las Asignaturas. La clase Asignatura es independiente del Alumno, ya que puede existir sin necesidad de que haya Alumnos matriculados a ella. Así mismo, el Alumno puede estar dado de alta en la universidad sin estar matriculado en ninguna asignatura.
 
Espero que esta pildorita haya sido clara y de verdad afiance conceptos fundamentales ya no en el desarrollo de buenos programas en POO, sino de códigos de calidad bien estructurados y fácilmente mantenibles. Cuando vi este capítulo de la asignatura de Programación II me resultó lioso y no le presté toda la atención que merecía. Me centraba en saber sacar las clases de un problema, definir que atributos tenía, y los métodos y sus funcionalidades. Vaya, estaba anclada en lo que conocía, la imperativa. No fue hasta ya después en Ingeniería del Software que llegué a entender del todo para que servía esto y que, la Programación Orientada a Objetos sin estas relaciones no deja de ser modulada, fallo que luego he visto años más tardo muy extendido en la profesión. Sin entender las relaciones, no se sabe de verdar trabajar con POO y poder de verdad explotar la modularidad y ecapsulación que ofrece.

La siguiente pildorita, sí que sí, será la de Herencia y Polimorfismo, la cual, como comenté antes, está ya acabada, así que en una semana tendréis una nueva dosis javera con la que ya prácticamente habremos acabado esta serie 🙂

Índice de Pildoritas

Share
8
Sep 16

Pildoritas de POO y Java: Atributos y Métodos

pildoras poo java
En la anterior pildorita de POO y Java introducimos el concepto de Visibilidad de una clase, la cual nos da la tan ansiada encapsulación.

No obstante, aunque ya llevamos dos pildoritas viendo atributos y métodos, todavía no hemos ahondado suficiente en ciertos conceptos a tener en cuenta a la hora de utilizarlos, pero que ahora que tenemos claro el concepto de Ámbito, podemos afrontar.

Atributos

Los atributos son las variables y constantes que definen los estados o datos de un objeto. Vimos en la anterior pildorita que, al igual que con el resto de elementos existentes en una clase, los atributos también se ven afectados por los modificadores de visibilidad. No obstante, estos modificadores de visibilidad (public, private, static o final), pueden venir seguidos de los modificadores de las características del atributo (su vida útil, sus posibles cualidades y valores, etc.).

  • static: El modificador static, que vimos en la anterior pildorita, se trata como un modificador de característica, y como vimos ya, especifica que el atributo pertenece a la clase y no a los objetos creados a partir de ella.
  • final: El atributo es una constante, por lo que deberá de tener obligatoriamente un valor inicial. Se suele especificar su nombre en mayúsculas por convención.
  • trascient: El atributo no es serializable, es decir, no puede ser convertido en una cadena de bytes que resulte fácilmente manipulable por red, almacenamiento en ficheros, bases de datos, etc. Utilizando este modificador evitamos que este atributo y su valor se tengan en cuenta a la hora de serializar el objeto que los contiene.
  • volatile: Este modificador indica a Java que este atributo puede ser accedido de forma concurrente por varios hilos de forma simultánea.

Métodos

Los métodos son un conjunto de instrucciones definidas dentro de una clase, que realizan tareas y, por norma general, operan sobre los estados de los atributos de dicha clase.

Así mismo, los métodos son el mecanismo que implementa la comunicación entre objetos, lo que comúnmente se llama Paso de Mensajes.

Un objeto, el emisor, solicita ejecutar uno de sus métodos a otro objeto, con el objetivo de que este realice alguna acción, o devuelva cierta información.

Los métodos así mismo, siguen la misma estructura que las funciones y procedimientos de la programación estructurada y pueden recibir, o no, parámetros, así como devolver, o no, valores.

[modificadores] tipo nombreMetodo ([lista parametros]) {
     // instrucciones
     [return valor;]
}

Los modificadores, que no son obligatorios (los corchetes significan que puede estar, o no), indicarán el ámbito de uso del método, y son los que ya hemos visto en la pildorita de Visibilidad y Ámbito.

Constructores

El constructor es un método especial de la clase que se ejecuta siempre que se crea un objeto de dicha clase. Sirve para inicializar los estados del objeto y que sus atributos siempre contengan valores válidos.

Una clase puede tener uno o más constructores. Así mismo, si no se define un constructor, el compilador crea automáticamente el constructor por defecto, un constructor sin parámetros que no hace nada y en el que los atributos del objeto se inicializan a los predeterminados por el sistema.

Para que un método sea interpretado como constructor de una clase debe tener las siguientes características:

  • Tiene el mismo nombre que la clase que contiene
  • No puede devolver ningún valor, ni siquiera el valor void
  • Es público, para que pueda invocarse desde cualquier parte donde se quiera crear un objeto de dicha clase
  • No se hereda

Por ejemplo, volviendo al ejemplo de Persona, cuando creábamos un objeto de este tipo en la clase PruebaPersona, lo hacíamos a través de la sentencia, Persona mar = new Persona();, dicha sentencia llama al constructor por defecto, public Persona();

Si quisiéramos, podríamos crear un nuevo constructor que inicialice los atributos a los valores pasados por parámetro, y así nos ahorraríamos las sentencias de set como mar.setNombre("Mar"), en la que dábamos valor a dicho atributo.

public class Persona {
	 
    private String nombre;
    private String apellidos;
    private String dni;
    private Integer edad;
    private String sexo;
    
    public Persona(String nombre, String apellidos, String dni, Integer edad, String sexo) {
    	super(); // Se llama al constructor por defecto de la clase superior, Object, ya que no se hereda. No es necesario en este caso, pero por convención se pone siempre
    	this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
    }

Ahora bien, al definir nosotros un constructor, el compilador dejará de crear el constructor por defecto, por lo que, en caso de querer un constructor sin parámetros, deberemos definirlo nosotros también. ¿Y como hacemos esto? Gracias a la Sobrecarga de métodos.

Sobrecarga de métodos

La sobrecarga de métodos es la creación de varios métodos con el nombre, pero con firmas diferentes.

La firma de un método se compone del nombre, la lista de argumentos y el dato devuelto. No obstante en Java, esto último no se tiene en cuenta, por lo que la firma es la combinación del nombre, y el número y tipo de argumentos.

Por ejemplo, los dos constructores de nuestro anterior ejemplo, tienen firmas diferentes por lo que el intérprete es capaz de diferenciarlos aunque tengan el mismo nombre.

public Persona(String nombre, String apellidos, String dni, Integer edad, String sexo) {
	this.nombre = nombre;
    	this.apellidos = apellidos;
    	this.dni = dni;
    	this.edad = edad;
    	this.sexo = sexo;
}

public Persona() {
	super();
}
 

La sobrecarga de métodos da pie a un concepto mucho más amplio conocido como Polimorfismo, pero esto ya es temática para la próxima pildorita, en la cual veremos también otro concepto fundamental de la Programación Orientada a Objetos: la Herencia.

Índice de Pildoritas

Share
24
May 16

Pildoritas de POO y Java: Visibilidad y ámbito

pildoras poo java

En la anterior píldora de POO y Java vimos que en la Programación Orientada a Objetos definimos clases, las cuales una vez se instancian son objetos concretos de esa entidad, con su propio estado.

Así mismo, sabemos que las clases y objetos se componen de atributos y métodos, es decir, estados y acciones sobre esos estados. Vimos la manera de definir variables (atributos) y funciones (métodos) en los primeros capítulos de Imperativa, no obstante, en POO hay que tener en cuenta nuevos conceptos propios del paradigma. El fundamental es la Visibilidad, la cual nos da la tan ansiada encapsulación. También debemos conocer cierto concepto previo utilizado en Java y que afecta a la definición de lo qué es visibilidad: Los paquetes.

Para mayor claridad de los conceptos, utilizaremos variaciones en el ejemplo inicial de la anterior pildorita, por lo que es recomendable tenerla abierta en otra pestaña.
 

Paquetes

Los paquetes no son más, siendo muy burdos, que carpetas, y sirven para organizar nuestras clases y darles un nombre único. Los paquetes además, como ocurre con las carpetas, se organizan en una estructura de árbol. Cuando creamos un paquete, se crea una estructura de directorios asociados.

En la anterior pildorita se definió una clase y aunque no se llegó a explicar, la primera línea con la palabra package, indica el paquete donde se encuentra alojada.

// Directorio donde se encuentra la clase Persona y PruebaPersona: 
// ejemplo1/persona
package ejemplo1.persona

carpetas
Así mismo, cuando utilicemos una clase del mismo paquete en otra clase, no tendremos que especificar su ruta. Si no es el caso, utilizaremos la palabra import seguida del paquete y clase.

import ejemplo1.persona.Persona

 

Visibilidad y acceso

La visibilidad, o vista, nos indica por quién es accesible un determinado elemento y es aplicable tanto a clases, como a atributos y métodos. Para diferenciar la visibilidad de un elemento, se utilizan los modificadores de acceso, palabras reservadas que especifican el tipo de visibilidad de dicho atributo, método, etc.

Hay cuatro tipos de modificadores: public, private, protected, default y static.

public

La vista public permite acceder al elemento desde cualquier clase del espacio de trabajo. Un ejemplo de esta vista es la de todos los métodos de la clase Persona o la de su atributo codigoUnico. Como vimos, desde PruebaPersona se accede a él sin necesidad de métodos intermedios.

package ejemplo1.persona;

public class Persona {
 
    public String codigoUnico; 
    
    public String toString() {
        String nuevalinea = System.getProperty("line.separator");
        String resultado = "DATOS DE LA PERSONA: " + nuevalinea + 
                "Codigo Unico: " + this.codigoUnico + nuevalinea +
                "Nombre: " + this.getNombre() + nuevalinea + 
                "Apellidos: " + this.getApellidos() + nuevalinea + 
                "DNI: " + this.getDni() + nuevalinea +
                "Edad: " + this.getEdad() + nuevalinea +
                "Sexo: " + this.getSexo() + nuevalinea;
 
        return resultado;
    }
}

package ejemplo1.persona

public class PruebaPersona {
 
    public static void main(String[] args) {
         
        Persona mar = new Persona();        
        mar.codigoUnico = "112";
        System.out.println(mar.toString());
         
    }
}

private

La vista private, por el contrario, sólo permite que el elemento sea utilizado por otros objetos de la misma clase, pero no por elementos de clases diferentes. Como se ve en el ejemplo anterior, el método toString() utiliza los atributos privados sin necesidad de utilizar métodos públicos que devuelvan sus valores. Sin embargo, para poder utilizarse desde la clase PruebaPersona es necesario hacerlo a través de sus métodos set y get.

package ejemplo1.persona;

public class Persona {
	
	private String nombre;
	
	 public String getNombre() {
        return nombre;
    }
 
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
}

package ejemplo1.persona

public class PruebaPersona {
 
    public static void main(String[] args) {
         
        Persona mar = new Persona();        
        mar.setNombre("Mar");
        System.out.println("El nombre de la persona es: " + mar.getNombre());
         
    }
}

¿Y que pasaría si intentaramos acceder a un atributo privado? Por ejemplo, el DNI:
private-example
Como se puede ver, se muestra un error pre-compilación, y se nos sugiere o bien cambiar la visibilidad del atributo - a public, por ejemplo - o utilizar un método set, como se hace en la línea anterior.

protected

La vista protected indica que un elemento es accesible desde una clase del mismo paquete, o por una clase que herede de la clase en la que este elemento se encuentra, sin importar el paquete. Una vez más, dejaremos aparcada la herencia, la cual requiere una pildorita por si sola. Cuando toque explicaremos más en profundidad este aspecto.

default

La vista default, que se puede también indicar sin poner ningún modificador de acceso delante del elemento, permite al elemento ser utilizado desde cualquier clase del mismo paquete.

public class Persona {
 
    String codigoUnico; 

}

package ejemplo1.persona

public class PruebaPersona {
 
    public static void main(String[] args) {
         
        Persona mar = new Persona();        
        mar.codigoUnico = "112";
        System.out.println("El Codigo de Persona es: " + mar.codigoUnico);
         
    }
}

static

Por último, existe el modificador static, el cual indica que el elemento pertenece a la clase y no a las instancias de la misma (objetos). Por ejemplo, como vimos en el ejemplo de la anterior pildorita, el main se declara como static. Esto permite acceder al método main sin necesidad de instanciar la clase que lo contiene.

package ejemplo1.persona;
/**
 * Clase Persona
 * @version 1.0
 * @since 2014
 */
public class Persona {
 
    static int numPersonas = 0;
    private String nombre;
   
   // Esto es un constructor 
   Persona() {
	   numPersonas++;
   }

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	
	
	public String getNombre() {
		return nombre;
	}
}

package ejemplo1.persona;
/**
 * Clase Test para probar la clase Persona
 * @version 1.0
 * @since 2014
 */
public class PruebaPersona {
 
    public static void main(String[] args) {
         
        Persona objeto1 = new Persona();
        objeto1.setNombre("Mar");
        
        Persona objeto2 = new Persona();
        objeto2.setNombre("Pepe");
        
        System.out.println("El nombre del objeto 1 es: " + objeto1.getNombre());
        System.out.println("El nombre del objeto 2 es: " + objeto2.getNombre());
        System.out.println("Se han creado " + Persona.numPersonas + " personas");
    }
}

El resultado que tendremos es el siguiente:

El nombre del objeto 1 es: Mar
El nombre del objeto 2 es: Pepe
Se han creado 2 personas

Existen otros modificadores de acceso como native, utilizado para indicar código diferente a Java, trascient, que se utiliza para indicar que este elemento no es persistente, final, para especificar que una variable determinada tendrá un valor fijo, volatile y synchronized, utilizados para la programación concurrente y abstract, para herencia. Al no ser modificadores de acceso alejados del concepto de visibilidad, no entran en esta pildorita, pero ya habrá tiempo de verlos.

Índice de Pildoritas

Share
5
Apr 16

Pildoritas POO y Java: El que mucho abarca... u_U!

pildoras poo java

Ayer entré en este blog y miré la parte de estadísticas de la web, cosa que no miraba desde hacía decenios.

Pese a que el rumbo de este sitio ha virado enormemente a la política, por lo que pude ver la mayoría de mis visitas – cosa que por otra parte me dio una muy buena alegría – llegan a este blog gracias a mis Pildoritas de Bases de Datos y Programación orientada a objetos en Java.

Estuve revisando las pildoritas y bueno, con las de POO se me cayó la cara de vergüenza, literalmente. Subí el último post, la introducción de POO, en noviembre de 2014, que se dice pronto. Desde entonces todo aquel que entra a esta serie de pildoras se encuentra con la “grata” sorpresa de que falta justamente la parte de POO, ¡en unas pildoritas que supuestamente son de POO!

Así que nada, ayer volví a releer las pildoritas, consulté apuntes y recoloqué ideas en mi cabeza, con la clara resolución de terminar los, como mucho, 3 o 4 posts que pueden faltar para concluírlas.

Para este finde espero tener el siguiente post, centrado en los ámbitos de las clases y objetos.

Como ya va siendo tradición en mis posts, una vez más pido disculpas a todas aquellas personas que puedan haberlas leído y se hayan quedado con la frustración de no verlas acabadas.

Share
24
Sep 14

Cómo abaratar un sector próspero: Guía de la Comunidad de Madrid

A primeros de este mes la Comunidad de Madrid anunció que iba a incorporar una asignatura obligatoria de Programación en la ESO, aunque fuera, eso sí, la comunidad con menor ratio de ordenadores por clase. Según Ignacio González la idea era formar a los jóvenes de cara a un futuro laboral donde las nuevas tecnologías tendrán una presencia generalizada.

Todo esto puede parecer genial. En Reino Unido por ejemplo se lleva enseñando programación desde hace años. No obstante, como todo lo que se hace en este país, lo que se pretende no es tener futuros ciudadanos formados, sino futuros esclavos.

Ya en el anuncio inicial, Ignacio González y Lucía Figar dejaron ver algunas de las áreas que darían los alumnos: creación de webs, aplicaciones móviles y robótica. Las dos primeras partes tienen el objetivo obvio de formar a los alumnos en la programación más extendida en el sector nacional, y robótica aunque tiene poca aplicación en desarrollos españoles, sí que sería una buena motivación para los chavales, aunque difícilmente un estudiante de ESO podrá hacer grandes cosas en esa área con sus conocimientos en física y matemáticas.

alierta-ignacioIgnacio González cerrando su futura jubilación en Telefónica

Desde el minuto muchos sospechamos que la intención del gobierno del PP no era otra que malformar chavales que según terminen ESO puedan incorporarse como programadores al mundo laboral cobrando una miseria, y devaluando todavía más el único sector que no va mal en este país. La confirmación ha sido el anuncio de que Telefónica se encargará de la formación de los profesores de secundaria que tengan que dar la asignatura. Dicho curso, casi por completo online, constará de 50 horas.

Una persona no aprende a programar en 50 horas, menos aún cómo para enseñar a otros. Por otra parte, dudo que precisamente Telefónica, empresa que externalizó por completo sus desarrollos y contrata a otras empresas para esta labor, sea la mejor opción para enseñar a otros a programar. Tenemos muchísima gente muy formada en paro que podría dar clases, profesores universitarios o incluso funcionaros de TIC desasignados con muy buenos conocimientos. No obstante, intuyo que formar bien a los profesores es lo de menos para la Comunidad de Madrid. Es mejor darle una mamandurria a Telefónica y asegurar la “jubilación” de algunos miembros del gobierno, como viene siendo tónica general en el gigante español de las telecomunicaciones.

La informática en este país está copada mayoritariamente por personas con un perfil científico de cualquier área menos la informática. Estas personas saben programar, pero en muchos casos mal. ¿Por qué se hace esto? Porque lo que buscan la mayoría de empresas son programadores lo más baratos posibles. Sólo hay que echar un vistazo a cualquier portal de empleo para ver cómo se contratan programadores sin experiencia por 800€, cuando hasta hace unos años se pagaba como mínimo a un recién titulado más de 1.000€. Y esto sin una crisis significativa en el sector.

En España no se da valor añadido al buen programador, porque, como todo en este país, buscamos el pelotazo fácil, hacer proyectos los más baratos posibles y en tiempos muy cortos. Así pasa, tenemos aplicaciones mal hechas, con código espagueti y que a la larga su mantenimiento cuesta casi más que la propia fase de desarrollo.

Ya existe una pequeña burbuja en la informática, como todo lo que tocan nuestros gobernantes y empresarios que da dinero: Desarrollos inútiles y mal hechos por millonadas, mantenimientos eternos muy costosos...es decir, desarrollar por desarrollar con el único objetivo de sacar el máximo beneficio, y a costa del contribuyente, porque curiosamente en España la mayoría de las grandes empresas del sector viven de proyectos con la administración pública. Un ejemplo sonado fue la web del senado, que después de costar 500.000€ -una cifra que no es descabellada en un proyecto de este envergadura – tenía fallos de seguridad elementales de Cross-site Scripting, y no pasaba los validadores más básicos de páginas web.

En vez de intentar solventar este problema y que España sea un país puntero en desarrollo y nuevas tecnologías, lo que se propone es extender aún más este problema. Convertirnos en un país como Argentina o India, donde sus profesionales tienen salarios muy bajos para que las multinacionales puedan hacer desarrollos por cuatro duros. Telefónica es experta en ello, ya que en su momento cuando externalizó sus desarrollos contrató a Accenture Argentina para realizar esta labor. La diferencia es que en esos países por mucho que cobren poco, los conocimientos de sus programadores están a años luz de lo habitual en este país: Allí cobran poco porque son países en desarrollo. En España se pretende devaluar salarios hasta el nivel de Argentina o India ampliando el perfil de programador a casi cualquiera que sepa hacer una web. Como mano de obra barata no podemos competir con estos países.

Programar una web o una aplicación móvil está al alcance de cualquiera. Sin ir más lejos, cuando yo tenía 15 años hacía webs con lo que aprendí de HTML y PHP por mi cuenta. No necesité ni cursar una optativa, ni mucho menos una FP o una carrera. Ahora bien, con esos conocimientos jamás podría haber hecho una web de gestión grande, donde se trabaja con juegos de datos inmensos alojados en una base de datos, y donde la importancia de que un algoritmo sea óptimo es crítico para los tiempos de respuesta. Un chaval de instituto no va a saber jamás algorítmica, entre otras cosas porque no dispone de los conocimientos matemáticos necesarios, así que difícilmente sabrá si su código es bueno o malo, y en caso de ser malo por qué. Por otra parte, no parece que vayan a recibir formación en bases de datos, así que me pregunto cómo afrontarán el 99% de desarrollos actuales, que tiran contra una base de datos, y como encima optimizarán esos accesos sin conocimientos de álgebra relacional, cosa también habitual cuando atacas bases de datos con millones de registros.

Por tanto, este no es sino la enésima reforma enfocada a abaratar al trabajador español y ponerlo al nivel de países como China. Para ello, van a acabar con uno de los pocos sectores con salud del país que podían generar trabajo de calidad y una clase media sólida. Todo sea por las prebendas asociadas a la burbuja tecnológica que ya han iniciado desde hace años.

Share
13
Sep 13

¡Feliz Día del Programador!

Hoy, 13 de Septiembre, se celebra desde 2009 en Rusia el Día del Programador.

¿Y Por qué el 13 de Septiembre? Pues porque es el día 256 del año, que como sabéis, es una potencia de 2 muy importante en la informática, donde todo funciona en binario, y además es el número de combinaciones diferentes posibles que se pueden hacer con 8 bits (2^8).

Así que nada, los pringados que programamos estamos de enhorabuena, porque hoy es nuestro día 😀

¡Felicidades a todos! 😀

Podíamos aprovechar este día para conseguir que se nos valore más, que se conozca en España la importancia que tiene en un desarrollo contar con buenos programadores.

developer

Share