Post-Compile Checks
As soon as we use the public modifier on a class, the compiler will let any other class use it, even if the direction of the dependency points in the wrong direction according to our architecture. Since the compiler won't help us out in these cases, we have to find other means to check that the dependency rule isn't violated.
One way is to introduce post-compile checks – that is, checks that are conducted at runtime when the code has already been compiled. Such runtime checks are best run during automated tests within a continuous integration build.
A tool that supports this kind of check for Java is ArchUnit (https://github.com/TNG/ArchUnit). Among other things, ArchUnit provides an API to check whether dependencies point in the expected direction. If it finds a violation, it will throw an exception. It's best run from within a test based on a unit testing framework such as JUnit, making the test fail in the event of a dependency violation.
With ArchUnit...