<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Craig Atkinson</title>
    <link>https://www.atkinsondev.com/</link>
    <description>Recent content on Craig Atkinson</description>
    <generator>Hugo -- gohugo.io</generator>
    <copyright>Copyright © 2020, Craig Atkinson; all rights reserved.</copyright>
    <lastBuildDate>Sun, 03 Jan 2021 00:00:00 +0000</lastBuildDate>
    
	<atom:link href="https://www.atkinsondev.com/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Faster test failure debugging with GenAI?</title>
      <link>https://www.atkinsondev.com/post/ai-test-failure-analysis/</link>
      <pubDate>Tue, 11 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/ai-test-failure-analysis/</guid>
      <description>What are some ways we can use GenAI to make developers&#39; lives easier?
A couple of years ago I had the chance to use GenAI to help build out a natural-language-to-query-language translator in a software observability system. This capability allowed users to ask a plain-English question such as &amp;quot;What are my slowest requests?&amp;quot; or &amp;quot;Show me my errors&amp;quot;. Then using ChatGPT we generated the corresponding query in our system&#39;s query language.</description>
    </item>
    
    <item>
      <title>Separate plumbing code from business logic</title>
      <link>https://www.atkinsondev.com/post/separate-plumbing-business-logic/</link>
      <pubDate>Thu, 13 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/separate-plumbing-business-logic/</guid>
      <description>Over the course of your career you will hear about many design patterns. From higher-level design patterns like model-view-controller and model-view-presenter to implementation patterns such as observer, singleton, and adapter pattern.
These patterns are valuable to establish a consistent design / architecture and separation of concerns in your application.
But many of the services we build today are largely integrations between different systems, with business logic sprinkled on top. How can we design the internals of these systems so they are understandable, maintainable, and testable?</description>
    </item>
    
    <item>
      <title>Faster Gradle builds through caching and parallelization</title>
      <link>https://www.atkinsondev.com/post/faster-gradle-builds/</link>
      <pubDate>Sat, 18 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/faster-gradle-builds/</guid>
      <description>Spend less time waiting for your build to run and more time developing software by enhancing your Gradle build with caching and parallel execution. The fastest part of your build is one you don&#39;t even need to run at all. And then run the necessary parts of your build in parallel.</description>
    </item>
    
    <item>
      <title>How many alerts are too many?</title>
      <link>https://www.atkinsondev.com/post/how-many-alerts/</link>
      <pubDate>Sun, 24 Mar 2024 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/how-many-alerts/</guid>
      <description>Recently I came across a Reddit post where the author wanted to know if their on-call situation was standard or if it was out of the ordinary. The post describes a tire fire, not a production-ready software system: &amp;quot;Is it normal to get alerted multiple times each and every hour of oncall, and then expected to go in to work?&amp;quot;</description>
    </item>
    
    <item>
      <title>ChatGPT experiment - analyzing a team&#39;s oncall impact</title>
      <link>https://www.atkinsondev.com/post/chatgpt-oncall-analysis/</link>
      <pubDate>Sun, 26 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/chatgpt-oncall-analysis/</guid>
      <description>As you&#39;ve likely seen, ChatGPT is getting a lot of attention lately. I wanted to experiment with it and see what I could learn, so this past weekend I tried out integrating ChatGPT into one of my apps. What was it like to work with and what could I potentially get from it? This is a recounting of my experiment.
A while back I built a frontend app to process and analyze a team&#39;s alerts from PagerDuty that I called OnCalm.</description>
    </item>
    
    <item>
      <title>You can&#39;t build everything: opportunity cost in software development</title>
      <link>https://www.atkinsondev.com/post/opportunity-cost-software-development/</link>
      <pubDate>Tue, 21 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/opportunity-cost-software-development/</guid>
      <description>Why can&#39;t you just add this new feature or fix that lingering bug? After all, it&#39;s the time and effort for that change alone - right? But it&#39;s not just the cost of what work you choose to tackle - you&#39;re also paying the price for all the other work you didn&#39;t implement instead. That&#39;s the opportunity cost.
Opportunity cost is the recognition that we have limited resources, and by choosing one option we are excluding other options.</description>
    </item>
    
    <item>
      <title>Ten communication tips for staff-plus engineers</title>
      <link>https://www.atkinsondev.com/post/communication-tips-staff-plus-engineers/</link>
      <pubDate>Wed, 04 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/communication-tips-staff-plus-engineers/</guid>
      <description>As a staff-plus engineer, you likely advanced through your career solving challenging technical problems. And now that you&#39;ve reached the staff-plus level, it&#39;ll just be more of that - won&#39;t it?
