Software developers are oddly proud of our tools. I don't imagine that plumbers spend a lot of time comparing wrenches, or carpenters chisels, but the internet is aflame with software developers trying to find the "one true setup".
While we don't think there's a single silver bullet (fear people who do), we do have our particular favourites that we've written about below.
For back-end work, we're utterly devoted to Kotlin - the JetBrains language distilled from their favourite bits of the variety of languages they support.
Having spent our careers working in Java or Scala, Kotlin gives us a modern, powerful language to work in without losing the experience we've gained as OO programmers working on the JVM. Early in the life of the company, we decided that Scala was an unfair sell for our clients. If they build out permanent teams in the future, we want them to be able to tap into an abundant talent source: Scala's talent market is anything but!
While Java experience is abundant, the language itself is unproductive for a small company. The innovation in recent years is promising, but I don't think we're alone in saying that (while the JVM is a marvel) the Java language is too restrictive when compared with modern competitors.
This is where Kotlin shines. It's easy to train a good Java developer to write idiomatic Kotlin and it's the same eco-system. Tapping into existing knowledge about - for instance - how JDBC works makes the initial productivity dip short-lived.
Our favourite Kotlin features include:
- great compile times when compared to other JVM languages (legends say Kotlin was written while waiting on a Scala project to compile);
- second-to-none IDE integration - this is obvious given its creator, but the integration between Kotlin and IntelliJ leaves me wondering if I'm really the one driving at times;
- OO in action! While object-oriented programming is out of fashion in some circles right now in favour of functional programming, we love the paradigm. Kotlin strikes a great balance between OO for the larger structure of a system with FP in the small for data manipulation.
To top it all off, Kotlin interoperability with Java-land is close to perfect. We can leverage the existing ecosystem without missing a beat - which brings us onto our next tech choice.
There's a lot to love about Spring Boot and a lot to dislike, but we're confident that the good outweighs the bad by a considerable margin.
Sure it's slow to start-up and uses more memory than more recent competitors like quarkus or micronaut. And yes, debugging any configuration issues ends up in a Lovecraftian nightmare of AbstractAbstractionDelegateManagerFactory classes. But the advantages are there in spades.
Spring Security is incredible, a patchwork quilt of decades of security learnings coming together into a neat DSL that abstracts away the many horrors of InfoSec. We've used it for OAuth2, traditional session-based authentication and even for passing secret keys in a custom header. To our mind, it's the killer feature that makes leaving Spring a tough sell.
And that's before we consider the fantastic ecosystem. Spring has spent a long time as the apex predator in Java web applications and it shows. There's a whole host of auto-magically wired in various starter libaries for Spring Boot that can handle almost any integration that one might require. What's more, many of these integrations have been around for years, so the maturity and stability of these integrations is far beyond what hand-rolled code would accomplish in a fixed time-frame.
The recent innovations are nothing to sniff at either. We're smitten with spring-data-jdbc as striking the right balance between a speedy ORM setup without incomprehensible magic behind the scenes. It also lets us drop into SQL when we need to get serious!
We love building Spring Boot monoliths. We're convinced that a Spring Boot back-end coupled with Kotlin is a top-class back-end experience. That's before we even talk about how we integrate it with the front-end.
Server-rendered HTML with Hotwire permalink
After a number of years building SPA's, we saw the light in 2019 and started thinking about what modern web development should look like. We found the JAMStack pattern - while great for large companies with large teams - to be slow and expensive for small companies/teams.
To that end, we started building out classic Spring MVC server-side rendered apps using webjars for JS/CSS libraries. This, dear reader, was clunky. Node.js has won with respect to the developer experience for front-end and we knew that we were giving something up by leaving it.
So we started trying to figure out how to hook it into Spring to get the best of both worlds.
This resulted in a starter template where we use laravel mix in a gradle task to build our front-end assets before hooking them into our server-side pebble templates.
This works amazingly well.
Coupled with the ridiculously productive tech that Basecamp has been releasing in recent years in the form of hotwire, we're building features with a higher degree of polish, better performance, and built-in accessibility in half the time.
It's a joy to work with. You can check out what we've open-sourced so far under koil.
While the pieces above are the primary building blocks that we use, they're by no means alone. We love postgresql, anything from JetBrains, Heroku, Kubernetes, semaphoreci, cypress and many other tools.
But Kotlin, Spring Boot, and server-side rendered HTML are fundamental to the way we work. We can change many other things in our tech stack, but changing any of these would be a fundamental shift. At that point, we might as well shop around and see what's going on in Ruby on Rails.