One important principle in program design is having a single source of truth for a specific program state. So if you have several ways of determining if a Page
is a Blog
page, this can get confusing and result in bugs.
Instead, you should have just one place where the Page
type is stored, and access it in a uniform way through the program. This principle is called the "single source of truth" and is well-known in computer science. It can be applied to many situations, including:
Page
example).As always, using caches to speed up access to this information can be problematic, as the cache ends up copying the single source of truth. Even when writing a simple program, relying on a unified, single source of truth is helpful.
It has always been a dream of mine to build a cool-looking website. But a lot of my early ideas for web design were based around light mode—images that look fine on a white background only. My concepts did not work for dark mode.
Sure, I was able to change the background color to black, but this just looked awkward and unbalanced. Instead, for a "cool-looking" website that works in dark mode, it is necessary to have vector graphics (like SVG) that dynamically adjust to the color mode.
Here are some things I have learned:
currentcolor
as a color in SVGs, and this will be modified when the user changes to dark or light mode.currentcolor
.It might not look as cool as I was hoping, but using SVG images works well for dark and light mode, and this benefits users who tend to prefer dark mode (like myself).
Sometimes simpler is better. I have been trying to push a 2-column layout on Dot Net Perls for some time, and while I feel it has worked reasonably well, it might be time for a change. People tend to expect a top-to-bottom article format. So I have updated the layout the articles on this site to be more sequential instead of side-by-side.
I am hoping this change is easier to maintain, and easier to use. I also changed the section icons so they are less intrusive, and also adhere better to dark mode (because most programmers use dark mode these days). The simpler markup is probably easier for bots to understand.
Probably my favorite C# article on this site has been the C# List article. The List
generic type is extremely useful: it can help in many programs. And it has been one of the most popular articles as well over the lifetime of Dot Net Perls.
The article has been updated many, many times, but some memories come to mind:
Even if it may not be the hottest new thing on the Internet these days, I think the List
article is still my favorite piece of writing on this site. It has helped many developers figure things out in their own programs over the years.
Some years ago it seemed like RSS feeds were the future of web publishing. Each site would have an RSS feed, and users would read articles each day from their favorite sites as the RSS feeds were updated.
But something happened. RSS feed support was removed from web browsers, and RSS feed readers were discontinued. It seemed like RSS feeds were just a relic of the past. But with the rise of AI-generated text, I wonder: could RSS feeds that are written by humans become a way to avoid AI-generated text in search engines?
These days, if you want to read AI-generated text, you have many options—it is everywhere. It may be difficult to find human-written text content in the oncoming flood of AI slop.
I added an RSS feed to this site, for the first time in years. I even validated that it is a correctly-formatted XML file. I downloaded a feed reader and it works correctly on the new RSS file—perhaps RSS feeds can make a comeback and provide a way for readers to avoid AI-generated text.
Usually when a program becomes big and complex enough (and important enough) it has some features that are slow. If left alone, the slowness will often become annoying. One thing I like to do in console programs is provide a hidden benchmark option.
When writing articles, I make many spelling errors so I have a spelling checker. Because of the quantity of text it must process, the spell-checker must be optimized. By providing a benchmark command, which causes the program to repeat the spell-checking many times, I can make sure the speller is kept in good condition.
Here are some benefits of using a hidden benchmark option:
Programs often last for many years, if they are useful. Even though a hidden benchmark command is still a micro-benchmark, which causes distortions in the results, it is still worth doing as it can highlight any regressions and give some motivation.
I have been writing about C# code for many years, and it has been a popular subject among developers. The language has kept becoming larger and more complicated with each release, but one feature from many years ago is still my favorite.
The word LINQ stands for Language Integrated Query. Think of database (SQL) queries, and how you can find (select), sort and filter or even join together results from a database. With LINQ, we can do this inside the C# language itself, on object
collections like Lists.
With some syntax additions to the language, we can:
from
-clause to have a query similar to a natural language question.order by
-clause to sort the results.select
-clause to specify how we want to have the results arranged.With queries similar to natural language, we can say "from this list, order items alphabetically and select items with this matching condition." In no other language have I found the same built-in quality of queries as in C#. While I might not love other aspects of C#, LINQ (System.Linq
) is my favorite.
Over the years the C# language has been updated many times, and each time the syntax seems to become more complex. It has adapted features from newer languages, and it has multiple ways to use a switch
statement, access elements in a List
, define methods, and more.
I can see why the language is updated by Microsoft—it would become obsolete otherwise. Developers would want to use more modern languages (like Rust) that have the newer features. But the problem with a language that is updated so many times is that it ends up being unrecognizable.
On each release, C# gains new features but these features were not part of its initial design:
switch
statement, but also a switch
expression that returns values (and has different syntax).List
in many ways—basically any syntax is supported.In my experience, most developers do not use many of the new features. Despite this, C# ends up becoming more complicated and difficult to use. If you have to learn so much new language syntax, why not just learn a language that was designed with modern features from the start? The language from .NET 4 makes more sense than what it has turned into in 2025.
Suppose you are making a website and want to have a static site generator. This is great for performance, but it means you need a way to deploy the files to a remote server. Rsync, a command-line tool, is ideal for this.
Over the years I have used various graphical FTP programs to deploy a statically-generated website, but rsync
is faster and more reliable (and also free). Basically with rsync
, one types in rsync
and then the "from" directory (the local folder) and the "to" directory (the remote folder on a server).
With command-line flags it can support SSH so that it can perform a secure update of the website. Then, once the files are deployed, the remote web server (like Caddy or NGINX) will automatically serve the new files. While the exact usage of rsync
is out of the scope of this post, it is available in WSL (Windows Subsystem for Linux) and macOS.
A lot of the times when I try out new software I am disappointed. It is hard to configure, it is too slow, or it is not an improvement over what I had before. But when I tested the Caddy web server, written in Go, I was pleasantly surprised.
Caddy is not exactly new software, as it has been around for a few years. With help from the official Caddy documentation, I was up and running on a test server within half an hour. I switched the live website to Caddy and there were no problems.
Caddy has some big advantages over other software like NGINX:
I had an issue with the site, but it turned out to be a Linux server misconfiguration problem. I needed to enable swap pages so the server would not run out of memory. Caddy was never at fault, and it performed admirably given the broken system it was running on.