Aprendiendo a programar en java 1
Durante el curso que estoy finalizando he aprendido una gran cantidad de buenas prácticas orientadas a escribir código limpio, mantenible y escalable en Java. A continuación se recogen algunas de las más importantes.
Uso de final en Java
La palabra clave final se utiliza para declarar constantes o variables que no deben ser modificadas una vez inicializadas.
Aunque es común usarla a nivel de clase, también es muy recomendable utilizarla dentro de funciones para garantizar la inmutabilidad de las variables.
Beneficios
- Previene errores y modificaciones accidentales
- Mejora la legibilidad del código
- Muy utilizada en inyección de dependencias
- Práctica común en Spring
Ejemplo
public PersonasImplicadasService(
final PersonasImplicadasRepository repo1, // No se puede reasignar
PersonasImplicadasRepository repo2) { // Se podría reasignar
repo1 = null; // Error por ser final
repo2 = null; // Compila, pero es mala práctica
this.personasImplicadasRepository = repo1;
}
Uso de DTO y Mapeo en Servicios
El uso de DTO (Data Transfer Object) junto con el mapeo a entidades es una práctica clave en aplicaciones Spring.
Ejemplo
public Long create(final PersonasImplicadasDTO personasImplicadasDTO) {
final PersonasImplicadas personasImplicadas = new PersonasImplicadas();
// Mapeo de DTO a entidad
mapToEntity(personasImplicadasDTO, personasImplicadas);
return personasImplicadasRepository.save(personasImplicadas).getId();
}
Beneficios
- Mayor control sobre los datos
- Separación clara de responsabilidades
- Mejora en seguridad
- Independencia entre capas
Separación entre DTO y Entidades
Separar DTOs y entidades permite mantener una arquitectura limpia y desacoplada.
1. Separación de responsabilidades
- Entidad: representa el modelo persistente (base de datos)
- DTO: transporta datos entre capas (API ↔ Servicio)
@Entity
@Table(name = "personas_implicadas")
public class PersonasImplicadas {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "grado_implicacion_id")
private GradoImplicacion gradoImplicacion;
@Column(name = "fecha_alta")
private LocalDateTime fechaAlta;
}
public class PersonasImplicadasDTO {
private Long id;
private Long gradoImplicacionId;
private String nombre;
}
2. Control de datos expuestos
Permite decidir qué datos entran y cuáles salen del sistema.
Ejemplo (Salida)
public PersonasImplicadasDTO findById(Long id) {
PersonasImplicadas entidad = repository.findById(id).orElseThrow();
PersonasImplicadasDTO dto = new PersonasImplicadasDTO();
dto.setId(entidad.getId());
dto.setNombre(entidad.getNombre());
return dto;
}
3. Independencia de evolución
DTOs y entidades pueden evolucionar de forma independiente:
- Añadir campos al DTO sin afectar a la base de datos
- Modificar la entidad sin romper la API
4. Doble validación
Se validan los datos en dos niveles:
DTO (Entrada)
public class PersonasImplicadasDTO {
@NotNull(message = "El nombre es obligatorio")
@Size(max = 100)
private String nombre;
@NotNull
private Long gradoImplicacionId;
}
Entidad (Persistencia)
@Entity
public class PersonasImplicadas {
@Column(nullable = false, length = 100)
private String nombre;
@ManyToOne(optional = false)
private GradoImplicacion gradoImplicacion;
}
5. Rendimiento
Permite optimizar consultas evitando cargas innecesarias (lazy loading).
@Entity
public class PersonasImplicadas {
@OneToMany(fetch = FetchType.LAZY)
private List<Documento> documentos;
}
public class PersonasImplicadasDTO {
private Long id;
private String nombre;
private Integer totalDocumentos;
}
Conclusión
Aplicar estas buenas prácticas permite:
- Código más limpio y mantenible
- Mayor seguridad en el manejo de datos
- Mejor escalabilidad del sistema
- Separación clara entre capas
Son fundamentales en cualquier aplicación profesional desarrollada con Java y Spring.