<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Code on Pauls Blog</title><link>https://prule.github.io/pauls-blog/categories/code/</link><description>Recent content in Code on Pauls Blog</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 03 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://prule.github.io/pauls-blog/categories/code/index.xml" rel="self" type="application/rss+xml"/><item><title>Sample data</title><link>https://prule.github.io/pauls-blog/post/coding/2026/sample-data/</link><pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/sample-data/</guid><description>&lt;h2 id="the-strategic-case-for-programmable-sample-data"&gt;The Strategic Case for Programmable Sample Data&lt;/h2&gt;
&lt;h3 id="i-the-core-thesis"&gt;I. The Core Thesis&lt;/h3&gt;
&lt;p&gt;Manual database entry is a bottleneck that introduces inconsistency. The most effective way to ensure environmental parity and development velocity is to treat &lt;strong&gt;sample data as code&lt;/strong&gt;. By leveraging business services to seed the database with deterministic, UUID-based records, teams create a stable foundation for testing, UI development, and collaborative debugging.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="ii-supporting-arguments"&gt;II. Supporting Arguments&lt;/h3&gt;
&lt;h4 id="1-enforcement-of-business-logic-via-service-seeding"&gt;1. Enforcement of Business Logic via Service Seeding&lt;/h4&gt;
&lt;p&gt;A common mistake is seeding a database via direct SQL scripts. This bypasses the application’s validation rules and side effects.&lt;/p&gt;</description></item><item><title>Completing your GitHub Profile</title><link>https://prule.github.io/pauls-blog/post/coding/2026/github-profile/</link><pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/github-profile/</guid><description>&lt;h1 id="completing-your-github-profile"&gt;Completing your GitHub Profile&lt;/h1&gt;
&lt;p&gt;While I&amp;rsquo;m looking for a job I thought I&amp;rsquo;d find out how I could improve my Github profile.
This was the advice I found&amp;hellip;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-fill-in-your-profile--properly"&gt;1. Fill in your profile — properly&lt;/h2&gt;
&lt;p&gt;Most developers leave half the sidebar blank. Don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bio:&lt;/strong&gt; Don&amp;rsquo;t just write your job title. &amp;ldquo;Senior Software Developer&amp;rdquo; tells nobody anything. &amp;ldquo;Senior Software Developer — Kotlin, Spring Boot, clean architecture&amp;rdquo; tells a recruiter immediately whether to keep reading.&lt;/p&gt;</description></item><item><title>Stop Serving PNG: Switch to WebP</title><link>https://prule.github.io/pauls-blog/post/coding/2026/webp/</link><pubDate>Thu, 30 Apr 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/webp/</guid><description>&lt;h1 id="stop-serving-png-switch-to-webp-and-cut-your-image-sizes-by-80"&gt;Stop Serving PNG: Switch to WebP and Cut Your Image Sizes by 80%&lt;/h1&gt;
&lt;p&gt;WebP is the modern image format your website should already be using. Google&amp;rsquo;s &lt;code&gt;cwebp&lt;/code&gt; tool converts your existing PNG and JPEG files to WebP in seconds — and the results speak for themselves: a 1,434 × 1,522 PNG at 371 KB becomes a 74 KB WebP file. That&amp;rsquo;s an &lt;strong&gt;80% reduction&lt;/strong&gt; with no visible quality loss.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="the-bottom-line"&gt;The Bottom Line&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use WebP for all web images.&lt;/strong&gt; Install &lt;code&gt;cwebp&lt;/code&gt;, run one command per image, and dramatically reduce page load times without sacrificing quality.&lt;/p&gt;</description></item><item><title>Eliminate PR Noise with ktfmt</title><link>https://prule.github.io/pauls-blog/post/coding/2026/ktfmt/</link><pubDate>Tue, 21 Apr 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/ktfmt/</guid><description>&lt;p&gt;Few things are as frustrating during a code review as seeing a 50-line diff, only to realize that 45 of those lines are just re-ordered imports or adjusted indentation. This is &amp;ldquo;PR noise&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;In the Kotlin world, &lt;strong&gt;ktfmt&lt;/strong&gt; is one of the best tools to solve this. Developed by Meta, it&amp;rsquo;s a deterministic formatter that ensures every developer on your team produces the exact same output, regardless of their individual IDE settings.&lt;/p&gt;</description></item><item><title>AI-Assisted Engineering: From Implementation to Specification</title><link>https://prule.github.io/pauls-blog/post/coding/2026/ai-coding/</link><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/ai-coding/</guid><description>&lt;p&gt;The more I use AI to assist with coding, the more I realize that &lt;strong&gt;context is the primary currency of effective assistance.&lt;/strong&gt; The quality of the output is directly proportional to the quality of information available to the assistant.&lt;/p&gt;
&lt;p&gt;This realization has fundamentally changed how I work. I’ve started treating ADRs (Architecture Decision Records) and design documents not as &amp;ldquo;after-the-fact&amp;rdquo; documentation, but as essential inputs to be versioned in Git alongside the code. Goodbye Confluence; hello documentation-as-code.&lt;/p&gt;</description></item><item><title>Creating and releasing an application</title><link>https://prule.github.io/pauls-blog/post/coding/2026/creating-an-application/</link><pubDate>Sun, 22 Mar 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/creating-an-application/</guid><description>&lt;h2 id="creating-and-releasing-an-application"&gt;Creating and releasing an application&lt;/h2&gt;
&lt;p&gt;I love sim racing, so I thought it would be an interesting exercise to create an application that makes use of Assetto Corsa Competizione (ACC) telemetry.&lt;/p&gt;
&lt;p&gt;The basic operation is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The client sends a registration message to ACC&lt;/li&gt;
&lt;li&gt;ACC replies and starts sending telemetry messages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is all done over UDP.&lt;/p&gt;
&lt;h2 id="acc-messages"&gt;ACC messages&lt;/h2&gt;
&lt;p&gt;The first step was to create a library that could parse the message byte streams. There is a little bit of documentation in the way of some C# code and a &lt;code&gt;ServerAdminHandbook.pdf&lt;/code&gt; that can be found in the ACC installation.&lt;/p&gt;</description></item><item><title>Leave planner 1.1.0</title><link>https://prule.github.io/pauls-blog/post/coding/2026/leave-planner-1_1_0/</link><pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/leave-planner-1_1_0/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://prule.github.io/leave-planner/" target="_blank" rel="noopener"&gt;Leave Planner&lt;/a&gt;
 helps you track your leave balance and plan future holidays with ease.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="announcing-leave-planner-v110-work-from-home-tracking--more"&gt;Announcing Leave Planner v1.1.0: Work From Home Tracking &amp;amp; More!&lt;/h1&gt;
