De Java 9 a Java 11: Lo más destacado en cada versión

Java 9 (septiembre 2017)


No es LTS, pero fue una versión muy importante por los siguientes cambios:
  • 1. Sistema de Módulos (Project Jigsaw)
    • Introducción del sistema de módulos (module-info.java).
    • Mejora la encapsulación, permite dividir el JDK en módulos.
    • Permite a las aplicaciones definir qué partes del código exponen o requieren.

    module com.ejemplo.miapp {
        requires java.base;
    }
    

  • 2. JShell (REPL)
    • Nueva herramienta interactiva de línea de comandos.
    • Permite probar fragmentos de código Java sin necesidad de compilar clases.
  • 3. API Stream mejorada
    • Nuevos métodos: takeWhile(), dropWhile(), ofNullable(), etc.
  • 4. Interface privada en métodos
    • Métodos privados en interfaces, útil para compartir lógica entre métodos default o static.


Java 10 (marzo 2018)


También no LTS, pero con una novedad destacada:
  • 1. var – Inferencia de tipo local
    • Permite declarar variables con inferencia de tipo a nivel local.
    var lista = new ArrayList<String>();
    
    • Mejora la legibilidad
    • Solo se puede usar en variables locales, no en parámetros o atributos

  • 2. Recolección de basura experimental (G1 mejoras)
    • Mejoras en el recolector G1 GC (mejor administración de memoria).

  • 3. API de colecciones inmutables mejorada
    • Posibilidad de copiar fácilmente colecciones usando métodos copyOf() en List, Set, y Map.


Java 11 (septiembre 2018) – LTS


Versión LTS (Long-Term Support) — sucesora oficial de Java 8 para muchos entornos de producción.
  • 1. Nuevas funciones del lenguaje
    • var en parámetros de lambda:
    lista.forEach((var item) -> System.out.println(item));
    

  • 2. API HTTP Client (estable)
    • El nuevo HttpClient (experimental en Java 9) ahora es estable.
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.ejemplo.com"))
        .build();
    
    HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
    

  • 3. Métodos útiles en String
    • isBlank(), lines(), repeat(n), strip(), stripLeading(), stripTrailing()
    "Hola ".repeat(3); // Hola Hola Hola
    

  • 4. Eliminación de APIs obsoletas
    • Se eliminaron herramientas y módulos antiguos: Java EE y CORBA (como javax.xml.bind, javax.activation, etc.)

  • 5. Nuevo recolector de basura: ZGC (experimental)
    • ZGC (Z Garbage Collector), un recolector de baja latencia, escalable.



Resumen

Versión Estado Novedades Clave
Java 9 No LTS Sistema de módulos, JShell, mejoras en Stream
Java 10 No LTS var para variables locales, mejoras en GC
Java 11 LTS HttpClient, mejoras en String, var en lambdas, eliminación de Java EE

Java 8: Las Principales Novedades que Revolucionaron el Lenguaje


Las Principales Novedades que Revolucionaron el Lenguaje

