Udemy courses: Git and Docker
I want to recommend a couple of courses on Udemy that I took over the last couple of months. Both helped me gain confidence and knowledge in tools that I use every day: Git and Docker.
I want to recommend a couple of courses on Udemy that I took over the last couple of months. Both helped me gain confidence and knowledge in tools that I use every day: Git and Docker.
The state of racing simulators on Linux today is not as bad as I expected. Last time I tried them about ten years ago, it was still a plain WINE without DirectX to Vulkan translation layers, Valve hadn't released Proton yet, and other improvements by numerous contributors from the open-source community weren't available. Games like rFactor simply didn't work at all.
Recently, I decided to give it another shot. Even though Linux still might not be a viable option for all simracers, I found it doable!
Music streaming services provide us access to huge libraries, which is great! Algorithms study what we like and offer useful recommendations or let us discover something entirely new.
However, we can only access what has been officially released. Some "live in ${city.name}" DVD release that you enjoy might not be available on a streaming service. Occasionally, artists and labels end up in legal battles, and the content that was released in the '80s and '90s suddenly can't be distributed anymore. Over time, I started to notice that a playlist with my favorite music lost at least a third of the tracks I liked to listen to! That makes other sources of obtaining music relevant again.
YouTube is one of them. The quality is not fantastic due to irreversible compression, but there are so many live recordings, obscure releases, and covers that I find it worth it. As I store music on my home server, I needed a solution that wouldn't pollute it with hundreds and hundreds of packages. Yes, I'm looking at you, ffmpeg! Probably most tools that can download and process videos from YouTube depend on ffmpeg.
So if you too want to utilize yt-dlp in an isolated environment, I can offer dockerization!
I recently started playing racing simulators and joined a league that mimics the real Formula 1 championship. These cars are really challenging and unpredictable, especially with my experience. Another key aspect to consider is tire strategy. There are several compounds that offer different levels of traction, wear, and overall speed. A good strategy can help you gain positions, while a bad one can undermine solid driving.
I decided to create a tool that would help me to find out the most common strategies.
In March, I wanted to add code generation to a project I was working on. I had a publicly available OpenAPI contract of considerable size, and using it I needed to integrate with a third-party service. I decided to stick with the generator I was already familiar with. Unfortunately, it was incompatible with the specification at my hands!
A couple of years ago, I created a simple website designed to assist QA engineers in practicing some of the most commonly used test design techniques: Equivalence Partitioning and Boundary Value Analysis. The site provides a specification of a feature along with multiple implementations; one is correct, and the others are not. The objective was to show that the correct test input can effectively detect all errors. However, my initial intent was not clear to the end users because I did not provide correct answers or any explanations! Let me do that in this post.
To no one's surprise, posting regularly to a blog when you have a job and when you don't are two different things. Nevertheless, I'm trying to reincorporate writing into my daily routine. If you're reading this, then I have succeeded! In the previous entry, I briefly described that I settled on a Go backend and a React web app for this site, explaining how code generation based on the OpenAPI specification simplifies the synchronization of any changes between the two.
Once the code is written and tested, it's time to deploy it to my VPS. I used a couple of tools for that, with the actual commands stored in Makefiles. For the Go service, it looked like this:
While I believe there's nothing wrong with this approach given the nature of the project, I wanted to switch to GitHub Actions and Packages. That would eradicate the need to define deployment properties on every machine where I code, let alone maintaining them up to date if. Moreover, even though the exact tools differ from company to company, this approach would be much closer to what a real business would do with their product. In other words, besides the personal interest, it is relevant to my job!
The transition was rather simple. I was already building Docker images, so all I had to do was to move this part to GitHub and push images to their registry. Here, I want to document what I did and think about what can be done next.
When I created this blog last summer, I had several goals in mind: to acquire new skills, learn about fresh technologies, and have fun in the process. Its simplicity allowed me to rewrite the project multiple times using different programming languages and libraries: Rust with Axios, Java with Next.js, Java with Thymeleaf, and finally, Golang with React. While the first two options reduce the amount of code by handling both the service logic and the HTML rendering, they also take on too much responsibility in this way. Not that this is wrong by definition, but I prefer to separate these concerns.
However, this approach increases the workload. I had to build models on both sides, consider not only the controllers but also the client implementation, where changes on either side can break the integration. In this post, I want to explore a way to eliminate this overhead and explain how to generate code for a Go server and React client based on an OpenAPI specification. The idea is not limited to this stack, it can be easily applied elsewhere with suitable tools.
The full demo project is available on GitHub.
It might be hard to find a fully independent service today. Even in the case of a monolithic architecture, where all components of the software are tightly coupled within a single codebase, there's still a need to integrate with the outer world. For instance, internal banking logic can be self-sufficient. But functionalities like police security checks and interbank money transfers can't be done in isolation.
During the development phase of a product or feature, programmers may write stubs and mocks to substitute missing dependencies. As QA engineers, however, we want to test the code that will go into production, touching the same statements and execution paths as the real data. Furthermore, we need to validate the system's behavior with various inputs, hence it should be possible to change how the external service responds to the program under test.
WireMock is a tool that enables us to do exactly this. It launches an HTTP server that can be configured to respond to specific requests in a desired manner. Let's say there is a system that should verify the recipient's IBAN against a database. If the response is positive, the transfer proceeds; if negative, the transfer must be blocked.
Was 2023 the year of the personal website? And what about 2024?
I'm not sure about 2024, but on the last day of 2023, I'd like to respond to the first question posed by Matthias Ott. His Own Your Web newsletter was one of my motivations to keep working on this blog. Seeing others and their website designs reminds me of the days before social media, which had more room for personal expression.
I don’t mean everything is bad today. However, I like being able to personalize my blog with snowflakes, a Christmas tree at the bottom of the page, and altering the mood of my visitors. We can't do that on Facebook or Twitter, which I find odd. Many would enjoy and even pay for such personalization. The only example I can think of is Steam, where gamers can purchase various avatar borders, profile backgrounds, and other visual elements.
This year wasn't just about starting my website.
Whether we're concerned about privacy or not, we utilize cryptography every day. Thanks to HTTPS we can securely log in to online banks, use government services, share our location, chat with friends, and participate in other activities where leaks could result in financial loss, damage to our reputation, or even mental or physical harm.
Your communications with this website are also encrypted! That's not because you're transmitting or receiving confidential data while being here, but rather your browser wouldn't allow you to open this page otherwise. In the past, something like credit card details could be transferred in plain text, making it an easy target for hackers. Today, the risk is significantly reduced as browsers enforce site owners like me to secure the connection.
Long before the advent of the World Wide Web, the secrecy and confidentiality aspects of his role led Julius Caesar to contemplate how to safeguard his orders. A messenger carrying important information could be intercepted, and then it would be disclosed to the enemy. To counter this threat, he began encrypting his correspondence using a simple algorithm that was eventually named after him: a Caesar cipher.
Quicksort is a curious algorithm. Many people learn it soon after the bubble sort because it can be easy to understand and code. Despite this, quicksort is widely used. For instance, Java comes with a dual-pivot implementation to sort arrays. Here, I want to dissect it step by step to cement my knowledge.
I've watched several documentaries over the past couple of months and wanted to jot down my impressions. Here's the list:
While discussions on the topic of AI have been ongoing for years, they weren't as prominent outside the circle of enthusiasts. That changed one year ago when OpenAI introduced ChatGPT in November 2022. I want to recommend a book that is relevant to the subject.
A couple of days ago, I took on an interesting task on Exercism. You can find the full description here. The goal is to create a function that takes a number between 1 and 31 and converts it to a list of actions. The sequence is defined by the five rightmost digits of the number when converted to binary. If you're unfamiliar with the binary system, I recommend reading this explanation first.
In this post, I'll discuss how I gradually improved my initial solution and share some interesting findings about the performance of different approaches.
It can be hard to decide how to spend our free time. We may have some ideas about activities to engage in, but our brains prefer not to invest effort in something deemed unrewarding. Alas, among such things we can find work on quite useful tasks. Usually these activities don't yield immediate tangible output, and it takes months and years to achieve our goals. Say, learning a new language or obtaining any other comprehensive skill. Consequently, our motivation tends to fade off over time. Faced with a choice between difficult or boring tasks and something easy, we often succumb to the temptation, and turn to social media or TV shows.
This summary is based on two books I've recently read: "Thinking, Fast and Slow" by Daniel Kahneman and "Willpower and self-control: How genes and the brain hinder our struggle against temptations" by Irina Yakutenko. The former explores how our brains trick us from a psychologist's perspective, the latter is focused on biochemical processes.
To mitigate this problem, I started creating to-do lists. Having a clear path to follow makes it much easier to stay on the course. No doubt, there are various causes of procrastination, and what works for one individual may not work for another. But to-do lists can be a valuable ally for many people.
I'd like to share my experience on how I've managed to organize my time better.
The modern internet is highly centralized. While independent websites still exist, we rarely go beyond the firsrt few search results and get news from social media. These platforms are the internet for many people because they not only help old friends stay in touch, but also act as content aggregators and providers, enabling algorithms to control what we see.
Recent changes on now X and Reddit pushed me to take a look at decentralized solutions. I joined Lemmy and Mastodon. Both are significantly smaller than their commercial counterparts and don't have as much content, which makes mindless scrolling for hours impossible. This change alone freed up a lot of time and helped me realize how addictive these services are.
On the other hand, the absence of a 'smart feed' puts responsibility of finding new content on the user. As I discovered, people continue to post on personal blogs, and some websites still generate RSS feeds. I believe it's important to have full control over our feeds. The cheap pleasure that comes with scrolling social media harms our lives and distracts us from our long-term goals. Instead of doing something useful, we spend endless hours arguing with strangers and watching memes.
Algorithms' job is to keep us engaged, they don't care whether we get useful information or engage in benificial activities in the process. In fact, platforms like Facebook profit off hate speech and misinformation. See also: How Facebook Became a Tool for Genocide.
To be part of the solution and not the problem, I decided to launch this blog a couple of months ago. Now, I want to introduce an RSS feed that should make following me easier. Let's see how I implemented it with ROME, Spring Boot, Docker and Nginx!
While learning a new programming language, it can be easy to miss a little detail you'd never overlook in a familiar environment. The Rust's compiler is rather good at telling the user what they're doing wrong, but for a beginner it can be difficult to understand more advanced errors. I got one while going through the Diesel ORM Getting Started guide. Let's explore it!
I've watched several documentaries over the past couple of months and wanted to jot down my impressions. Here's the list:
Testcontainers is a great tool for managing external services required for the proper functioning of an entire application or its components during testing. It automatically deploys these services before a test begins and then stops them once testing is over. This simplifies the process of running tests across multiple environments.
While working on integration tests for the service behind this blog, I stumbled upon an issue. It lies on the border between Testcontainers and Spring. When executing a single test or an entire class, everything worked as expected. But when executing multiple test classes (e.g. with ./gradlew test), the database became inaccessible.
In this post I'm exploring one of the possible solutions to this issue.