Category : General

Quiero cambiar al mundo…


Pregunta Java

La clase HashSet implementa la interface Set, respaldada por una tabla de hash (de hecho una instancia de HashMap).   No se garantiza que la iteración sobre la misma arrojará resultados en un orden particular y no existe garantía sobre si el orden permanecerá constante a lo largo del tiempo. Esta clase permite el elemento null.


Algunos de los Errores Más Críticos en el Desarrollo de Software

1–Neutralización inadecuada de elementos especiales usados en un comando SQL (SQL Injection)

La inyección SQL es un método de infiltración de código intruso que se vale de una vulnerabilidad informática presente en una aplicación en el nivel de validación de las entradas para realizar consultas a una base de datos.
El origen de la vulnerabilidad radica en el incorrecto chequeo y/o filtrado de las variables utilizadas en un programa que contiene, o bien genera, código SQL. Es, de hecho, un error de una clase más general de vulnerabilidades que puede ocurrir en cualquier lenguaje de programación o script que esté embebido dentro de otro.





2.-Neutralización inadecuada de elementos especiales usados en un comando OS (‘OS Command Injection’)

Un ataque de inyección de comandos en el sistema operativo se produce cuando un atacante intenta ejecutar comandos de sistema a través de una aplicación vulnerable. Las aplicaciones se consideran vulnerables al ataque de inyección de comandos si se utilizan las entradas del usuario y se ejecutan directamente.

3.- Copia de buffer sin comprobar el tamaño de la entrada. (Clásico ‘Buffer Overflow’)

Es un error de software que se produce cuando un programa no controla adecuadamente la cantidad de datos que se copian sobre un área de memoria reservada a tal efecto (buffer), de forma que si dicha cantidad es superior a la capacidad preasignada los bytes sobrantes se almacenan en zonas de memoria adyacentes, sobrescribiendo su contenido original.

4.-Neutralización inadecuada de datos entrada durante la generación de Web Pages (‘Cross-site Scripting’)

XSS, del inglés Cross-site scripting es un tipo de inseguridad informática o agujero de seguridad típico en las aplicaciones Web, que permite a una tercera parte inyectar páginas web o contenido ajeno, para ser visto por el usuario usando código JavaScript u otro lenguaje script similar (ej: VBScript), evitando medidas de control como la Política del mismo origen. Este tipo de vulnerabilidad se conoce en español con el nombre de Secuencias de comandos en sitios cruzados.

5.- Falta de Autenticación en Funciones Críticas.

La falta de autenticación es común en los sistemas que por falta de tiempo para su desarrollo o descuido son dejados al final.  Los programadores se enfocan en crear los módulos críticos del sistema que son los mínimos necesarios para operar y dejan funciones de autenticación para el final.

6.- Falta de Autorización.

Este problema no es igual al del punto 5, aquí se trata de restringir a los usuarios de un sistema a ciertas funciones dentro de una aplicación.   No todos lo usuarios deben tener los mismos privilegios y la autenticación no es suficiente.  Por ejemplo, si tienes una función para crear o dar de alta a usuarios nuevos, esta función debe quedar restringida para perfiles con privilegios de administrador.

7.- Uso de credenciales “Hard-code”

Crear una contraseña oculta en el código para poder acceder sin restricciones es muy mala idea, una vez que esta contraseña se sabe la violación de seguridad es permanente.

8.- La falta de cifrado en datos confidenciales.

Siempre que se provee de autenticación a usuarios es necesario almacenar de alguna forma un username y una contraseña.  Almacenar la contraseña o cualquier otro dato crítico, sin ningún tipo de cifrado, permite que un atacante que haya podido vulnerar el acceso a una base de datos o cualquier otro medio de almacenamiento que use tu sistema, tome también los datos de acceso de los usuarios y use otras funciones críticas de la aplicación de forma directa.

9.- Carga no restringida de archivos potencialmente peligrosos.

Algunas veces se provee a los usuarios de funciones que permitan cargar imágenes, documentos o cualquier clase de archivo que la solución lo requiera.  Se debe tener cuidado en filtrar todos aquellos archivos que puedan ser ejecutados tanto por el sistema operativo como por el contenedor web, o bien simplemente utilizados con fines distintos a los que se ha diseñado la solución.

10.- Depender de Entradas que no son confiables para decisiones críticas.

No se debería por ejemplo, permitir a usuarios ejecutar funciones críticas o la descarga de contenido no apropiado basándose en los datos que proporciona, como su edad o algún otro dato que pueda ser fácilmente falseable.  A veces es necesario proveer a las aplicaciones de una serie de candados como números de seguridad, identificaciones oficiales, captchas, etc.