Desde su lanzamiento en marzo de 2014, Java 8 marcó un hito en la evolución del lenguaje, incorporando características largamente esperadas por la comunidad. Si vienes de Java 7, este artículo te pone al día con los cambios más importantes que trajo esta versión.

  • 1. Expresiones Lambda


    ¡La estrella de Java 8! Las expresiones lambda permiten tratar funciones como ciudadanos de primera clase, facilitando el trabajo con APIs funcionales y reduciendo el código "boilerplate"

    // Antes
    Collections.sort(lista, new Comparator<String>() {
        public int compare(String a, String b) {
            return a.compareTo(b);
        }
    });
    
    // Con Lambda
    lista.sort((a, b) -> a.compareTo(b));
    

    ✅ Más conciso
    ✅ Más legible
    ✅ Ideal para trabajar con colecciones

  • 2. API Stream

    La nueva Stream API permite procesar colecciones de manera funcional, con operaciones como map, filter, reduce, etc. Ideal para trabajar con datos de forma declarativa y paralelizable.

    List<String> nombres = Arrays.asList("Ana", "Luis", "Pedro");
    List<String> resultado = nombres.stream()
        .filter(n -> n.startsWith("P"))
        .map(String::toUpperCase)
        .collect(Collectors.toList());
    

  • 3. Interface con Métodos por Defecto (Default Methods)

    Ahora las interfaces pueden tener implementaciones por defecto, lo que permite extender interfaces sin romper la compatibilidad con versiones anteriores.

    interface Saludo {
        default void decirHola() {
            System.out.println("Hola!");
        }
    }
    

  • 4. Referencias a Métodos y Constructores

    Una forma elegante de referirse a métodos existentes sin ejecutarlos, útil sobre todo en programación funcional.

    // Lambda
    lista.forEach(s -> System.out.println(s));
    
    // Referencia a método
    lista.forEach(System.out::println);
    

  • 5. Nueva API de Fecha y Hora (java.time)

    Se introdujo un nuevo paquete java.time.*, inspirado en la biblioteca Joda-Time. Mucho más intuitivo, inmutable y libre de los problemas del antiguo Date y Calendar.

    LocalDate hoy = LocalDate.now();
    LocalDate cumpleaños = LocalDate.of(1990, Month.JUNE, 3);
    Period edad = Period.between(cumpleaños, hoy);
    

  • 6. Optional: Evitando NullPointerException

    El nuevo tipo Optional<T> ayuda a manejar valores potencialmente nulos de forma segura y explícita.

    Optional<String> nombre = Optional.ofNullable(obtenerNombre());
    nombre.ifPresent(n -> System.out.println(n.toUpperCase()));
    

  • 7. Mejoras en la JVM y rendimiento

    Aunque más técnicas, Java 8 trajo mejoras en el rendimiento de la JVM, la incorporación del compilador Nashorn para ejecutar código JavaScript, y optimizaciones internas que hacen a las lambdas y streams muy eficientes.




Libros para programadores en JAVA

Para principiantes:

  • Head First Java de Kathy Sierra y Bert Bates

    Este libro es ideal si estás empezando en la programación. Utiliza un enfoque visual y accesible, con muchos ejemplos prácticos. Te ayudará a comprender los conceptos básicos de Java y la programación orientada a objetos de manera amena.

  • Java: A Beginner's Guide de Herbert Schildt

    Un clásico para aquellos que quieren entender Java desde cero. Explica desde lo más básico hasta temas más avanzados de una forma clara y progresiva. Es excelente para nuevos programadores.

  • Effective Java (3ra edición) de Joshua Bloch

    Aunque es un libro más avanzado, puede ser útil incluso para principiantes con algo de experiencia. Está repleto de buenas prácticas y consejos útiles para escribir código Java limpio y eficiente.

Para desarrolladores intermedios y avanzados:

  • Java: The Complete Reference de Herbert Schildt

    Este libro es un recurso exhaustivo sobre Java, cubriendo tanto la sintaxis básica como las bibliotecas y API más avanzadas. Ideal para desarrolladores que buscan una guía completa sobre el lenguaje.

  • Clean Code: A Handbook of Agile Software Craftsmanship de Robert C. Martin

    Aunque no está enfocado exclusivamente en Java, es una obra clave para aprender buenas prácticas de programación y diseño de código limpio. Sus principios son aplicables a cualquier lenguaje, y muchos ejemplos están hechos en Java.

  • Java Concurrency in Practice de Brian Goetz

    Si tienes algo de experiencia con Java y quieres profundizar en la programación concurrente, este libro es esencial. Te enseña a trabajar con hilos, sincronización, y cómo escribir aplicaciones Java concurrentes seguras.

  • Spring in Action de Craig Walls

    Si te interesa trabajar con el popular framework Spring, este libro es una excelente guía para aprender a desarrollar aplicaciones robustas con Java. Cubre temas como la inyección de dependencias, AOP (Aspect-Oriented Programming), y la configuración de Spring.

  • Springboot in Action de Craig Walls

    También del mismo autor, esta es guía práctica para desarrollar aplicaciones Java con Spring Boot. A través de ejemplos claros, el autor explica cómo simplificar el proceso de configuración y despliegue, aprovechando la potencia de Spring Framework para crear aplicaciones robustas y escalables de manera eficiente.