Sorry!
While in well-crafted staff-plus roles you will have sufficient focus and time for helping teams solve technical challenges, as a technical leader your scope now includes additional areas where so-called &amp;quot;soft skills&amp;quot; are very important. And your work up until this point may have been more on the technical side, so the importance of soft skills can be one of the bigger adjustments that staff-plus engineers such as yourself need to make to be successful in their role.</description>
    </item>
    
    <item>
      <title>Four keys I look for when reviewing software pull requests</title>
      <link>https://www.atkinsondev.com/post/pull-request-review-keys/</link>
      <pubDate>Sat, 10 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/pull-request-review-keys/</guid>
      <description>Over the past 15 years I&#39;ve reviewed hundreds upon hundreds of pull requests. From pull requests against projects I built and maintain to PRs submitted as promotion portfolio reviews in projects I&#39;ve never seen or worked on, and everything in between.
Over time I&#39;ve developed a set of four key items I look for in each pull request review - regardless of the circumstances of the change. I&#39;m synthesizing and sharing these keys with you in hopes they&#39;re helpful to you as well.</description>
    </item>
    
    <item>
      <title>Mock API servers for Maestro Android testing using MockServer and Gradle</title>
      <link>https://www.atkinsondev.com/post/android-maestro-mock-rest-api/</link>
      <pubDate>Thu, 17 Nov 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/android-maestro-mock-rest-api/</guid>
      <description>Maestro is a great library for writing high-level UI tests that verify your Android app works from your users&#39; perspective. For a more detailed intro into Maestro, please see my recent Maestro intro post.
If you&#39;re testing an app that makes REST API calls, you&#39;ll need a way to verify those parts of the app work correctly. While full tests that access real versions of the APIs can be valuable, there are tradeoffs to using real APIs in Maestro tests:</description>
    </item>
    
    <item>
      <title>High-level Android UI tests with Maestro</title>
      <link>https://www.atkinsondev.com/post/android-maestro-testing/</link>
      <pubDate>Sun, 30 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/android-maestro-testing/</guid>
      <description>For fun I&#39;ve recently been building an Android app with Kotlin and Compose. With this app, I can set goals for the week and track my progress towards those goals. My schedule is too varied day-to-day to successfully finish daily goals of say, read X minutes a day. But I found that setting goals per week helped me achieve those goals more easily than trying to find time each and every day to make progress on these goals.</description>
    </item>
    
    <item>
      <title>Running Android emulator tests in GitHub Actions</title>
      <link>https://www.atkinsondev.com/post/android-emulator-tests-github-actions/</link>
      <pubDate>Thu, 20 Oct 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/android-emulator-tests-github-actions/</guid>
      <description>Tests for your Android application can come in a couple different flavors:
 Unit tests Connected Android tests  You can execute the regular unit tests under the app/src/test directory without any special setup, but for the connected Android tests under app/src/androidTest you&#39;ll need a real device or an Android emulator. The connected Android tests can include testing UI interactions, on-device database queries, and more.
If you&#39;re using GitHub Actions for your CI, you can run your connected Android tests using an Android Emulator.</description>
    </item>
    
    <item>
      <title>Five ways to be a force multiplier in software engineering</title>
      <link>https://www.atkinsondev.com/post/force-multiplier/</link>
      <pubDate>Sun, 24 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/force-multiplier/</guid>
      <description>As you move along in your software engineering career, one of the biggest ways you can have a larger impact is to be a force multiplier.
What does it mean to be a force multiplier, you might ask? Having an outsized impact on others beyond your direct contributions. For example, helping level-up the skills of other members of your team so you can all deliver faster and with higher quality vs you alone just working the next development task.</description>
    </item>
    
    <item>
      <title>Stop lighting money on fire: Seven tips to improve developer productivity</title>
      <link>https://www.atkinsondev.com/post/improve-developer-productivity/</link>
      <pubDate>Wed, 27 Oct 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/improve-developer-productivity/</guid>
      <description>Software engineering teams are a critical component of many companies, where the effectiveness of these teams can have a significant impact on the company&#39;s success.
Making investments in areas such as these in improving developer productivity will pay off significantly, giving development teams more time to focus on delivering business capabilities and less time spent triaging production issues, fighting flaky tests, waiting for unnecessary build steps, or hunting down false production alerts.</description>
    </item>
    
    <item>
      <title>Lessons learned from building an open-source side project</title>
      <link>https://www.atkinsondev.com/post/open-source-side-project/</link>
      <pubDate>Sat, 18 Sep 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/open-source-side-project/</guid>
      <description>On Twitter you&#39;ll see jokes about folks purchasing domain names in the hopes of launching a side project. Then that domain comes up for renewal, taunting those never had the chance to launch that side project.
