When I first started writing the XGallery3 application, I experimented with splitting out common code into NuGet packages. At the time, the experiment was mostly a failure since the shared code I split off into the packages was still undergoing a lot of changes. Updating the shared code, building, packaging, uploading, and downloading took several minutes even for simple changes.
Fast forward four years. I dusted off the old shared code libraries, converted them from .NET Framework 4.5 to .NET Core 7, and repackaged them.
Lesson #1 - Small Loosely-Coupled Packages
Like most of my projects, the Tools packages are constantly evolving. One of the biggest lessons I learned about NuGet packages was to make the packages as modular as possible with very little coupling. Most of the Tools packages now only depend on the Common package which contains a lot of helper classes and extension methods. But for a long time, I had the packages very tightly coupled because I had pulled them from a single application code base. When I started reusing the packages for other projects, I found a lot of the code I had shared out wasn't well suited for reuse. I spent part of 2021 and most of 2022 refactoring the package code base to reduce the coupling. Most of the refactoring was removing the Autofac registration methods I had created since they weren't reusable in different applications.
Lesson #2 - Automate Packaging & Pushing
In 2021, I started creating a home lab. I upgraded my home machine and was debating what to do with the old machine. A project from my day job required spinning up a few virtual machines to test some ArcGIS authentication so I repurposed the old machine as a server. I tried out Fedora Server and ProxMox before finally settling on TrueNAS Scale for the hypervisor. Since TrueNAS Scale supports Docker containers as well as virtual machines, I took the opportunity to create containers for several database servers and a Seq server. A co-worker suggested I set up a build server so I spent a weekend setting up TeamCity Server and a couple of build agents in containers.
Once the build server was up and running, setting up the build projects for all my code bases was pretty straightforward. Since I had already refactored the Tools code base to .NET Core, I created a build step to push the NuGet packages created by the previous build step to the NuGet Gallery. The benefit of this approach is two-fold. First, I can only push packages that successfully build and pass all of the unit and integration tests. Second, the package versions are handled automatically by TeamCity.
Lesson #3 - Versioning
My packages are badly versioned. When I started down this path, I assumed that since the packages were primarily for my personal use, the versioning didn't matter. But now that my packages are being shared in about a dozen home projects, the lack of proper versioning has become a detriment to their use. My next big project for the Tools package is to apply correct semantic versioning to all the packages.
Lesson #4 - Create Sample Code
Integration and unit tests are a valuable part of the Tools code base to make sure any changes don't break the existing behavior. I use code coverage to ensure as much of the code base is being tested. For a long time, I assumed that those tests would also serve as documentation on how to use the code. Unfortunately, that approach has not worked as well as I would have liked so in 2023 I created the samples code base to provide working examples of the packaged code.
I've also been using the samples code base to help refactor the packaged code to be less tightly coupled and manage versioning updates.