Para especialización:

  • Java Performance: The Definitive Guide de Scott Oaks

    Este libro es perfecto para aquellos que deseen optimizar el rendimiento de sus aplicaciones Java. Cubre desde la optimización de la memoria hasta la mejora del rendimiento en la ejecución de aplicaciones en producción.

  • Java: The Good Parts de Jim Waldo

    Este libro es ideal para los desarrolladores que ya tienen experiencia con Java y desean centrarse en los aspectos más poderosos del lenguaje. Es una excelente manera de aprender a escribir un código más eficiente y conciso.

  • Maven: The definitive guide por Sonatype

    Ésta es una guía completa para aprender a usar Apache Maven, una herramienta de automatización de construcción. El libro cubre desde la configuración básica hasta técnicas avanzadas, explicando cómo gestionar dependencias, construir proyectos, integrar con otros sistemas y optimizar el proceso de desarrollo.

  • Oracle Certified Associate Java SE 8 Programmer I de Jeanne Boyarsky y Scott Selikoff

    Ésta es una guía completa para preparar el examen de certificación OCA Java SE 8. El libro cubre los fundamentos de Java, incluyendo sintaxis, estructuras de control, clases, interfaces, y manejo de excepciones, proporcionando ejercicios prácticos y consejos para el examen.

Frameworks a los chapazos: Maven (Parte 2/2)


Frameworks a los chapazos: Maven (Parte 2/2)



Más Maven

Aun quedan temas por cubrir como herencia, super POM, Standard Directory Layout, Repositorios, Plugins, Arquetipos, instalación

Instalación


Podemos salir de la instlación, fácil, rápido y para toda la familia. Simplemente googleamos 'download maven' y el primer enlace deberia ser este:

https://maven.apache.org/download.cgi




Procedimiento

  • Descargar los archivos binarios en zip o tar.zip según sistema operativo
  • Alojarlos en alguna carpeta que nos resulte cómoda
  • Setear esa ruta como M2_HOME (este nombre es por conveniencia) y agregarla al PATH del sistema incluyendo a la carpeta bin donde se encuentra el comando mvn, (set en Windows y export en linux y mac)
  • verificar instalación en la terminal con el comando mvn --version ó -v en su versión corta:


Herencia en Maven


En Maven, la herencia se refiere a la capacidad de un proyecto (o módulo) para heredar configuraciones y propiedades de un proyecto padre. Esto es útil para gestionar configuraciones comunes y evitar la duplicación de código.

¿Cómo Funciona?


En el pom.xml la herencia define un proyecto hijo hereda las configuraciones del proyecto padre.
  • Proyecto Padre (pom.xml):

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/POM/4.0.0/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>pom</packaging>
       
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>5.3.8</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    </project>
    

  • Proyecto Hijo (pom.xml):

  • <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/POM/4.0.0/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>com.example</groupId>
            <artifactId>parent-project</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <artifactId>child-project</artifactId>
    </project>
    

En este ejemplo, el proyecto hijo hereda las dependencias y configuraciones definidas en el proyecto padre, para el caso concreto mostrado, el hijo cuenta como dependencia spring-core-5.3.8 porque su padre la declara como dependencia y se funciona como en la vida real, se heredan muchas caracteristicas de nuestros padres.

¿Qué es el Super POM?