Dale una Paleta


10 de las Mejores Prácticas en Java

1.- Evitar la creación innecesaria de objetos, Lazy Initialitation

La creación de objetos en Java es una de las operaciones mas costosas en términos de uso de memoria e impacto en el performance.  Esto es evitable creando o inicializando objetos solo en el momento en que serán requeridos en el código.

1
2
3
4
5
6
7
8
9
10
11
12
public class Paises {
 
    private List paises;
 
    public List getPaises() {
        //se inicializa solo cuando es requerido
        if(null == paises) {
            paises = new ArrayList();
        }
        return paises;
    }
}



2.- Nunca hacer variables de instancia públicas

Hacer una variable de instancia pública puede ocasionar problemas en un programa.  Por ejemplo si tienes una clase MiCalendario. Esta clase contiene un arreglo de cadenas diasDeLaSemana.  Pero es una arreglo público y este puede ser accedido por cualquiera.  Tu asumes que este arreglo contiene siempre los 7 nombres de los días de la semana.  Alguien por error puede cambiar el valor e insertar un error!

1
2
3
4
5
6
7
8
public class MiCalendario {
 
    public String[] diasDeLaSemana =
        {"Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"};
 
    //mas código
 
}

La mejor práctica como mucho de ustedes saben, es definir siempre estas variables como privadas y crear los métodos accesores, “setters“ y “getters”

1
2
3
4
5
6
private String[] diasDeLaSemana =
    {"Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Sabado", "Domingo"};
 
public String[] getDiasDeLaSemana() {
    return diasDeLaSemana;
}

Pero escribir los métodos accesores no resuelve el problema del todo.  El arreglo sigue siendo accesible.  La mejor forma de hacerlo inmodificable es devolviendo un arreglo clonado en lugar del arreglo mismo.  Esto se logra modificando el método get de la siguiente forma.

1
2
3
public String[] getDiasDeLaSemana() {
    return diasDeLaSemana.clone();
}

3.- Trata siempre de minimizar la Mutabilidad de las clases

Hacer una clase inmutable es hacerla inmodificable.   La información de la clase se preservará durante el tiempo de vida de la clase.  Las clases inmutables son simples y fáciles de manejar.  Son “thread safe”.  Normalmente son los bloques que permiten formar otros objetos más grandes.

No obstante, crear objetos inmutables pueden golpear significativamente el rendimiento de una aplicación.  Así que elije cuidadosamente si quieres que una clase sea o no inmutable.  Trata siempre de tener clases pequeñas con el menor número de clases inmutables.

Para hacer una clase inmutable puedes definir sus constructor de forma privada y luego crear un método estático para inicializar al objeto y devolverlo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Empleado {
 
    private String primerNombre;
    private String segundoNombre;
 
    // constructor private default
    private Empleado (String primerNombre, String segundoNombre) {
        this. primerNombre = primerNombre;
        this. segundoNombre = segundoNombre;
    }
 
    public static Empleado valueOf (String primerNombre, String segundoNombre) {
        return new Empleado (primerNombre, segundoNombre);
    }
}

4.- Trata de usar más las Interfaces sobre las Clases Abstractas

No es posible la herencia múltiple en Java, pero definitivamente puedes implementar múltiples interfaces.  Esto hace que cambiar la implementación de una clase existente sea fácil y que puedas implementar una o mas interfaces en lugar de cambiar la jerarquía completa de la clase.

Pero si tu estás cien por ciento seguro de que métodos de una interface tendrás, entonces solo implementa esa interfaz.   Es bastante difícil agregar un nuevo método en una interfaz existente sin alterar todo el código que se está implementando.  Por el contrario un nuevo método puede ser fácilmente agregado en una clase abstracta sin alterar la funcionalidad existente.

5.- Limita siempre el alcance de una variable local

Las variables locales son grandiosas.  Pero algunas veces pueden insertar mas bugs durante el copiado y pegado de código viejo. Minimizar el alcance de una variable local hace que el código sea mas legible, menos propenso a errores  y mas mantenible.

Por lo tanto, debemos declarar variables justo antes de ser usadas.

Procura inicializar una variable desde su declaración.  Si eso no es posible asígnale el valor nulo.

6- Trata de usar librerías estándar en lugar de hacer las tuyas desde cero

