The reason I don't use them is not because they are bad, but because IntelliJ is so much better.
I even use IntelliJ Ultimate for non Java code like React, even though Visual Studio Code seems to be de-facto standard for React developers and guides.
46 karma · joined May 6, 2023
The reason I don't use them is not because they are bad, but because IntelliJ is so much better.
I even use IntelliJ Ultimate for non Java code like React, even though Visual Studio Code seems to be de-facto standard for React developers and guides.
I can use my IDE to see the type if necessary.
> Everything that came after isn't really memorable nor helpful,
There are several improvements that are very helpful
One example is how multi line strings help me to read more clearly without the unnecessary string concatenations:
var sql = """
SELECT foo
FROM bar
WHERE last_updated > :lastUpdated
""";
Another example is how switch statements have improved code readability, at least from my personal subjective viewpoint. String dayName = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3, 4, 5 -> "Other day";
default -> "Weekend";
};At my previous job some were able to change that by consistently using "modern" features of Java. It inspired others to change and eventually we ended up with a good code base.
Be the one to start the change by implementing new features using good code. This will give others "permission" to do the same. Also try to give soft suggestions in code reviews or pair programming of simpler ways to do it (don't push too hard)
At my current job all of us were eager to try the latest features from the start, so we never had to convince new hires.
https://maven.apache.org/enforcer/enforcer-rules/versionRang...
https://maven.apache.org/extensions/maven-build-cache-extens...
> Incremental builds work on the modified part of the project graph part only
> Subtree support for multimodule projects builds part of the codebase in isolation
> Version normalization supports project version agnostic caches
> Project state restoration (partial) avoids repeating expensive tasks like code generation
If memory is an issue, you can set a limit and the JVM will probably still work fine
I use Spring Boot at my day job and write mostly web services. I don't spend time messing around with config files and annotations. When I create a service class, I annotate it with @Service, and that is mostly what I need.
Example:
@Service
public record ItemsService(ItemsRepository repo) {
public void doStuff(String country) {
var items = repo.findByCountry(country);
// do stuff with items
}
}
Later versions of Spring Boot has reduced a lot of the annotations necessary, like @Inject if you use constructors etc. There are of course other annotations and configurations, but 90% of what I do is similar to the example I gave above. Things may have changed since last you used it, but the amount of "magic" and annotations is often much less than what is posted in these types of discussions.I think a lot of people are noticing the changes Java has had in the previous years. The language has made a lot of improvements, and I feel that the mind set of the community has changed. The old enterprise way of factories and unnecessary abstractions have lost a lot of popularity, and is mostly still alive in legacy software/teams and universities who have not yet caught up.
Even Spring Boot is now a valid approach for getting sh*t done for startups. There are of course frameworks that are more light weight, or you can start from scratch and choose your own libraries to keep the size down. But SB is simply good enough for most use cases, and even supports native compilation now.
For now, I use Lombok's @Builder annotation. It makes it much easier to create and copy a record, where non-assigned attributes are set to default.
Example:
var bmw = Car.builder().make("BMW").build()
It also has a practical toBuilder() syntax that creates a copy of the original record, with some attributes changed var other = bmw.toBuilder().year(2024).build()It may not have the convenient "years" method directly, but you can add an arbitrary unit of time quite easily
Example with duration:
Duration.of(1, ChronoUnit.YEARS)
Example with datetime: today.plus(2, ChronoUnit.YEARS)
It even supports decades, centuries, eras and half days :-)For those curious about how it handles leap years:
var leapDay = LocalDate.of(2024, 2, 29)
leapDay.plus(1, ChronoUnit.YEARS);
// ==> 2025-02-28
var lastYear = LocalDate.of(2023, 3, 1);
lastYear.plus(1, ChronoUnit.YEARS);
// ==> 2024-03-01
var lastFeb = LocalDate.of(2023, 2, 28);
lastFeb.plus(1, ChronoUnit.YEARS);
// ==> 2024-02-28
var firstFeb = LocalDate.of(2024, 2, 1);
leapDay.with(TemporalAdjusters.lastDayOfMonth());
// ==> 2024-02-29Java has several 3rd party dependencies that are expected to just be there in projects where I have worked. Examples are Lombok, Apache Commons and SLF4J. These have become so widely used, that I have stopped thinking about them as external dependencies.
Guava used to be more popular too, but now that Java has Optional and Streams, I don't see it as often.
Logback even supports including the call chain in the output, so you could include the parent method, grand parent method etc. This probably uses reflection, so it could have a negative impact for applications that need a high performance.
I personally use the @Builder annotation on records with more than 3-4 fields. I find it much more readable than a long list of arguments to the constructor.
It also makes it easy to return a copy of the record where only a few fields have changed:
var r = book.toBuilder()
.lastUpdated(now)
.title("...")
.build()
I also use other annotations, but I could work without them if a future version of Java provides a builder-like pattern (or named arguments)According to others in this discussion they also made architecture changes (DB, Kafka etc.). Do we know if that improved the performance?
There is no objective way we can tell if Elixir had any performance impact. It could have been due to the rewrite, the architecture change or a combination of both.
If it's just about ignoring forced exception management, Lombok provides the @SneakyThrows annotation.
I would need something more before I add a new type of extension. Maybe if you could solve the null-check issue.
i.e. rewriting
var x = a.getFoo()?.getBar()
to var x = a.getFoo() != null ? a.getFoo().getBar() : null
In that case I may consider it for my personal projects, and then potentially recommend it at work once it becomes more widespread and has IDE support.I haven't yet tried it myself, but it looks promising:
https://spring.io/blog/2022/10/21/introducing-spring-modulit...
This meant upgrades were usually as simple as increasing the version, as the infrastructure team had already made sure that the other dependencies had been tested. Each team were free to ignore this and do whatever they wanted, but the benefits were too great to ignore for most teams.
At my current job we don't have this type of shared configuration, which makes micro services much harder to maintain.
One name for this is "Modulith" where you use modules that have a clear enforced boundary. You get the same composability as micro-services without the complexity.
Here's how Spring solves it: https://www.baeldung.com/spring-modulith
It's basically a library that ensures strict boundaries. Communication has to go through an interface (similar to service api) and you are not allowed to leak internal logic such as database entities to the outer layer
If you later decide to convert the module into a separate service, you simply move the module to a new service and write a small API layer that uses the same interface. No other code changes are necessary.
This enables you to start with a single service (modulith) and split into microservices later if you see the need for it without any major refactoring