Publicado en Conceptos el 9 de December, 2009 por Lek. (4 comentarios)
Hoy toca otro post de teoría de la programación para hablar de uno de esos conceptos que muchas veces es difícil llevar a la práctica.
En algunos paradigmas de programación (como la programación orientada a objetos) se nos dice que desde fuera de una clase sólo necesitamos saber qué se hace, no el cómo. Si la clase se encarga de interaccionar con una base de datos no necesita saber cuál es la base de datos ya que de eso se encargaría el driver (lo cual sería cierto si el estándar SQL fuera más… estándar… pero eso es otro tema). Y al resto de clases del proyecto no les importa tampoco cómo realiza esa interacción, sino que sólo deben preocuparse de que tal método devuelve los datos de la tabla cual.
¿Cómo se hace esto? Definiendo muy bien la visibilidad de la clase. Esto es, qué métodos se van a llamar desde el resto de clases (métodos públicos), cuáles están restringidos a clases “amigas” (del mismo paquete o que hereden de la nuestra, son los métodos protegidos) y cuáles no son accesibles en absoluto fuera de nuestra clase (métodos privados).
Por definición, es recomendable que todas las variables sean definidas como privadas, de forma que la única manera de manipularlas sea a través de los métodos públicos definidos por la clase y que sean éstos los que se encarguen de hacer todas las comprobaciones que sean necesarias.
Imaginemos la siguiente clase muy básica:
public class Persona {
private String nombre;
private int edad;
public Persona () {
inicializar ();
}
public void setNombre (String nombre2) {
nombre = nombre2;
}
public void setEdad (int edad2) {
if (edad2 > 0) {
edad = edad2;
}
}
public boolean validaVariables () {
return edad > 0 && ! "".equals(nombre);
}
private void inicializar () {
nombre = "";
edad = 0;
}
}
En este caso, lo que vemos desde fuera es que para la clase Persona podemos asignar una variable nombre y una variable edad. Podría haber más, pero no nos interesan puesto que no podemos interaccionar con ellas.
Además disponemos de una función para validar que los datos son correctos, pero nunca sabremos desde otra clase que existe un método inicializar.
Publicado en Conceptos el 4 de April, 2008 por Lek. (4 comentarios)
Era de noche, los bandidos se refugiaron en el bosque. El capitán se levanta y dice:
- Pedro, cuéntanos esa historia que tan bien sabes y tan mal dices
Pedro se levanta y dice:
Era de noche, los bandidos se refugiaron en el bosque. El capitán se levanta y dice:
- Pedro, cuéntanos esa historia que tan bien sabes y tan mal dices
Pedro se levanta y dice:
Era de noche, los bandidos se refugiaron en el bosque. El capitán se levanta y dice:
- Pedro, cuéntanos esa historia que tan bien sabes y tan mal dices
Pedro se levanta y dice:
…
La recursividad es la propiedad por la cual una función o trozo de código se llama a sí mismo. Para mí es una práctica bastante útil para ciertas tareas (la más socorrida podría ser sin lugar a dudas la de recorrer un árbol de directorios), pero desde luego no se trata de una práctica que acostumbre a pasar inadvertida. Hay defensores de ella, que la ven como una forma de evitar repeticiones de código o interminables bucles anidados; y también tiene firmes detractores, pues el código recursivo requiere más memoria y requiere más atención del programador (esto lo digo por mi experiencia).
Tenéis más información en este post de Picando Código.
Publicado en Conceptos el 21 de March, 2008 por Lek. (4 comentarios)
Una de las máximas de los programadores es que el código debe ser fácilmente legible. Suele decirse que no hay mejor documentación de un programa que su código fuente. Hacer lo contrario, programar deliberadamente de forma que no sea legible es una práctica de programación conocida como ofuscación. Un arte como otro cualquiera, que tiene sus propios concursos y todo.
Para las empresas es una práctica útil para complicar a la competencia el entendimiento del código decompilado (aunque sea ilegal decompilarlo). Pero como es complicado hacer grandes programas de esta forma, existen multitud de herramientas que lo hacen por nosotros. Para Java he encontrado este listado en la página del ProGuard.
Sin embargo, en ocasiones uno se encuentra con un programa doblemente ofuscado… porque está ofuscado por pura ilegibilidad. Imaginad el siguiente trozo de código y comprenderéis…
FileOutputSream ff = new FileOutputStream (
String.valueOf (
String.valueOf (
(
new StringBuffer (
String.valueOf (
String.valueOf (
new File (
String.valueOf (
String.valueOf (
(
new StringBuffer (
String.valueOf (
String.valueOf (
System.getProperty (
"java.home"
)
)
)
)
).append (
System.getProperty (
"file.separator"
)
).append (
"empresa"
)
)
)
)
)
)
)
).append (
System.getProperty (
"file.separator"
)
).append (
"adm.conf"
)
)
)
);
Es un trozo de código de un programa real y tenéis la suerte de que os lo he ordenado un poco, porque estaba en 4 líneas tan solo………
Publicado en C/C++, Conceptos, Java el 3 de March, 2008 por Fran. (3 comentarios)
Después de la pequeña discusión en el post sobre la mutabilidad de las clases en Java, me propongo aclarar un poco el dilema y las dudas sobre lo qué realmente ocurre al pasar parámetros por referencia o por valor.
La definición de un parámetro por referencia nos dice que es aquel parámetro cuyo valor se puede modificar dentro de la función y se propagará a la variable que se paso como parámetro fuera de la función, es decir, nuestra variable podrá cambiar de valor una vez ejecutada la función.
En cambio, la definición de un parámetro por valor nos dice que es aquel parámetro cuyo valor cuyo valor se puede modificar dentro de la función, pero que no se propagará a la variable que se paso como parámetro fuera de la función, es decir, nuestra variable nunca podrá cambiar de valor una vez ejecutada la función.
Normalmente (por lo menos con los lenguajes de programación que yo he tratado) lo que se hace es que en los parámetros por referencia se pasa la dirección de la variable usándose ésta dentro de la función, y en los parámetros por valor se crea una copia de la variable que se usará dentro de la función.
Leer el resto »
Publicado en Conceptos el 15 de October, 2007 por Lek. (2 comentarios)
Empecemos con algo lúdico-festivo:
Juanito fue contratado para pintar una carretera. El primer día pintó 100 km, el segundo 70 y el tercero 30. Su jefe, preocupado por esta alarmante bajada en su rendimiento le preguntó qué le pasaba, a lo que Juanito le contestó: “Es que el cubo de pintura cada vez me queda más lejos”
El rendimiento de un programa es, a grosso modo, lo que tarda en realizar su cometido. Es, de todas las métricas de calidad, una de las más difíciles de evaluar para mí. No solemos disponer de ejemplos lo suficientemente grandes, en ocasiones el problema aparece en una librería de terceros o, simplemente, se escapa de nuestro control (hasta que aparece). Lo que suele ser común en todos los casos es el mal uso de los tipos String (o similar), y es que en todos los lenguajes que conozco el tratamiento de los String es una mierda (bueno, en realidad suele estar entre una puta mierda y una putísima mierda).
Os expongo como ejemplo lo que me ha pasado con un proyecto recientemente. Consistía en generar unos ficherucos y enviarlos a un servidor vía HTTP. No problem. Los ficheros con los que probamos funcionaban a las mil maravillas y el proyecto pasó a pilotaje dividido en 2 partes: la generación y el envío. Cuando quisieron hacer una prueba enviando datos de un mes (en lugar de un día), aquello explotó. Revisando toda la parte de generación solventamos el problema y pasó de tardar 8 horas a 15 segundos, ¡¡cambiando sólo 3 líneas de código!!. La cosa siguió funcionando hasta la semana pasada, en que empezaron a fallar ficheros de 75 y 40 megas respectivamente, ahora en la parte de envío (solventado el jueves :)).
Éste es un tema para hablar largo y tendido, porque ejemplos hay miles y creo que todos los que hayamos programado habremos sufrido estas pérdidas, en principio inexplicables. Y, además, está relacionado con algo de lo que hablaré dentro de poco (espero): trampear los límites.