A couple of years ago I did the unthinkable - I built and released an open source side project and then purchased the domain afterwards.
My open-source project Projektor is by no means wildly popular, but I wanted to share out some of the lessons I learned while building it in the hopes it helps others who are looking to build and release their own open-source side projects.</description>
    </item>
    
    <item>
      <title>Why write code comments?</title>
      <link>https://www.atkinsondev.com/post/why-write-comments/</link>
      <pubDate>Sat, 21 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/why-write-comments/</guid>
      <description>We&#39;ve all seen it, code comments that are so obvious they add nothing but noise to the codebase. Redundant comments restating exactly what operation the code is performing.
For example, this function&#39;s purpose is obvious from its name - adding a comment as well doesn&#39;t add any value:
1// Verifies if the auth token is valid 2fun isAuthTokenValid(tokenFromRequest: String) = 3 authConfig.publishToken == tokenFromRequest Or the comment on this block of code, which again doesn&#39;t clarify anything beyond what is already understandable from the code:</description>
    </item>
    
    <item>
      <title>Cypress browser testing leveraging React Testing Library</title>
      <link>https://www.atkinsondev.com/post/cypress-testing-library/</link>
      <pubDate>Thu, 19 Aug 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/cypress-testing-library/</guid>
      <description>If you&#39;re writing unit tests for your React components these days, there&#39;s a good chance you&#39;re using React Testing Library. It supports user-focused testing with reliable selectors to find elements, such as the data-testid attribute or finding an element by role. Specific and reliable selectors are key to make sure tests are resilient against unrelated changes to the component structure breaking existing unit tests.
For example, if we have this component with a data-testid element:</description>
    </item>
    
    <item>
      <title>Code coverage stats - are they helpful?</title>
      <link>https://www.atkinsondev.com/post/code-coverage-helpful/</link>
      <pubDate>Mon, 05 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/code-coverage-helpful/</guid>
      <description>Code coverage - how many code lines and branches are accessed during a test - is easy to measure in many languages and test frameworks. And at first glance, measuring code coverage seems like a no-brainer. After all, who wouldn&#39;t want to make sure their code is sufficiently tested?
But just because a metric is easy to measure, doesn&#39;t necessarily mean it is helpful.
Why code coverage can be misleading Code coverage tools will measure which lines (and branches) are accessed during a test, but code coverage measurements don&#39;t tell you the value of those tests.</description>
    </item>
    
    <item>
      <title>Testing OpenTelemetry JVM instrumentation with Kotlin</title>
      <link>https://www.atkinsondev.com/post/opentelemetry-jvm-testing-kotlin/</link>
      <pubDate>Tue, 29 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/opentelemetry-jvm-testing-kotlin/</guid>
      <description>The OpenTelemetry Java instrumentation agent automatically instruments many common frameworks but there are times you may want to customize your application&#39;s telemetry by adding your own custom spans, adding attributes to existing spans, etc.
In that case, it can be helpful to verify the custom instrumentation through automated testing. I recently added custom telemetry to my Projektor test reporting app and documented the steps here that I used to verify it in case this is helpful for others.</description>
    </item>
    
    <item>
      <title>First steps into observability with OpenTelemetry, Honeycomb, and Kotlin</title>
      <link>https://www.atkinsondev.com/post/opentelemetry-honeycomb-kotlin/</link>
      <pubDate>Sun, 06 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/opentelemetry-honeycomb-kotlin/</guid>
      <description>In this post we&#39;ll go through my initial journey to add observability to the Projektor test reporting app using OpenTelemetry and Honeycomb. Projektor already has traditional monitoring with metrics around p95 response times for each REST endpoint, counters for successful and failed operations, etc. But I was intrigued to see what additional production insights I could learn from some more advanced observability tools like Honeycomb.
Getting started Projektor is written in a JVM language (Kotlin), so I started with Honeycomb&#39;s great guide on getting started with Java.</description>
    </item>
    
    <item>
      <title>Verifying order of React elements with React Testing Library</title>
      <link>https://www.atkinsondev.com/post/react-testing-library-order/</link>
      <pubDate>Tue, 06 Apr 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/react-testing-library-order/</guid>
      <description>Recently I was working on sorting rows in a table in React and I wanted to be able to verify the rows sorted into the correct order. The table shows flaky tests (that is, tests that intermittently fail) and is built with Material Table. Material Table conveniently supports sorting out of the box by clicking on the column name.
For this app, I&#39;m using React Testing Library for the component tests.</description>
    </item>
    
    <item>
      <title>Customizing Recharts graphs for React and testing them with Cypress</title>
      <link>https://www.atkinsondev.com/post/customizing-recharts-graph-cypress-testing/</link>
      <pubDate>Sun, 14 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/customizing-recharts-graph-cypress-testing/</guid>
      <description>After I added the ability to collect and store code coverage stats in the Projektor test reporting tool, I wanted to also add a graph that showed the trend of code coverage over time. Then users could track their repo&#39;s code coverage to see if was increasing, decreasing, or staying the same.
