Java de los fundamentos al dominio — Lección 10
Cree aplicaciones mantenibles con capas y pruebas
Los artículos escritos en este blog fueron creados con el objetivo de enseñar. Además, la información del artículo puede ser incorrecta, así que tenga cuidado.
A medida que un programa crece, la extensión de los cambios se vuelve más importante que el número de clases. Concluyamos nuestra serie de Java dividiendo las reglas, el almacenamiento y los límites de la pantalla y haciendo que el comportamiento sea comprobable.
Jerarquía de responsabilidad
public final class OrderService {
private final ItemRepository repository;
public OrderService(ItemRepository repository) {
this.repository = repository;
}
public OrderResult buy(int itemId, int gold) {
Item item = repository.find(itemId)
.orElseThrow(() -> new ItemNotFoundException(itemId));
if (gold < item.getPrice()) {
return OrderResult.notEnoughGold();
}
return OrderResult.success(item, gold - item.getPrice());
}
}
El servicio es responsable de las reglas de compra y no conoce directamente la base de datos ni los detalles de implementación HTTP. El controlador o la pantalla pasa información al servicio y presenta el resultado.
Dejando las dependencias afuera
public interface ItemRepository {
Optional<Item> find(int id);
}
ItemRepository repository = new FileItemRepository(path);
OrderService service = new OrderService(repository);
Si el almacenamiento concreto se selecciona fuera del constructor, las pruebas pueden reemplazarlo con una implementación de memoria. Las interfaces no son adornos para todas las clases, sino que se colocan en la frontera donde cambian las tecnologías externas.
Operación de prueba
@Test
void purchaseKeepsRemainingGold() {
ItemRepository repository = new MemoryItemRepository(
new Item(10, "Potion", 30)
);
OrderService service = new OrderService(repository);
OrderResult result = service.buy(10, 100);
assertEquals(70, result.getRemainingGold());
}
La prueba verifica las reglas visibles externamente en lugar del orden de llamada a los métodos internos. Incluso si limpia la implementación, puede ver si el mismo contrato se cumple para la misma entrada.
herramientas del proyecto
Gradle o Maven compilan, prueban, controlan las versiones de la biblioteca y empaquetan en comandos repetibles. Coloque los archivos de compilación y las pruebas juntos en el repositorio para que el proyecto no se ejecute únicamente en el entorno de desarrollo.
Una buena estructura Java no es aquella que tiene muchas jerarquías. Es una estructura en la que las reglas para cambiar de estado, recursos externos y la vida útil de tareas concurrentes son claras y pueden verificarse en pequeñas unidades.