&lt;p&gt;This update brings a feature to help you manage your work life better, along with some under-the-hood improvements.&lt;/p&gt;
&lt;h2 id="-work-from-home-wfh-tracking"&gt;🏠 Work From Home (WFH) Tracking&lt;/h2&gt;
&lt;p&gt;With the rise of hybrid work, keeping track of the days you work from home is more important than ever, especially for tax purposes. Leave Planner now allows you to easily log your WFH days.&lt;/p&gt;</description></item><item><title>Leave planner application</title><link>https://prule.github.io/pauls-blog/post/coding/2026/leave-planner/</link><pubDate>Wed, 07 Jan 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/leave-planner/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Ever wanted to know how much leave you&amp;rsquo;ll have in the future and easily visualise your balance over time? Sure, some leave systems have some kind of future leave calculator, but none that I&amp;rsquo;ve seen make it easy or intuitive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Application available here, on github pages: &lt;a href="https://prule.github.io/leave-planner/" target="_blank" rel="noopener"&gt;https://prule.github.io/leave-planner/&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="the-spreadsheet-prototype"&gt;The spreadsheet prototype&lt;/h2&gt;
&lt;p&gt;To scratch my own itch, I started with a google sheet. The principle is simple: Enter your starting balance, and for each month fill in the estimated hours leave accrued. Add in your hours leave taken for the month&amp;hellip; and graph the total leave remaining.&lt;/p&gt;</description></item><item><title>YouTube channel aggregator experiment</title><link>https://prule.github.io/pauls-blog/post/coding/2026/youtube-channel-aggregator/</link><pubDate>Thu, 01 Jan 2026 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/youtube-channel-aggregator/</guid><description>&lt;p&gt;While trying to keep up with what&amp;rsquo;s happening in tennis and motorsport, I found myself wondering if the experience could be better. What if I could configure a list of channels, aggregate the videos, tag those videos by looking for keywords in their titles, and then have a convenient way to filter and navigate those.&lt;/p&gt;
&lt;p&gt;This provides me with a feed of relevant content which I can view oldest to newest. Watched videos are marked so they disappear from the feed, allowing me to pick up where I left off.&lt;/p&gt;</description></item><item><title>SDKMAN</title><link>https://prule.github.io/pauls-blog/post/coding/2025/sdkman/</link><pubDate>Mon, 15 Sep 2025 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2025/sdkman/</guid><description>&lt;div class="paragraph"&gt;
&lt;p&gt;SDKMAN! lets you install, manage and work with multiple versions of software development kits (SDKs) on most Unix-like systems.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;This means for example, you can install multiple versions of Java, Kotlin, Scala, Groovy, Gradle, Maven, Grails, Spring Boot, and many more. See the full list as of mid 2024 &lt;a href="sdk-list.txt"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_installation"&gt;Installation&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For installation instructions see the SDKMAN! website &lt;a href="https://sdkman.io/install"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sect2"&gt;
&lt;h3 id="_usage"&gt;Usage&lt;/h3&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;For common usage demonstration, using JAVA as an example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;To find all available versions of Java, run:&lt;/p&gt;
&lt;/div&gt;</description></item><item><title>Introduction to JSON5</title><link>https://prule.github.io/pauls-blog/post/coding/2025/json5/</link><pubDate>Thu, 06 Mar 2025 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2025/json5/</guid><description>&lt;div class="paragraph"&gt;
&lt;p&gt;Json5 is a superset of JSON that allows for comments and trailing commas. It’s a popular choice for configuration files due to its readability and flexibility.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;From the website:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="quoteblock"&gt;
&lt;blockquote&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Formally, the JSON5 Data Interchange Format is a superset of JSON (so valid JSON files will always be valid JSON5 files) that expands its syntax to include some productions from ECMAScript 5.1 (ES5). It’s also a subset of ES5, so valid JSON5 files will always be valid ES5.*&lt;/p&gt;
&lt;/div&gt;</description></item><item><title>Sharing gradle configuration</title><link>https://prule.github.io/pauls-blog/post/coding/2025/gradle-shared-config/</link><pubDate>Sat, 08 Feb 2025 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2025/gradle-shared-config/</guid><description>&lt;h1 id="sharing-gradle-configuration-between-modules"&gt;Sharing gradle configuration between modules&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Source code for this project is available at &lt;a href="https://github.com/prule/gradle-sample" target="_blank" rel="noopener"&gt;https://github.com/prule/gradle-sample&lt;/a&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When setting up multimodule gradle projects, we often need to share configuration - such as java toolkit version, plugins, junit platform etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;Previously I would have used the &lt;code&gt;allprojects&lt;/code&gt; or &lt;code&gt;subprojects&lt;/code&gt; block to do this, but now we have convention plugins. These are locally defined plugins which contain the configuration we want to share. The submodules can then apply those plugins without needing to copy and paste the configuration - this makes it easy to selectively choose which plugins to apply to which module.&lt;/p&gt;</description></item><item><title>Dependency upgrades with Renovate</title><link>https://prule.github.io/pauls-blog/post/coding/2025/renovate/</link><pubDate>Sun, 02 Feb 2025 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2025/renovate/</guid><description>&lt;div class="paragraph"&gt;
&lt;p&gt;In modern software development, managing dependencies is a critical yet often overlooked aspect of maintaining healthy codebases. Enter Renovate: an open-source tool that automates dependency updates, making your project maintenance both easier and more secure.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sect1"&gt;
&lt;h2 id="_what_is_renovate"&gt;What is Renovate?&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;Renovate is an automated dependency management tool that monitors your repository’s dependencies and automatically creates pull requests when updates become available. Think of it as your personal assistant that constantly checks for new versions of the libraries and packages your project uses.&lt;/p&gt;
&lt;/div&gt;</description></item><item><title>A Brief Introduction to AsciiDoc</title><link>https://prule.github.io/pauls-blog/post/coding/2024/asciidoc-example/</link><pubDate>Sun, 25 Aug 2024 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2024/asciidoc-example/</guid><description>&lt;div class="paragraph"&gt;
&lt;div class="notice info"&gt;
 &lt;div class="notice-title"&gt;Note&lt;/div&gt;
 &lt;div class="notice-content"&gt;
 The source code for this document is available at &lt;a href="https://github.com/prule/asciidoc-example" target="_blank" rel="noopener"&gt;github&lt;/a&gt;