El Super POM es el archivo de configuración base de Maven que se aplica a todos los proyectos. Define los valores predeterminados y comportamientos generales para todos los proyectos Maven. A términos de java, el super POM viene a ser como la clase Object, de la cúal todo heredan ímplicitamente de ésta, atributos y comportamientos.
Características del Super POM:
  • Ubicación: El Super POM está integrado en Maven y no se encuentra en tu proyecto.
  • Configuraciones Predeterminadas: Incluye configuraciones predeterminadas para el proceso de construcción, como plugins predeterminados y propiedades. Ejemplo de Configuración en el Super POM
  • No puedes ver ni modificar el Super POM directamente, pero puedes consultar su contenido en la documentación de Maven(https://maven.apache.org/ref/3.8.4/maven-model/maven.html#super-pom).
  • O pueder ir a el xml, dentro del jar(la versión puede variar, pero coincide con la versión de maven) y está en la carpeta de instalación:
    $MAVEN_HOME/lib/maven-model-builder-3.6.3.jar/org/apache/maven/model/pom-4.0.0.xml
    
Aquí podemos encontrar la definición del repositorio de maven central, la estructura de directorios, librerías básicas entre otras definiciones.

Standard Directory Layout


El Standard Directory Layout es la estructura de directorios recomendada para proyectos Maven. Facilita la organización del código fuente, recursos, pruebas, y otros archivos importantes.
Estructura de Directorios:
project-root/
|-- src/
|   |-- main/
|   |   |-- java/          # Código fuente principal
|   |   |-- resources/     # Recursos (archivos de configuración, imágenes, etc.)
|   |-- test/
|       |-- java/          # Código fuente de pruebas
|       |-- resources/     # Recursos de pruebas
|-- target/                # Archivos generados (compilaciones, artefactos)
|-- pom.xml                # Archivo de configuración de Maven

Puede sobrescribir esta estructura de carpetas en tu pom, pero ¿para qué hacerlo?.

Repositorios


Los repositorios son ubicaciones donde Maven almacena artefactos (librerías, proyectos) y sus dependencias. Maven utiliza repositorios para buscar e instalar dependencias necesarias para el proyecto.
Tipos de Repositorios
  • Repositorio Local: Almacena artefactos en tu máquina local (usualmente en el directorio .m2/repository).
  • Repositorio Central: El repositorio predeterminado al que Maven se conecta para descargar dependencias. Maven Central es el repositorio central más conocido.
  • Repositorios Remotos: Otros repositorios externos que puedes configurar en tu archivo pom.xml.
Ejemplo de Configuración de Repositorios en pom.xml

<repositories>
    <repository>
        <id>my-repo</id>
        <url>https://my.repo.url/repository</url>
    </repository>
</repositories>

¿Qué son los Plugins en Maven?


Los plugins se definen en el archivo pom.xml y se configuran en la sección de <build>.
Ejemplo de Configuración de Plugin
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Arquetipos


Un arquetipo es una plantilla para crear proyectos Maven nuevos. Define una estructura de proyecto predeterminada y puede incluir archivos de configuración básicos, código de muestra, y otros recursos.

Crear un Proyecto Usando un Arquetipo:

mvn archetype:generate -DgroupId=com.example -DartifactId=my-project -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Esto creará un nuevo proyecto basado en el arquetipo maven-archetype-quickstart.

[Métodos] Serializar y Deserializar objetos con Java


[Métodos] Serializar y Deserializar objetos con Java



La serialización y deserialización son dos procesos utilizados en programación para convertir datos como texto o incluso un objeto de una clase, a un formato de código binario para almacenarlo o transmitirlo, y luego revertir ese proceso en otro momento o lugar para recuperar los datos originales.

Tomemos como ejemplo la sigueinte clase Persona

public class Persona implements Serializable {
    private static final long serialVersionUID = 1L; // Identificador de versión para la serialización
    private String nombre;
    private int edad;
    private String ciudad;

    // CONSTRUCTORES
    // GETTERS y SETTERS
}


Es una simple clase en java que implementa la interfaz Serializable, de la cual cobra sentido el atributo serialVersionUID ya este número de versión nos indicará a la hora de deserializar si la clase ha sufrido algún cambio o modificación.
El siguiente ejemplo, muestra un método main que:
  • Instancia un objeto de la clase Persona
  • Serializa el objeto y lo guarda en un archivo, misma ubicación donde se está ejecutando, bajo el nombre de "persona.ser"
  • Por último, este fragmento de Deserialización pudiera estar en otro lado, pero hace lo propio deserializando un archivo "persona.ser", en la misma ubicación que la ejecución y lo lleva a un objeto Persona

    public static void main(String[] args) {
        // Crear una instancia de Persona
        Persona persona = new Persona("Darío", 35, "Buenos Aires");

        // Serialización
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("persona.ser"))) {
            oos.writeObject(persona);
            System.out.println("Persona serializada correctamente.");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Deserialización
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("persona.ser"))) {
            Persona personaDeserializada = (Persona) ois.readObject();
            System.out.println("Persona deserializada: " + personaDeserializada);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


Por último, nuestra propia implementación para reutilizar en métodos independientes:

Serializar


    public static void serializarObjeto(Object objeto, String ubicacion, String nombreArchivo) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(ubicacion + File.separator + nombreArchivo))) {
            oos.writeObject(objeto);
            System.out.println("Objeto serializado correctamente en: " + ubicacion + File.separator + nombreArchivo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


Deserializar


    // Método para deserializar un objeto desde un archivo
    public static Object deserializarObjeto(String ubicacion, String nombreArchivo, String nombreClase) {
        Object objetoDeserializado = null;
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(ubicacion + File.separator + nombreArchivo))) {
            objetoDeserializado = ois.readObject();
            System.out.println("Objeto deserializado correctamente desde: " + ubicacion + File.separator + nombreArchivo);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return objetoDeserializado;
    }


Uso

    public static void main(String[] args) {
        // Ejemplo de serialización y deserialización
        Persona persona = new Persona("Dario", 35, "Buenos Aires");

        // Serialización
        serializarObjeto(persona, "ruta/del/directorio", "persona.ser");

        // Deserialización
        Persona personaDeserializada = (Persona) deserializarObjeto("ruta/del/directorio", "persona.ser", Persona.class.getName());
        System.out.println("Persona deserializada: " + personaDeserializada);
    }

Frameworks a los chapazos: Maven (Parte 1/2)


Frameworks a los chapazos: Maven (Parte 1/2)



Maven es una herramienta de software para la gestión y construcción de proyectos Java creada por Jason van Zyl, de Sonatype, en 2002. Es similar en funcionalidad a Apache Ant, pero tiene un modelo de configuración de construcción más simple, basado en un formato XML. (fuente: Wikipedia)

Antes de Maven

Cada proyecto solía definir su forma de incluir dependencias, definir versión del proyecto, de compilar desde una version de jre a la version target, como realizar pruebas unitarias, generar reportes, crear ejecutables a partir del código fuente y hasta como se debería hacer la entrega de ese ejecutable.
Todo esto conlleva a que los desarrolladores tuvieran que invertir mucho tiempo para poder sumarse a un proyecto y al final del día para poder entregar el ejecutable final. Luego de esto, vuelta a empezar...

POM

El corazón de un proyecto manejado por maven es un fichero llamado pom.xml, que significa Project Object Model y debe encontrarse en la raíz de nuestro projecto.

1
2
3
4
5
6
7
8
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>my-project</artifactId>
  <version>1.0.0</version>
</project>

Las coordenadas maven

En el ejemplo anterior podemos ve que se definen las coordenas maven, la manera única de identificar a cualquier proyecto maven entre otro proyectos maven.
  • GroupId: identifica a nuestra empresa o persona, y debe ser nuestro dominio invertido. Opcionalmente puede contener el grupo de aplicaciones
  • ArtifactId: identifica a nuestro artefacto, nuestro proyecto o microservicio.
  • version: la version del proyecto mismo.

Adicionalmente podemos encontrar debajo de las coords nuestro packaging, el tipo de empaquetado que resulta de nuestro projecto, pudiendo ser jar, war, ear o pom, entre otras. Si no se espefica ninguno, tomará el por defecto: jar.

Los ciclos de vida

Maven cuenta con 3 ciclos de vida predefinidos: clean, default y site
  • Clean: se encarga de eliminar la carpeta target básicamente.
  • Default: maneja el ciclo de vida pero de nuestro proyecto.
  • Site: se encarga de generar la documentación si es que la hubiera.

Cada uno de estos ciclos se puede ejecutar de manera independiente, aunque por lo general llamaremos al clean y a algunas de las fases de Default.

Fases de los ciclos de vida

Cada ciclo de vida de maven incluye fases progresivas, es decir que cada fase se ejecutará luego de haber ejecutado la anterior aunque no la llamemos.

Clean

  • pre-clean: ejecuta los procesos necesarios para la limpieza.
  • clean: remueve todos los archivos generados en construcciones anteriores.
  • post-clean: finaliza los procesos de limpieza.

Default

  • validate: valida que el proyecto sea correcto y la información esté disponible.
  • compile: compila el código fuente del proyecto.
  • test: ejecuta los test unitarios usando un framework de testing.
  • package: toma el código compilado y lo empaqueta en un formato distribuible, como un jar.
  • verify: corre los checks de las pruebas de integración para asegurar que la calidad haya sido alcanzada.
  • install: instala el empaqueta, según coordenadas, en el repository local para que otro proyecto pueda usarlo.
  • deploy: copia el empaqueta del repositorio local al repositorio remoto, si es que lo hubiera.

Site

  • pre-site: ejecuta los procesos necesarios para esta fase.
  • site: genera la documentación del proyecto.
  • post-site: finaliza los procesos de esta fase y prepara el sitio para el despliegue.
  • site-deploy: despliega los archivos generados al servidor especificado.

Para el listado completo de las fases de cada ciclo visitar la documentación de maven aquí

Dependency Manager

Una de las caracteristicas más importantes de maven es la gestión de dependencias. Haciendo uso de las coordenadas podemos declaras dependencias para nuestro proyecto, estas se buscan en nuestro repo local y de no encontrarlas se descargán de maven central o repositorio que hayamos definido y luego se instalan en nuestro repositorio maven local para posterior uso. A continuación este ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>5.7.1</version>
      <type>jar</type>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
    ...
  </dependencies>
  ...
</project>

Dependencias, dependencias transitivas y resolución de conflictos

Como buen gestor de dependencias maven se encarga de incluir a nuestro proyecto las dependencias que declaremos en el pom, asi como también de las dependencias transitivas, estas son las dependencias de nuestras dependencias para que estas puedan funcionar correctamente.

También se encarga de la resolución de conflictos, en el ejemplo de la imagen nuestras dependencias 1 y 2 dependen de B, de ser la misma versión sólo la incluirá una vez, de ser distintas versiones tomará la mas nueva como válida.

Scope, type, optional y exclusion

Dentro de la etiqueta <project>, declaramos una sección de <dependencies> la cual incluye todas nuestras librerias envueltas con la etiqueta <dependency>, está a su vez incluye:

  • Coordenadas: estas son obligatorias y se utilizan para identenficar una libreria.
  • type: corresponde a la extensión del archivo. Es opcional y por defecto es jar.
  • scope: se refiere a como encontrar la dependencia y de como agregarla al classpath de la aplicación. Hay 5 scopes disponibles:
    • compile: este es el valor por defecto si se omite, tiene que ser encontrada en el momento de la compilación y estará disponible en todos los classpath. Será propagada a los proyectos que dependan de esta.
    • provided: es similar a compile, pero indica que se espera que el JDK o un contenedor lo provea al momento de ejecución. Sólo está disponible en el classpath de compilación y test, y no es transitiva.
    • test: este scope indica que la dependencia no es requerida para el uso normal de la aplicación, y sólo esta disponible para las fases de compilación y ejecución pero de los tests. No es transitiva.
    • runtime: este scope indica que la dependencia no es requerida para la compilación, pero si en la ejecución. Estará en el classpath de ejecucion y test, pero no en el classpath de compilación.
    • system: es similar a provided excepto que tenés que proveer el JAR que lo contiene de manera explícita. El artefacto siempre está disponible y nunca será buscando en los repositorios.
  • optional: Marca una dependencia como optional cuando este projecto en si mismo es una dependencia.

Más Maven

Aun quedan temas por cubrir como herencia, super POM, Standard Directory Layout, Repositorios, Plugins, Arquetipos, instalación

Principios en el diseño del software: KISS, DRY y SOLID


Principios del diseño de software



Los principios de diseño de software son como una guia que nos ayuda dando pautas para el desarrollo de estas aplicaciones.

A diferencia de los patrones de diseños, los principios no proveen con pasos, situaciones donde aplicarlos, es un poco mas generico.


Alguno de estos principios son siglas en ingles, obviamente, y son autoexplicativos. Alguno de ellos son kiss dry yagni soc solid.


Kiss (Keep it simple, stupid)


"Mantenelo simple corazón", esa es mi traducción por lo del beso y el corazón, aun que no haga falta ser bilingue para saber a que ser refiere la ultima S.

Otra variante podría ser invertir la palabras finales resultando ser "Mantenelo estupidamente simple" (keep it stupid simple) Este principio nos dice que tanto la documentación, el diseño, el código debe ser tan simple como sea posible, como si se tratará de leer una guia a prueba de tontos. Evitando la sobre-complicacíon cuando ésta sea innecesaria.

Luego de algún tiempo programando tendemos a aplicar nuestra experiencia resolviendo cuestiones no solicitadas, por ejemplo crear un formulario para visualizar datos existentes en una base de datos y queremos realizar una progresive web app con soporte de multilenguaje y personalización de estilos en tiempo de ejecución, con un backend con una arquitectura de microservicios, con servidores de descubrimiento, servidor de para balancear la carga, otro para estadisticas y métricas, montado sobre contenedores... y en fin muchas herramientas cuando existen alternativas mas sencillas.

Este es el principio más dificil de seguir en terminos de escalabildad. Por que nuestra solución sencilla es ideada para unos pocos usuarios, pero nuestro cliente confia que pronto tendrá cientos o miles de usuarios y pronto serán usuarios insatisfechos quejandose de lo lenta que resulta la herramienta que creamos manteniendo las cosas lo mas simple posible.

Será nuestra visión la que determine hasta donde se pueden mantener las cosas simples


DRY (Don’t Repeat Yourself))