Escribir código es divertido.  Pero no reinventes la rueda.  Es bastante recomendable usar librerías estándar que ya han sido probadas, debugeadas y usadas por otros.    Esto no sólo mejora la eficiencia de un programador sino que reduce las posibilidades de tener errores en el código.  Además, usar una librería estándar  hace al código mas legible y mantenible.

Por ejemplo Google tiene liberada la nueva librería Google Collections que puede ser usada para agregar mas funcionalidad a tu código.

7.- Siempre que sea posible trata de usar tipos primitivos en lugar de las clases Wrapper

Las clases Wrapper son buenas, pero también son lentas.  Los tipos primitivos son como clases, sin embargo las clases wrapper almacenan la información completa acerca de una clase.

Algunas veces un programador puede agregar un error en el código usando una wrapper por un descuido.  Por ejemplo:

1
2
3
4
5
6
7
8
int x = 10;
int y = 10;
 
Integer x1 = new Integer(10);
Integer y1 = new Integer(10);
 
System.out.println(x == y);
System.out.println(x1 == y1);

El primer System.out.println imprimirá true mientras que el segundo imprimirá false.  El problema cuando comparas dos clases wrapper es que no se puede usar el operador ==, porque en realidad se están comparando referencias y no sus valores actuales.

Además si estás usando una clase wrapper no debes olvidar inicializarla.  Porque el valor por default de las variables wrapper es null.

1
2
3
4
5
6
7
8
9
Boolean bandera = null;
 
        //más código
 
if(bandera == true) {
    System.out.println("Se establece el valor de bandera");
} else {
    System.out.println("No se establece el valor de bandera");
}

El código lanzará un NullPointerException cuando se trate de comparar con true y el valor sea nulo si en el código intermedio no fue inicializada.

8.- Usa los Strings con mucho cuidado

Usa siempre las cadenas con mucho cuidado en tu código.  Una simple concatenación de cadenas puede reducir el rendimiento de tu programa.  Por ejemplo si queremos concatenar cadenas usando el operador “+” en un ciclo for entonces todo el tiempo se estará creando un objeto String.  Esto afecta tanto a la memoria como al rendimiento.

Además en lugar de que instancies una objeto String no uses su constructor, sino que debes instanciarlo directamente. Por ejemplo:

1
2
3
4
5
//instanciación lenta
String lenta = new String("solo otro objeto string");
 
//instanciación rápida
String rapida = "solo otro objeto string";

9.- Siempre regresa colecciones vacías en lugar de nulas

No importa que tu método regrese una colección o un arreglo, siempre asegúrate de que cuando sea necesario se regrese vacío y no nulo, en aquellos casos en los que no contendrá elementos porque la lógica de tu programa lo requiera.  Esto te ahorrará un montón de tiempo cuando hagas pruebas para valores nulos.



10.- El copiado defensivo es salvador

El copiado defensivo hace que los objetos creados estén libres de la mutación.  Por ejemplo en el código siguiente tenemos definida la clase Estudiante la cual a su vez tiene una variable con la fecha de nacimiento que es inicializada cuando el objeto es construido.

1
2
3
4
5
6
7
8
9
10
11
public class Estudiante {
    private Date fechaNacimiento;
 
    public Estudiante(Date fechaNacimiento) {
        this. fechaNacimiento = fechaNacimiento;
    }
 
    public Date getFechaNacimiento () {
        return this.fechaNacimiento;
    }
}

Ahora podríamos tener el siguiente código que use al objeto Estudiante.

1
2
3
4
5
6
public static void main(String []arg) {
    Date fechaNacimiento = new Date();    
    Estudiante estudiante = new Student(fechaNacimiento);
    fechaNacimiento.setYear(2019);
    System.out.println(estudiante.getFechaNacimiento ());
}

En el código siguiente creamos tan solo al objeto Estudiante con algunas fechas de nacimiento por default.  Pero entonces cambiamos el valor del año de nacimiento.  Después imprimimos el año de nacimiento, este año fue cambiado por 2019!

Para evitar estos casos, se puede utilizar el mecanismo defensivo copias. Cambie el constructor de la clase del estudiante a lo siguiente.

1
2
3
public Estudiante(Date fechaNacimiento) {
    this.fechaNacimiento = new Date(fechaNacimiento);
}

Esto para asegurarnos de tener otra copia de la fecha de nacimiento que usamos en clase Estudiante.

11.-  Nunca dejes salir una excepción de un bloque finally

12.- Nunca lances «Exception» directamente.

tomado de: http://viralpatel.net


Depuración


Una carrera con el Universo


Don’t Panic


Debes programar…


Por si las dudas…





Programar es divertido