.
Unfortunately though, GitHub does NOT support includes so you won&amp;rsquo;t see this document rendered properly. Instead, I&amp;rsquo;ve used the Intellij plugin to generate a PDF document which you can see here: &lt;a href="ReadMe.pdf"&gt;ReadMe.pdf&lt;/a&gt;
.
 &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;The source code for this document is available at &lt;a href="https://github.com/prule/asciidoc-example"&gt;github&lt;/a&gt;.
Unfortunately though, GitHub does NOT support includes so you won’t see this document rendered properly. Instead, I’ve used the Intellij plugin to generate a PDF document which you can see here: &lt;a href="ReadMe.pdf"&gt;ReadMe.pdf&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;</description></item><item><title>Clean architecture - part 1</title><link>https://prule.github.io/pauls-blog/post/coding/2024/clean-architecture-1/</link><pubDate>Sun, 25 Aug 2024 00:00:00 +0000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2024/clean-architecture-1/</guid><description>&lt;div class="sect1"&gt;
&lt;h2 id="_clean_architecture_part_1"&gt;Clean architecture - part 1&lt;/h2&gt;
&lt;div class="sectionbody"&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;After porting my template app over to Kotlin, I thought it was time to attempt rewriting from a layered architecture to a ports and adapters/hexagonal architecture.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="paragraph"&gt;
&lt;p&gt;In the layered version, the usual patterns exist:&lt;/p&gt;
&lt;/div&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The domain models ARE the database entities&lt;/p&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The domain model is compromised, cluttered with persistence concerns and far from clean&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Services implement the business logic, manipulating the domain (database entities) and persisting them via the repositories&lt;/p&gt;
&lt;div class="ulist"&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Unfortunately the services usually end up being classes with a bunch of methods&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description></item></channel></rss>