O en español SECO (Siempre evita codigo oscuro), la máxima de este principio es evitar el uso del CTRL+C + CTRL+V, repitiendo funcionalidades entre distintas clases o métodos, ya que esto haria que el proyecto en general tenga mas lineas de codigo, sea dificil de entender y de mantener.


SOLID


  • Single Responsibility
  • Open/Closed
  • Liskov Sustitution
  • Interface segregation
  • Dependency inversion

A este principio le pusieron unas solidas ganas, introducido por Robert C. Martin y sus siglas agrupan otros 5 principios de la programacion orientada a objetos.

Single Responsibility, el principio de responsabilidad unica nos dice que una pieza de codigo tiene que tener una unica responsabilidad. Ese metodo getUsuario(id) deberia obtener un usuario por su id, o almenos eso se espera de el, pero si al inspeccionar de cerca el metodo nos damos cuenta que obtiene el usuario, actualiza la fecha de ultima actividad y le envia un mail con las novedades claramente estaria violando este principio, haciendo a la aplicacion dificil de entender por su impredictibilidad. Lo mas razonable sea contar con otros metodos como actulizarUltimaActividad(usuario) y informarNovedades(usuario) que se encarguen de una sola cosa.

Open/Closed, el principio de Abierto/Cerrado nos dice que una pieza de codigo tiene que estar abierta a extensiones pero cerrada al modificaciones. Este principio esta destinado a clases que puedan ser heredadas, donde sus clases hijas puedan extender su funcionalidad, pero sin cambiar lo que existia.

