Format All Your Java Projects With One Rule
A recent Twitter conversation reminded me of a project I'd been thinking of for a while.
Pick an opinionated formatter for your code, change no settings on it, and learn to not be bothered by it + get work done.
Life will be much easier when you work at a company that requires you to use a certain style and you'll waste much less time.
This pragmatic sentiment makes sense. Consistent formatting matters. In particular, it helps ensure meaningful diffs, making code review safer and easier.
Formatting in Java isn't standard, as it is in Go, or even common practice, as in TypeScript. But it should be. Josh Long of the Spring team pointed out that Phil Webb has written a Java formatter, which is used on Spring Boot. Wouldn't it be good if more projects used it?
Making Aspiration Reality
Discussions like this happen all the time among developers, and often don't produce practical results. It's one thing to have an aspiration about how we should work and another to make it reality.
Just as a good test suite makes specifications executable, Atomist can make delivery aspirations reality.
I decided to make an Atomist autofix to make it easy to apply Phil's spring-format
automatically to any Java project, by adding code like the following to an Atomist Software Delivery Machine:
const autofixGoal = new Autofix()
.with(springFormat(configuration));
sdm.withPushRules(
onAnyPush().setGoals(autofixGoal),
);
The key concept here is the push rule. Atomist's event-based approach reacts to pushes on any project, setting goals that determine behavior. When Atomist reacts to a push on any project, it sets the autofix goal, which in this case executes a single autofix wrapping spring-format
. If any formatting change is necessary, a commit is made to the same branch.
The springFormat
autofix registration function is included in Atomist's Spring Extension Pack. It only fires on Java projects, so the JVM is only started when necessary.
Why Autofix With Atomist?
You can invoke spring-format
as a Maven or Gradle task. However, invoking it using Atomist has several advantages:
- Formatting policy should span all repos. It's a cross-cutting concern. Applying formatting using Atomist, we don't need to modify the repos themselves to update Maven or Gradle build files. We can also the same approach to format other languages. (We use Atomist to run
tslint
to format our TypeScript projects.) - Autoformatting should be guaranteed, and not reliant on individual developer behavior. With Atomist, every push will result in the application of appropriate formatting, regardless of whether or not a developer builds before pushing.
- Autoformatting is not conceptually part of build. We want guaranteed formatting, but format errors shouldn't result in a build failure.
- We may want to apply different behaviors to different branches or pushes. Atomist makes this easy, whereas Maven or Gradle lack this concept.
Start Autoformatting Your Java Projects Today
You can start autoformatting your Java projects this way today. Get started on your laptop purely using open source via the Atomist CLI. Or enable Atomist on your team, and guarantee consistent formatting across all your projects, as well as visibility through Slack or MS Teams.
The Spring format SDM code is here. You'll need to build and install the Java wrapper and specify the location of the resulting executable JAR file (in index.ts
) to get it to work. You'll also need java
on the system where you're running your SDM.
How It Works
This is useful functionality in itself. However, Atomist is a powerful platform, so how it works is a useful hint toward countless other possibilities.
Implementing this capability on top of Atomist required two tasks, which took me about an hour in total:
- Wrap
spring-format
in an executable JAR file to make it easy to invoke. - Write an Atomist
AutofixRegistration
that spawns this command on the current project.
We can use this approach for other autofixes. We can use Atomist event handling and goals to drive any aspect of software delivery. Many features come out of the box with Atomist, but just about anything can be coded for further reuse, on top of Atomist's API for software. Atomist has been designed with testability in mind, so you can follow good engineering practice and engineer, rather than hack, your software delivery.
How could you enhance your software delivery with Atomist?