Repository navigation
feat: let controllers use the framework-free Nova libraries - #5
Merged
Merged
Conversation
Run the rules of LayeredArchitectureTest through the ArchUnit engine, with the EngineTestKit of JUnit, over three small sample services kept under fixtures: one that follows the layers, one whose controller reaches outside them and one that only has a controller and a service. The samples pin what the rules do today. The entity, service and repository layers can already use the framework-free Nova libraries, a controller cannot reach other packages of the service or the Nova starters, and a layer with no classes fails instead of passing. Gradle does not run the samples as tests, because some break the rules on purpose. Only LayeredArchitectureRulesTest runs them.
The controller rule only admitted the layers, java, jakarta, Spring, Quarkus and the test libraries, so a controller could not throw ApplicationError.invalidInput(...) from the layered errors of ADR-031: the rule flagged the call. Allow pe.edu.nova.java.libs.., the framework-free Nova libraries, in that rule. It is narrower than pe.edu.nova.. on purpose. A service lives under pe.edu.nova too, so allowing the whole prefix would stop the rule from catching a controller that reaches the service's own packages outside the layers. The Nova starters stay out, because they wire the framework. The controller was the only layer with an allow-list. The rules of the entity, service, repository and DTO layers only forbid other layers, so they already accepted these libraries and the domain could already throw DomainError. The sample services now prove it.
The README still showed Maven, version 1.0.0 and mvn test, and it listed a rule the library does not have. The library forbids service fields that are not final, which rules out field injection, but it never looks for @Autowired. Show the Gradle install from GitHub Packages and the toolchain plugin that brings the library, run the tests with Gradle, and list each layer with the rules that apply to it. Explain that the controller is the only layer with an allow-list and why it admits pe.edu.nova.java.libs.. and not pe.edu.nova.., and that a layer with no classes fails on purpose, with the ArchUnit switch for a service that really lacks one.
The install snippet of the README names the version of the library, and it went stale after the first release: it still showed 1.0.0 when the library was at 1.1.2. Mark the snippet for release-please, so that each release pull request updates it together with the changelog.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Qué cambia
Un controlador no podía lanzar
ApplicationError.invalidInput(...), de los errores por capas de ADR-031: la reglacontrollers_depend_only_on_allowed_layerssolo admitía las capas del servicio,java,jakarta, Spring, Quarkus y las librerías de prueba, y marcaba la llamada.pe.edu.nova.java.libs.., las librerías de Nova sin framework. Es más estrecho quepe.edu.nova..a propósito: un servicio también vive bajope.edu.nova, y admitir el prefijo entero dejaría sin efecto la regla para los paquetes propios del servicio. Los starters (pe.edu.nova.java.starters..) siguen fuera, porque cablean el framework.entity,service,repositoryydtosolo prohíben capas concretas, así que ya admitían esas librerías: el dominio ya podía lanzarDomainError, y un servicio puede declararthrowsde un error de Nova sin queservices_should_not_throw_generic_exceptionlo marque. Las pruebas lo demuestran.failed to check any classes, y no se relaja. Es la misma comprobación que detecta unbasePackage()que dejó de coincidir con el código tras un renombrado, o una capa llamadacontrollersen vez decontroller, casos que de otro modo pasarían sin revisar ninguna clase. Relajarla quitaría esa red a todos los servicios para ahorrarle a unos pocos una clase de relleno. Un servicio que de verdad no tiene la capa puede apagar la comprobación conarchRule.failOnEmptyShould=falseenarchunit.properties, que es el interruptor de ArchUnit; el README lo explica../gradlew testy la versión actual, y describe las reglas tal como son. La lista anterior prometía una regla contra@Autowiredque la librería no tiene: lo que existe es que los campos de instancia de un servicio seanfinal.extra-filesy marcas de bloque), para que no vuelva a quedarse en 1.0.0.LayeredArchitectureRulesTestcorre las reglas con el motor de ArchUnit (EngineTestKit) sobre tres servicios de ejemplo ensrc/test/java/.../fixtures: uno que cumple todo, uno cuyo controlador se sale de las capas y uno sin repositorio, entidad ni DTO. Gradle no los corre como pruebas, porque dos incumplen reglas a propósito.Es un
feat:y no un cambio incompatible: la lista de permitidos solo crece, así que nada de lo que pasaba deja de pasar. Con él sale la 1.2.0.Cómo se verificó
aServiceThatFollowsTheLayersPassesEveryRuleyaControllerMayUseTheNovaLibrariesButNotTheRestOfNova) con la violacióncalls method <...FixtureError.of(java.lang.String)> in (ItemController.java:30), la misma que vería el template conApplicationError. Con el cambio pasan las seis pruebas del repositorio../gradlew build javadoc: verde, con los mismos avisos de Checkstyle (9) y de Javadoc (1) que teníamain; ninguno es nuevo.exclude("**/fixtures/**")el build falla con 10 pruebas rotas, así que la exclusión hace falta.archRule.failOnEmptyShould=falsedel README se probó: con él, el servicio sin repositorio, entidad ni DTO deja de fallar.