Liskov sustitution, el principio de sustition de Liskov nos dice que cada clase puede ser sustituida en lugar de su padre, sin la necesidad de conocer cual se esta implementando. Esto pasa generalmente al usar colecciones, definimos un objeto tipo List aunque la implementacion podria ser ArrayList, LinkedList.

Interface segregation, el principio de segregacion de interfaces dice que el codigo cliente no debiera estar atado a funcionalidades innecesarias al implementar una interfaz, esta no debe segregar metodos de proposito general. Una solucion a este problema es romper la interfaz en varias interfaces mas pequeñas y mas especificas. Otra solucion es el patron adapter, que permite heredar de una clase que implementa una interfaz extensa

Dependency inversion, el pricipio de inversion de dependencia nos dice que se debe depender de abstracciones y no de implementaciones, desacoplando asi los modulos de alto nivel de los modulos de bajo nivel. La Inyección de Dependencias es uno de los métodos que siguen este principio.


YAGNI (You aren’t gonna need it)


El principio de lo no vas a necesitar tiene su origen en la programación extrema, y propone evitar aquellas piezas de codigo que se desarrollan por si acaso, generalmente sobrevalidaciones, sin estar seguros de necesitarlo y nos dice no, no lo vas a necesitar.


SOC (Separation of concern)