The Projektor UI is built with React, so I explored graphing library options for React. I found different options available, and found that Recharts fit in the sweet spot of being customizable - for example, for making the graph clickable to go to an individual test run - but also high-level enough to encapsulate most of the visualization code.</description>
    </item>
    
    <item>
      <title>Using the GitHub API with Kotlin</title>
      <link>https://www.atkinsondev.com/post/github-api-kotlin/</link>
      <pubDate>Wed, 10 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/github-api-kotlin/</guid>
      <description>Recently as part of Projektor test report project, I wanted to add the capability to comment directly on pull requests with links to the test report, code coverage stats, etc. That way users could get easier and faster access to the information than searching through the CI output to find the link to the Projektor test report. And if the project has code coverage, Projektor can compare the coverage percentage from the PR to the previous mainline build run, quickly telling reviewers whether the coverage increased, decreased, or stayed the same as part of the code changes.</description>
    </item>
    
    <item>
      <title>Improving Postgres query performance with explain/analyze</title>
      <link>https://www.atkinsondev.com/post/postgres-explain-analyze/</link>
      <pubDate>Sun, 07 Mar 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/postgres-explain-analyze/</guid>
      <description>Database queries slower than you&#39;d like? With Postgres&#39; built-in explain/analyze capability you can identify what&#39;s making the query slow and fix it.
In this example, we&#39;ll analyze the performance of query called as part of an API GET endpoint.
First, we&#39;ll seed our test database with enough data to get meaningful query analysis results. If the database has only a few records, Postgres may execute queries differently than if we have &amp;gt;100k records in production and the analysis results may not match what we&#39;d see in prod.</description>
    </item>
    
    <item>
      <title>Integrating database access and management with Flyway and jOOQ into a Kotlin Ktor app</title>
      <link>https://www.atkinsondev.com/post/database-jooq-flyway-ktor/</link>
      <pubDate>Sun, 28 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/database-jooq-flyway-ktor/</guid>
      <description>One of my goals when I started a learning project a couple of years ago was to get more hands-on experience with Kotlin co-routines, so I explored app frameworks that natively supported co-routines. I landed on Ktor, an open-source framework from JetBrains (creators of Kotlin) that supports co-routines throughout the framework. I&#39;ve really enjoyed working with Ktor, and the lightweight flexibility of the framework allowed me to easily integrate libraries like jOOQ and Flyway.</description>
    </item>
    
    <item>
      <title>Individually release different artifacts from monorepo with GitHub Actions using tags</title>
      <link>https://www.atkinsondev.com/post/github-actions-releasing-different-tags/</link>
      <pubDate>Wed, 24 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/github-actions-releasing-different-tags/</guid>
      <description>For the Projektor open-source test reporting project I wanted to keep all the code in a single mono repo to make it easy to work on and manage. But over time as the project evolved it grew into multiple deployable artifacts, and I wanted to be able to release each of those components independently as needed:
 Server .jar deployed to GitHub releases Gradle plugin deployed to the Gradle plugin portal Node package deployed to the NPM registry  The project is built with GitHub Actions, and after some digging I found that GitHub Actions supports executing different actions based on the format of a tag.</description>
    </item>
    
    <item>
      <title>Kotlin test assertions with informative failure messages using Strikt</title>
      <link>https://www.atkinsondev.com/post/strikt-kotlin-assertions/</link>
      <pubDate>Sun, 21 Feb 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/post/strikt-kotlin-assertions/</guid>
      <description>When I started writing Kotlin code a couple of years ago, one of the main things I missed after previously writing tests with Groovy/Spock were the easy yet powerful assertions with Groovy&#39;s power assert - not to mention the expressive failure messages when a test failed. Groovy&#39;s power assert prints out the .toString() of every element in the assertion, making it easier to diagnose what went wrong from reading the test report.</description>
    </item>
    
    <item>
      <title>About</title>
      <link>https://www.atkinsondev.com/about/</link>
      <pubDate>Sun, 03 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/about/</guid>
      <description>I&#39;m Craig Atkinson, a principal engineer who is passionate about making an impact through my work. Whether it&#39;s through architecting enterprise platforms, building products for customers, mentoring fellow engineers, or creating tools to improve developer productivity. In my 15+ years in the software industry I&#39;ve worked with companies at various stages, from startups to Fortune 50 enterprises - in a variety of industries, from medical devices, finance, insurance, developer productivity, to retail.</description>
    </item>
    
    <item>
      <title></title>
      <link>https://www.atkinsondev.com/archives/</link>
      <pubDate>Tue, 28 May 2019 00:00:00 +0000</pubDate>
      
      <guid>https://www.atkinsondev.com/archives/</guid>
      <description></description>
    </item>
    
  </channel>
</rss>