Clear boundaries in code are important... and hard. Especially in legacy code. ArchUnit allows you to capture the structure your team agreed on in tests.
Starting to work with legacy code
Recently we picked up a project and attempted to move it forwards. We wanted to introduce new concepts and structures in a new UI. Also, we wanted to keep the old UI until the new one was ready for production.
The new UI would start as a read-only version. It should not depend on existing code, allowing us to learn the codebase over time. Only in the next phase would we change the existing business logic.
Typically, you would document decisions like this, for instance in an ADR. This is a great way to capture the reasons behind the decision. But expressing the decision in tests gives additional benefits.
The benefit of tests
The tests remind everyone on the team about the decision. If my code for the new UI depends on legacy code, the tests break. This obviously helps new team members learn about decisions that have been made.
It is also helpful for those who have been on the team from the beginning. If in the heat of the moment a dependency sneaks in, then there is a failing test. Gently reminding you of the team agreement. Also, when you have bigger changes, maybe a refactoring, it's hard to keep track of all the changes. ArchUnit tests lift some mental burden off from you because they check that you agreed to avoid dependencies to legacy code.
Failing tests as a chance
When a test fails, it gives you the chance to rethink the approach you just went with. Either you come up with a better idea, or you start a fruitful discussion with your teammates. Of course, the outcome of such a discussion can be to change or relax the rules a bit. But then it is a deliberate decision. Nothing sneaked in without you being aware of it. Changing the ArchUnit tests is something that can be easily seen in a PR review. Which again is a chance for a fruitful discussion with your team.
The power of arch unit tests
ArchUnit tests run pretty fast. They won't slow your test suite down, giving you an additional safety net on every test run. This allows you to avoid dead ends when implementing or refactoring early; way earlier than a fellow developer can in a code review.
So in short ArchUnit tests will help your team to
learn about decisions
stick to those decisions
trigger discussions about corner cases
And all of that with every test run. Which means early and reliable feedback.
Show, don’t tell
I hope by now that you are excited about ArchUnit. So what does this look like in code?
ArchUnit tests are regular JUnit tests. Just include ArchUnit as a dependency and you are ready to go.