El principio de separacion de conceptos nos habla de los diferentes aspectos de la funcionalidad de nuestra aplicación. Por ejemplo la capa de negocio, la capa de datos etc. Un buen ejemplo de separación es el patrón MVC(Modelo, vista, controlador).


The Boy Scout rule


Este no es un acronimo, si lo fuese seria TBSR, pero basicamente nos propone aplicar la regla del boyscout, dejar el campo en mejores condiciones de lo que lo encontamos. Como desarrolladores siempre se puede hacer un pequeño cambio para mejorar la calidad de nuestro codigo, algo que veamos al pasar y que estamos seguros que podemos mejorar, siempre y cuando este no sea un cambio.


La Ley de Demeter


Según este principio, una pieza de codigo solo debe tener conocimiento limitado de otras piezas de codigo, y solo conocer aquellas que con las que está relacionadas. Es como aquella frase que dice nunca hables con extraños, podriamos agregar con amigos cerrcanos.


El principio de Hollywood


Este principio está basado en la típica respuesta que se les da a los actores que hacen una audicion para una película: "No nos llame, nosotros le llamaremos". Un ejemplo del principio de Hollywood es la inversión de control (IoC), que hace que una clase obtenga las referencias a objetos que necesita para poder funcionar, a través de una entidad externa, como el contenedor de Spring.