Imagine we’re building yet another e-commerce platform. One of its crucial business processes is, of course, processing an order. After a successful payment, the Orders module (domain) has to call Warehouse asynchronously to prepare purchased goods. Yet, they may not be there. Usually, it’s not a big deal, since we can get them from our suppliers. But what if any of the items are not available anymore? The order has been already placed!
Hi! 👋 I'm Mike, a.k.a @mikemybytes, building distributed systems for fun and living. While I specialize in JVM technologies (mainly Java, Kotlin, Spring), my professional interests go far beyond that. Let me show you what I found interesting!
I launched my own brand “Mike my bytes” in November 2020 as an experiment. Rebooting my existing blog (dated back to 2015!) along with becoming active on Twitter really paid off. Apart from joy, it also brought thousands of people interacting with my content every month. Today, it’s high time to make some adjustments. Refreshed mikemybytes.com design is just the beginning. Content is king The Twitter I discovered in 2020 is no longer there.
The calendar doesn’t lie. A decade of my professional career in software development has just passed. 10 years of experience always felt like a magical and very distant boundary. Am I a better engineer now? Am I a different person? Absolutely! Yet, it didn’t happen overnight. Reviewing these changes is a fascinating exercise. Sometimes I struggle to remember what I had for lunch the day before… But 10 years?! That’s really a lot of time!
Quite some time ago, JUnit’s @CsvAnnotation caught my attention. It turned out so interesting, that I dedicated it a separate blog post and a significant part of a conference talk. It also inspired me to create a new way of writing parameterized tests with JUnit 5. The JUnit 5 FormattedSource library allows defining test case arguments in a human-readable way, following a user-defined format. As a result, it can be used to improve tests readability.
Keeping our domain (business) logic together is usually a really good idea. It not only makes it easier to reason about the most important part of our code but also increases its cohesion. Yet, decoupling the domain code from all the rest (orchestration, persistence, etc.) can be tricky. In this post, I’d like to share a simple pattern that helps me with that. The amazing Unit Testing Principles, Practices, and Patterns book calls it the CanExecute/Execute pattern.
Database migrations are a standard way of dealing with database schema changes, especially in the relational world. No matter which solution we choose (e.g. Flyway or Liquibase in the Java ecosystem), the number of migrations usually grows together with the project itself. An unfortunate side effect is that the test execution time grows as well. An effective way of speeding up our test execution in such cases is to squash (compact) all the existing migrations into a single file.
The very last days of the old year are probably a good time to think about the next one. Although we already learned how inaccurate any predictions can be, it still feels like an interesting exercise to me. Let’s try to predict the tech future just a little bit… 🔮 I have to warn you, that everything you’ll read here is just a reflection of my own gut feeling. It’s a bunch of guesses based on news, observations, and discussions with my colleagues (👋).
The JVM has spoiled us with its cleverness. It makes so many decisions behind the scenes, that lots of us gave up on looking at what’s inside. Memory-related discussions are probably more likely to appear at a conference or during a job interview than at “real” work. Of course, depending on what you work on. Java apps are often run in containers these days. Built-in container awareness makes the JVM respect various container-specific limits (e.
We create APIs all the time - and I don’t have only libraries and frameworks in mind. Every piece of code that’s intended to be called by another piece of code is an API, in some sense. It’s our job to define an interface, which will be used to achieve whatever is expected. While discussing various API designs, we often focus on “how it’s gonna look” first. Does it allow fluent calls?