<?xml version="1.0" encoding ="UTF-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.0">
  <channel>
    <title>Software Meadows</title>
    <description>A pleasant walk through computing</description>
    <link>https://www.softwaremeadows.com/feed</link>
    <link href="https://www.softwaremeadows.com/feed" rel="self" type="application/rss+xml" xmlns="http://www.w3.org/2005/Atom" />
    <item>
      <title>Navidrome IIS Reverse Proxy</title>
      <description>&lt;p&gt;This is a quick post, not a full How To.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;BLUF&lt;/strong&gt;&lt;br /&gt;
To use IIS as your reverse proxy for Navidrome: a) enable WebSockets, and b) clear the &lt;code&gt;Accept-Encoding&lt;/code&gt; header's value&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I recently replaced my long-running (and woefully unmaintained) Subsonic self-hosted music server with &lt;a href="https://www.navidrome.org/"&gt;Navidrome&lt;/a&gt;. This was initially (relatively) painless, as Navidrome has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A native Windows installer that also installs a Windows Service&lt;/li&gt;
&lt;li&gt;Straightforward ability to point to my existing library&lt;/li&gt;
&lt;li&gt;Reasonably easy to import playlists I exported from Subsonic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There were a few barriers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The documentation didn't seem as clear as I'd have liked on how &lt;a href="https://www.navidrome.org/docs/usage/configuration-options/"&gt;configuration options&lt;/a&gt; work. Specifically, that options can be set in the &lt;code&gt;navidrome.ini&lt;/code&gt; file OR server environment variables, and that the option names are not the same. But, in fairness, this was probably me being impatient.&lt;/li&gt;
&lt;li&gt;Navidrome organizes songs completely based on tags. This makes sense, but initially showed lots of my albums as separate songs. It was tedious (but worthwhile) to &lt;a href="https://www.mp3tag.de/en/"&gt;tag those songs&lt;/a&gt; to include Album Artist. The &lt;a href="https://www.navidrome.org/docs/usage/tagging-guidelines/"&gt;tagging guidelines documentation&lt;/a&gt; is very useful here . . .
&lt;ul&gt;
&lt;li&gt;Except, that in some cases the Year tag is what would cause albums to show separately. I'm pretty sure this has more to do with a bunch of MP4 (.m4a) files I have. Someday I'd like to convert those to MP3 and then reget the album info.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;My previous Subsonice reverse proxy didn't work with Navidrome.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last one is the subject of this post. I lost about eight hours on it. The reason to use a reverse proxy is because the Navidrome application (web server) doesn't support SSL. But, if using the app publically (not just within one's local network), SSL (HTTPS) is essential for security. Most of the web examples of using a reverse proxy with Navidrome use &lt;a href="https://nginx.org/en/docs/windows.html"&gt;nginx&lt;/a&gt;. I came very close to installing and using nginx, but that would have required me switching all of my other sites to use it to. Ugh.&lt;/p&gt;
&lt;p&gt;I use Microsoft Internet Information Server (IIS) on purpose; I'm a Microsoft stack developer, and need to understand the tools. And it seemed like it &lt;em&gt;should&lt;/em&gt; work. But I kept getting an HTTP 500 error.&lt;/p&gt;
&lt;p&gt;Finally, after looking at logs and beating my head against the keyboard (didn't help), I installed &lt;a href="https://www.telerik.com/fiddler/fiddler-classic"&gt;Fiddler Classic&lt;/a&gt; to watch the traffic. It didn't tell me more than I knew, but then I tried sending my GET request from Fiddler.&lt;/p&gt;
&lt;p&gt;And it worked.&lt;/p&gt;
&lt;p&gt;Fiddler Compose, by default, only uses two headers. This led to a process of elimination of the headers being sent. Fiddler made this pretty easy since I could copy the headers I sent from my browser request (examinging Fiddler Inspection) directly into the Fiddler Compose, eliminating them until it worked again. It turned out, the Navidrome app's web server doesn't accept encoding (or at least not standard encoding).&lt;/p&gt;
&lt;p&gt;Once I knew that, I could update IIS Url Rewrite to include the server variables (not at all well documented how those relate to HTTP headers) and change their values.&lt;/p&gt;
&lt;p&gt;Sorry, you'll need to do your own research on configuring IIS as a reverse proxy. There may be a better way than what I've done (because I'm still finding different documentation on how to do it).&lt;/p&gt;
&lt;p&gt;Here's the &lt;code&gt;web.config&lt;/code&gt; I used. It:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Passes requests from &lt;code&gt;https://music.flattland.com&lt;/code&gt; to Navidrome&lt;/li&gt;
&lt;li&gt;Changes the Accept-Encoding request header via a server variable&lt;/li&gt;
&lt;li&gt;Allows (somehow) WebSockets passthrough&lt;/li&gt;
&lt;li&gt;Rewrites outbound URL tag values if the Navidrome URL &lt;code&gt;http://localhost:4533&lt;/code&gt; is found&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;system.webServer&amp;gt;
        &amp;lt;rewrite&amp;gt;
            &amp;lt;rules&amp;gt;
                &amp;lt;rule name=&amp;quot;ReverseProxyInboundRule1&amp;quot; stopProcessing=&amp;quot;true&amp;quot;&amp;gt;
                    &amp;lt;match url=&amp;quot;(.*)&amp;quot; /&amp;gt;
                    &amp;lt;action type=&amp;quot;Rewrite&amp;quot; url=&amp;quot;http://localhost:4533/{R:1}&amp;quot; /&amp;gt;
                    &amp;lt;serverVariables&amp;gt;
                        &amp;lt;set name=&amp;quot;HTTP_SEC_WEBSOCKET_EXTENSIONS&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;
                        &amp;lt;set name=&amp;quot;HTTP_ACCEPT_ENCODING&amp;quot; value=&amp;quot;&amp;quot; /&amp;gt;
                        &amp;lt;set name=&amp;quot;HTTP_X_ORIGINAL_ACCEPT_ENCODING&amp;quot; value=&amp;quot;{HTTP_ACCEPT_ENCODING}&amp;quot; /&amp;gt;
                    &amp;lt;/serverVariables&amp;gt;
                &amp;lt;/rule&amp;gt;
            &amp;lt;/rules&amp;gt;
            &amp;lt;outboundRules&amp;gt;
                &amp;lt;rule name=&amp;quot;ReverseProxyOutboundRule1&amp;quot; preCondition=&amp;quot;ResponseIsHtml1&amp;quot;&amp;gt;
                    &amp;lt;match filterByTags=&amp;quot;A, Form, Img&amp;quot; pattern=&amp;quot;^http(s)?://localhost:4533/(.*)&amp;quot; /&amp;gt;
                    &amp;lt;action type=&amp;quot;Rewrite&amp;quot; value=&amp;quot;http{R:1}://music.flattland.com/{R:2}&amp;quot; /&amp;gt;
                &amp;lt;/rule&amp;gt;
                &amp;lt;preConditions&amp;gt;
                    &amp;lt;preCondition name=&amp;quot;ResponseIsHtml1&amp;quot;&amp;gt;
                        &amp;lt;add input=&amp;quot;{RESPONSE_CONTENT_TYPE}&amp;quot; pattern=&amp;quot;^text/html&amp;quot; /&amp;gt;
                    &amp;lt;/preCondition&amp;gt;
                &amp;lt;/preConditions&amp;gt;
            &amp;lt;/outboundRules&amp;gt;
        &amp;lt;/rewrite&amp;gt;
        &amp;lt;urlCompression doStaticCompression=&amp;quot;true&amp;quot; /&amp;gt;
    &amp;lt;/system.webServer&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;p&gt;Some of these I didn't use, but may still be helpful, especially if you're trying to mimic nginx.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.inedo.com/docs/installation/windows/web/howto-use-iis-as-reverse-proxy"&gt;HOWTO: Configure IIS as a Reverse Proxy for the Integrated Web Server&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;This site says to enable &amp;quot;preserveHostHeader,&amp;quot; which I didn't do. Maybe that would remove the need to overwrite Accept-Encoding?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables"&gt;Setting HTTP request headers and IIS server variables&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Official MS documentation. It confusingly does two things: changes language mapping and overwrites HTTP headers via server variables&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/20113296/how-to-set-the-x-forwarded-for-header-on-iis-reverse-proxy-setup"&gt;How to set the X-Forwarded-For header on IIS reverse proxy setup?&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;I didn't need to do this, but nginx shows it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.yossarian.net/2022/02/02/Setting-up-Navidrome-with-Nginx-as-a-reverse-proxy"&gt;Setting up Navidrome with Nginx as a reverse proxy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Fri, 2 Jan 2026 09:24:48 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/Navidrome IIS Reverse Proxy</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/Navidrome IIS Reverse Proxy</guid>
    </item>
    <item>
      <title>Flatt's Favorite Development Tools 2024</title>
      <description>&lt;p&gt;&lt;strong&gt;CONTENTS&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#my-ode-to-scott-hanselman"&gt;My Ode to Scott Hanselman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#why-do-tools-matter"&gt;Why Do Tools Matter?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#by-requirement"&gt;By Requirement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#by-license-type"&gt;By License Type&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#by-security"&gt;By Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#by-category"&gt;By Category&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-tools"&gt;The Tools&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#visual-studio"&gt;Visual Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#visual-studio-code"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#git-for-windows"&gt;Git for Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#powerbi-desktop"&gt;PowerBI Desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sql-server-developer"&gt;SQL Server Developer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sql-server-management-studio"&gt;SQL Server Management Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#powershell-7x"&gt;PowerShell 7.x&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#linqpad"&gt;LINQPad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#notepad"&gt;Notepad++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#azure-cli"&gt;Azure CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#windows-terminal"&gt;Windows Terminal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#windows-package-manager-winget"&gt;Windows Package Manager (winget)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#nvm-for-windows"&gt;NVM for Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#sharex"&gt;ShareX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#microsoft-remote-desktop-rdc-manager"&gt;Microsoft Remote Desktop (RDC) Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#7-zip"&gt;7-zip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#oh-my-posh"&gt;Oh-My-Posh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#kdiff3"&gt;KDiff3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#insomnia"&gt;Insomnia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#telerik-fiddler"&gt;Telerik Fiddler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ditto"&gt;Ditto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#balsamiq-wireframes"&gt;Balsamiq Wireframes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ultrafilesearch"&gt;UltraFileSearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#freecommander-xe"&gt;FreeCommander XE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#oracle-virtualbox"&gt;Oracle VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#inkscape"&gt;Inkscape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#paintnet"&gt;Paint.Net&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="my-ode-to-scott-hanselman"&gt;My Ode to Scott Hanselman&lt;/h2&gt;
&lt;p&gt;Scott, you are right, this post took so long!&lt;br /&gt;
I could have coded an app. I could have written a song.&lt;br /&gt;
But I've yearned to promote my fave tools for years&lt;br /&gt;
For the public to read, even if nobody cares.&lt;/p&gt;
&lt;p&gt;You're a tool nerd for sure, an App User Supreme&lt;br /&gt;
Trying utils in numbers I could only (of) dream.&lt;br /&gt;
You pointed the way, you're a software sensei,&lt;br /&gt;
Here's my kata in prose, my Tao (meaning &amp;quot;way&amp;quot;).&lt;/p&gt;
&lt;p&gt;You make coding real cool&lt;br /&gt;
Thank you, dude, and stay well.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.hanselman.com/blog/scott-hanselmans-2021-ultimate-developer-and-power-users-tool-list-for-windows"&gt;Scott Hanselman's 2021 Ultimate Developer and Power Users Tool List for Windows - Scott Hanselman's Blog&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="why-do-tools-matter"&gt;Why Do Tools Matter?&lt;/h2&gt;
&lt;p&gt;Let me ask you something? Could you build a house using just a hand saw, hammer, manual drill, and ruler?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Well, sure you could. But why in the world would you?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The DevOps Research and Assessment (DORA) group have conistently found that when software teams can &lt;a href="https://dora.dev/devops-capabilities/technical/teams-empowered-to-choose-tools/"&gt;choose their own tools they are more productive&lt;/a&gt; and deliver higher quality work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Teams that can choose which tools to use do better at continuous delivery. No one knows better than practitioners what they need to be effective.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Developers are power users. In organizations, they need to be entrusted with the security privileges to easily install and remove software. That's part of their job. Which isn't to say their tools shouldn't be audited. That's good security. But security departments should partner with developers and operations to reduce friction to developing valuable software. That's a responsible use of time and funds. Removing barriers to tool choice, along with practical security measures, is analogous to letting your skyscraper contractors use whichever tools they need while following safety protocols.&lt;/p&gt;
&lt;p&gt;Below are most of the tools I consider essential in my kit today. They've proven their worth over years and years. The list below includes some apps for SQL data reporting that may not be applicable to your environment. I'm missing several testing tools that the QA person on a team would require. Hopefully I can update with those in the future. I also include some design and testing tools that maybe you don't need to sling code but are valuable on a team. Or maybe you should try them and see!&lt;/p&gt;
&lt;p&gt;I'm a Microsoft stack developer and my choices reflect that.&lt;/p&gt;
&lt;h2 id="by-requirement"&gt;By Requirement&lt;/h2&gt;
&lt;p&gt;While all of the tools and utilities in this article are valuable, there are some without which development can't practically be done.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Must Have&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;LINQPad&lt;/li&gt;
&lt;li&gt;Git for Windows&lt;/li&gt;
&lt;li&gt;PowerBI Desktop&lt;/li&gt;
&lt;li&gt;SQL Server Developer&lt;/li&gt;
&lt;li&gt;SQL Server Management Studio&lt;/li&gt;
&lt;li&gt;PowerShell 7&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;Telerik Fiddler&lt;/li&gt;
&lt;li&gt;ShareX&lt;/li&gt;
&lt;li&gt;Balsamiq Wireframes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;High Value&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything else!&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;del&gt;&lt;strong&gt;Note&lt;/strong&gt; It was hard leaving LINQPad out of the Must Have section. I'd hate to be without it; the ROI is incredibly high. But it's not--technically--essential.&lt;/del&gt;
&lt;strong&gt;Update 2025&lt;/strong&gt;  I've changed my mind. I've found LINQPad to be so useful and save so much time that I consider it an essential tool.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="by-license-type"&gt;By License Type&lt;/h2&gt;
&lt;p&gt;The only types listed here are Free and Licensed. Some apps (such as LINQPad) have free versions that aren't adequate for daily, high-performance use. In those cases, they're listed as Licensed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Licensed&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio&lt;/li&gt;
&lt;li&gt;LINQPad&lt;/li&gt;
&lt;li&gt;Balsamiq Wireframes&lt;/li&gt;
&lt;li&gt;UltraFileSearch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;Git for Windows&lt;/li&gt;
&lt;li&gt;PowerBI Desktop&lt;/li&gt;
&lt;li&gt;SQL Server Developer&lt;/li&gt;
&lt;li&gt;SQL Server Management Studio&lt;/li&gt;
&lt;li&gt;PowerShell 7.x&lt;/li&gt;
&lt;li&gt;Notepad++&lt;/li&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Windows Terminal&lt;/li&gt;
&lt;li&gt;Windows Package Manager (winget)&lt;/li&gt;
&lt;li&gt;NVM for Windows&lt;/li&gt;
&lt;li&gt;ShareX&lt;/li&gt;
&lt;li&gt;Microsoft Remote Desktop (RDC) Manager&lt;/li&gt;
&lt;li&gt;7-zip&lt;/li&gt;
&lt;li&gt;Oh-My-Posh&lt;/li&gt;
&lt;li&gt;&lt;del&gt;KDiff3&lt;/del&gt; Updated 2025&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;Telerik Fiddler&lt;/li&gt;
&lt;li&gt;FreeCommander XE&lt;/li&gt;
&lt;li&gt;Oracle VirtualBox&lt;/li&gt;
&lt;li&gt;Inkscape&lt;/li&gt;
&lt;li&gt;Paint.Net&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="by-security"&gt;By Security&lt;/h2&gt;
&lt;p&gt;Many apps require UAC to install, but don't require admin rights to run.  They may also require UAC with an exe/winget installer but also have portable versions. Apps are categorized below by least-needed privilege. For example, Git for Windows need UAC for the exe installer but not for portable, so it's listed under portable. Likewise if it's non-UAC but also has a portable, then the app is listed as portable.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While portable apps are viable, I recommend using an installer--winget is ideal!--whenever possible. This makes it much easier to keep software up to date and secure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Install UAC = true&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio&lt;/li&gt;
&lt;li&gt;PowerBI Desktop&lt;/li&gt;
&lt;li&gt;SQL Server Developer&lt;/li&gt;
&lt;li&gt;SQL Server Management Studio&lt;/li&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Windows Package Manager (winget)&lt;/li&gt;
&lt;li&gt;NVM for Windows&lt;/li&gt;
&lt;li&gt;7-zip&lt;/li&gt;
&lt;li&gt;&lt;del&gt;KDiff3&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;Telerik Fiddler&lt;/li&gt;
&lt;li&gt;Balsamiq Wireframes&lt;/li&gt;
&lt;li&gt;UltraFileSearch&lt;/li&gt;
&lt;li&gt;Oracle VirtualBox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Install UAC = false&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;Oh-My-Posh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Portable&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Git for Windows&lt;/li&gt;
&lt;li&gt;PowerShell 7&lt;/li&gt;
&lt;li&gt;LINQPad&lt;/li&gt;
&lt;li&gt;Notepad++&lt;/li&gt;
&lt;li&gt;Windows Terminal&lt;/li&gt;
&lt;li&gt;ShareX&lt;/li&gt;
&lt;li&gt;Microsoft Remote Desktop (RDC) Manager&lt;/li&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;Ditto&lt;/li&gt;
&lt;li&gt;FreeCommander XE&lt;/li&gt;
&lt;li&gt;Inkscape&lt;/li&gt;
&lt;li&gt;Paint.Net&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="by-category"&gt;By Category&lt;/h2&gt;
&lt;p&gt;These categories are kind of loose, but helped me understand my own tool use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IDEs and Editors
&lt;ul&gt;
&lt;li&gt;Visual Studio&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;/li&gt;
&lt;li&gt;LINQPad&lt;/li&gt;
&lt;li&gt;Notepad++&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Version Control
&lt;ul&gt;
&lt;li&gt;Git for Windows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Terminals and Shells
&lt;ul&gt;
&lt;li&gt;PowerShell 7.x&lt;/li&gt;
&lt;li&gt;Windows Terminal&lt;/li&gt;
&lt;li&gt;Oh-My-Posh&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Software Management
&lt;ul&gt;
&lt;li&gt;Window Package Manager (winget)&lt;/li&gt;
&lt;li&gt;NVM for Windows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Diff and Merge
&lt;ul&gt;
&lt;li&gt;&lt;del&gt;KDiff3&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Debugging
&lt;ul&gt;
&lt;li&gt;Insomnia&lt;/li&gt;
&lt;li&gt;Telerik Fiddler&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Other
&lt;ul&gt;
&lt;li&gt;Azure CLI&lt;/li&gt;
&lt;li&gt;Microsoft Remote Desktop (RDC) Manager&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Design&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Balsamiq Wireframes&lt;/li&gt;
&lt;li&gt;Visio&lt;/li&gt;
&lt;li&gt;Inkscape&lt;/li&gt;
&lt;li&gt;Paint.Net&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Oracle VirtualBox&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Data&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PowerBI Desktop&lt;/li&gt;
&lt;li&gt;SQL Server Developer&lt;/li&gt;
&lt;li&gt;SQL Server Management Studio&lt;/li&gt;
&lt;li&gt;Oracle IDE of some kind&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;General Utilities&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;7-zip&lt;/li&gt;
&lt;li&gt;Ditto&lt;/li&gt;
&lt;li&gt;UltraFileSearch&lt;/li&gt;
&lt;li&gt;Ditto&lt;/li&gt;
&lt;li&gt;FreeCommander XE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Documentation and Support&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ShareX&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-tools"&gt;The Tools&lt;/h2&gt;
&lt;h3 id="visual-studio"&gt;Visual Studio&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://visualstudio.microsoft.com/downloads/"&gt;https://visualstudio.microsoft.com/downloads/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free | Individual 45/user/mo | Enterprise 240/user/mo&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Visual Studio has provided perhaps the best IDE for decades. Not using it for most Microsoft stack development would be like not designing skyscrapers using computer-aided design.&lt;/p&gt;
&lt;h3 id="visual-studio-code"&gt;Visual Studio Code&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://code.visualstudio.com/download"&gt;https://code.visualstudio.com/download&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: N&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Several years ago Microsoft went from having the world's simplest text editor--Notepad--to creating one of the best text editors available on any platform. VS Code out of the box includes amazing features including file comparison and Git support. Its tens of thousands of extensions let you be super-productive.&lt;/p&gt;
&lt;h3 id="git-for-windows"&gt;Git for Windows&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://gitforwindows.org/"&gt;https://gitforwindows.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget)  N (zip)
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Git is the de facto version control system today and Git for Windows is the must-have tool for Windows users.&lt;/p&gt;
&lt;h3 id="powerbi-desktop"&gt;PowerBI Desktop&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/download/details.aspx?id=58494"&gt;https://www.microsoft.com/en-us/download/details.aspx?id=58494&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget,&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;If you're creating PowerBI reports, you need this application.&lt;/p&gt;
&lt;h3 id="sql-server-developer"&gt;SQL Server Developer&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/sql-server/sql-server-downloads"&gt;https://www.microsoft.com/en-us/sql-server/sql-server-downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;When developing against a SQL database there are two local choices: Developer or Express. Developer is the superior choice because it includes all the same features as SQL Server, letting you develop with parity.&lt;/p&gt;
&lt;h3 id="sql-server-management-studio"&gt;SQL Server Management Studio&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms"&gt;https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;There are other really good SQL tools, but SSMS is still the best overall.&lt;/p&gt;
&lt;h3 id="powershell-7.x"&gt;PowerShell 7.x&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/powershell/"&gt;https://learn.microsoft.com/en-us/powershell/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, msi, winget) N (zip, msixbundle, dotnet)
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, msi, winget, zip, msixbundle, dotnet&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;There's a version of PowerShell that's pre-installed in Windows called, naturally, &lt;em&gt;PowerShell for Windows&lt;/em&gt;. But the latest version of PowerShell--version 7--is what you want to use. It has new features and is cross-platform. It's also what's used by Azure DevOps Pipelines, so if you're writing PowerShell scripts for ADO you want to use the same version.&lt;/p&gt;
&lt;h3 id="linqpad"&gt;LINQPad&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.linqpad.net/"&gt;https://www.linqpad.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)&lt;br /&gt;
COSTS: Free | Individual 125/major ver | Team 10-user 850/major ver&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;There are a few tools I always pay for because they save me (and my client or employer) ten times over. One of those is LINQPad. In truth, I only occassionally use it for database querying. I mostly use it for code prototyping, debugging, and utilities. I'd estimate using this tool saves me a couple hundred hours a year. You need to buy a license to get Intellisense and other features. It's a bargain.&lt;/p&gt;
&lt;h3 id="notepad"&gt;Notepad++&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://notepad-plus-plus.org/downloads/"&gt;https://notepad-plus-plus.org/downloads/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Nowadays I use VS Code for most of my text editing. But Notepad++ still has features that make it valuable to install. For example, it has excellent search-in-files where results are output to a separate pane. I've also found it integrates better into Git as the default editor for things like &lt;code&gt;git commit --amend&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="azure-cli"&gt;Azure CLI&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/cli/azure/"&gt;https://learn.microsoft.com/en-us/cli/azure/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: winget, msi&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Sometimes you can gain real automation benefits by writing command line tools. Accessing Azure Portal and Azure DevOps via a CLI is very helpful. Here's one use case: A script that runs a batch of DevOps pipelines.&lt;/p&gt;
&lt;h3 id="windows-terminal"&gt;Windows Terminal&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/terminal/"&gt;https://learn.microsoft.com/en-us/windows/terminal/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: N&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: winget, zip, msixbundle&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;When Microsoft decided to &lt;em&gt;finally&lt;/em&gt; create a professional terminal they delivered in spades. Windows Terminal can run many shells--command, PowerShell, Bash--in a modern tabbed interface. In Windows 11 it has offically replaced the ancient command prompt.&lt;/p&gt;
&lt;h3 id="windows-package-manager-winget"&gt;Windows Package Manager (winget)&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/"&gt;https://learn.microsoft.com/en-us/windows/package-manager/winget/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: msixbundle&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Winget is apt-get for Windows. It's Microsoft's answer to Chocolaty. It's built into Windows 11. And it's categorized by Microsoft as a developer tool. It's the easiest way to install and upgrade local software, saving developers hours of time. It reduces friction to keeping software up-to-date, which is great for security. For onboarding, a simple script can be created that allows setting up a development machine in 20 minutes instead of two (or more!) hours.&lt;/p&gt;
&lt;p&gt;In short, winget is a great productivity tool fully supported by Microsoft.&lt;/p&gt;
&lt;h3 id="nvm-for-windows"&gt;NVM for Windows&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/coreybutler/nvm-windows"&gt;https://github.com/coreybutler/nvm-windows&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Developing apps using Node has a drawback: by default you can only have one version installed at a time. The solution is Node Version Manager (nvm) for Windows. This mighty tool needs to run with Admin privileges because it installs and switchs the currently active Node version. It's a critical, time-saving tool for situations like upgrading versions.&lt;/p&gt;
&lt;h3 id="sharex"&gt;ShareX&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://getsharex.com/"&gt;https://getsharex.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;You can pay for SnagIt and get an adequate experience. Or you can &lt;em&gt;not&lt;/em&gt; pay for ShareX and customize your experience to be super-efficient. The time to learn this tool is well worth it. I use screen shots every day for writing documentation, creating bug reports, posting questions to other developers. Taking and editing screen shots should be as frictionless as possible. No other tool I've used does it better. You can even perform decent OCR and make short screen recordings and GIFs (very helpful for training). ShareX probably saves me a hundred hours a year.&lt;/p&gt;
&lt;h3 id="microsoft-remote-desktop-rdc-manager"&gt;Microsoft Remote Desktop (RDC) Manager&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/sysinternals/downloads/rdcman"&gt;https://learn.microsoft.com/en-us/sysinternals/downloads/rdcman&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: N&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Sometimes you only have to log into one or two servers using Remote Desktop. But other times you need to log into quite a few and bounce back and forth between them. That's when RDC Man, from the venerable Sysinternals (part of Microsoft), is your friend. It's &lt;em&gt;just&lt;/em&gt; a way of launching and organizing RDP sessions, but man is it helpful!&lt;/p&gt;
&lt;h3 id="zip"&gt;7-zip&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.7-zip.org/download.html"&gt;https://www.7-zip.org/download.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, msi, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Windows has Zip decompression built in. But 7-zip is still the tool to install when you regularly deal with compressed files. And developers deal with compressed files all the time. It's the best utility for the job, plus the 7z compression is amazing.&lt;/p&gt;
&lt;h3 id="oh-my-posh"&gt;Oh-My-Posh&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://ohmyposh.dev/"&gt;https://ohmyposh.dev/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: N&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, powershell&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;I do most of my Git work at the command line. I take advantage of aliases and the power that Visual Studio and VS Code don't have. The smartest thing I did a couple of years ago was install Oh-My-Posh so I can, at a glance, know the status of my repo. Just this utility has saved me from making dumb mistakes that would have cost me hours of time. I'd be foolish not to use it.&lt;/p&gt;
&lt;h3 id="kdiff3"&gt;KDiff3&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://download.kde.org/stable/kdiff3/?C=M;O=D"&gt;https://download.kde.org/stable/kdiff3/?C=M;O=D&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2025:&lt;/strong&gt; I no longer use KDiff3. It's a good tool, but I've found that VS Code's Git 3-way merge is better. However, for folder diffing you need KDiff or something like it. (FreeCommander XE has folder compare, for example)&lt;/p&gt;
&lt;p&gt;I'll admit right now I've never used Beyond Compare. I should evaluate it, for sure. In the meantime, what other file diff/merge tools are out there? VS Code does a good job and can be called from the Git CLI. Visual Studio's diff/merge isn't quite as good in my opinion. WinMerge--another free tool--is nice but doesn't open well from Git CLI. But it does compare folders, which VS and Code don't. And then there's KDiff3. It's hard to find the latest version of this tool, so use the link above. What I like about KDiff3 above the other tools is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opens quickly from Git CLI&lt;/li&gt;
&lt;li&gt;Has the clearest 3-way merge experience&lt;/li&gt;
&lt;li&gt;Shows character diffs&lt;/li&gt;
&lt;li&gt;Has a good folder diff&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Honestly, no tool magically resolves Git merge conflicts. They're all taking their best guess. So find a tool or two you like.&lt;/p&gt;
&lt;h3 id="insomnia"&gt;Insomnia&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/Kong/insomnia"&gt;https://github.com/Kong/insomnia&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://insomnia.rest/"&gt;https://insomnia.rest/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: N&lt;br /&gt;
COSTS: Free | |Individual 5/mo | Team  12/user/mo
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2025:&lt;/strong&gt;  My workplace uses Postman, so I haven't used Insomnia for a long time. I'm keeping it on the list, but I can't fully recommend it.&lt;/p&gt;
&lt;p&gt;Postman is the big name tool for testing web services (e.g. REST APIs). But I . . . kind of . . . don't like it. Insomnia just seems like a tool focused on making the work easier, not selling me licenses. In fact, to use it for free, download from GitHub, install choosing local, and use the local scratch pad. I admit, that path is a little hidden, but it's a great way to try out the tool long term.&lt;/p&gt;
&lt;p&gt;For QA departments, Postman may be a smarter tool and maybe it's good for developers, too. But I'd give Insomnia a fair chance.&lt;/p&gt;
&lt;h3 id="telerik-fiddler"&gt;Telerik Fiddler&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.telerik.com/download/fiddler"&gt;https://www.telerik.com/download/fiddler&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;I don't reach for Fiddler every day. But on those days I need to know exactly what's going on with my web app traffic, I could either guess for hours or I can run Fiddler and know if a few minutes. It's an essential tool for that reason.&lt;/p&gt;
&lt;h3 id="ditto"&gt;Ditto&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://ditto-cp.sourceforge.io/"&gt;https://ditto-cp.sourceforge.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;A utility I didn't know I needed until I had it, Ditto was demonstrated to me by a colleague a couple of years ago. I'm amazed how often I use it, not only for simple cases (I copied something to the clipboard ten minutes ago and have since copied over it. Ditto lets me get that previous copy) but for some power-user situations. I've used it to make several dozen entries where I needed to use three or four different copy-paste operations. A real time-saver!&lt;/p&gt;
&lt;h3 id="balsamiq-wireframes"&gt;Balsamiq Wireframes&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://balsamiq.com/wireframes/desktop/"&gt;https://balsamiq.com/wireframes/desktop/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Trial | Individual 129/maj ver | Cloud 2 project 90/year, 20 project 490/year (unlim users)&lt;br /&gt;
INSTALLATION: cloud, exe, msi, winget (To install w/o UAC, VC Redist must already be installed)&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;I love Balsamiq. I've used it for years. It's delightful. It's keyboard-centric, making it quick to create wireframes. The results are, by design, low-fidelity, which signals to customers and users &amp;quot;this is not the final design.&amp;quot; The cloud version has collaboration features (which I haven't used). Most of all, the company has made it a joy to use.&lt;/p&gt;
&lt;h3 id="ultrafilesearch"&gt;UltraFileSearch&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.ultrafilesearch.com/"&gt;https://www.ultrafilesearch.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC:Y&lt;br /&gt;
COSTS: Trial | Individual 25/maj ver | Team(5) 20/user/maj ver&lt;br /&gt;
INSTALLATION: exe, msi, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;You can search for files and folders in Windows. You can even power search--sort of--using arcane commands. Or you can use a dedicated file search tool. VS Code has some capability in this regard, but UltraFileSearch is one I like a lot. It's worth paying for. I'm always suprised just how much I have to search source code. Visual Studio doesn't cut it for refined searching.&lt;/p&gt;
&lt;p&gt;I also like FreeCommander's file search.&lt;/p&gt;
&lt;h3 id="freecommander-xe"&gt;FreeCommander XE&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://freecommander.com/en/summary/"&gt;https://freecommander.com/en/summary/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)&lt;br /&gt;
COSTS: Free (x32) | Individual 20/year ver (x64)&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;One day awhile back I got tired of having a half dozen File Exporer windows open. Really tired. So I evaluated most of the &amp;quot;explorer replacements&amp;quot; out there and, while several were good, only one let me do everyting I wanted: dual-pane for files, tabs, a pane for favorites, and a pane for the tree.&lt;/p&gt;
&lt;p&gt;FreeCommander does much more than file management, but just being able to have one window where I can easily switch folders? It's amazing how much it streamlines my work. It also has a really good file search (though I like UltraFileSearch a little better for power use), batch file renaming, and customizable tool bar where, for instance, I have a button to launch VS Code in the currently selected folder.&lt;/p&gt;
&lt;h3 id="oracle-virtualbox"&gt;Oracle VirtualBox&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.virtualbox.org/"&gt;https://www.virtualbox.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;Back in the day--decades ago--I fell in love with VMWare Workstation. It was the first app that let you install an operating system &lt;em&gt;inside&lt;/em&gt; an operating system. It was--and is--magical. But VMWare is now a behemoth. Filling the desktop user's need is VirtualBox. What good is it to a developer? Simply, it's a relatively quick way to test software simulating a regular user's machine. This can be critical for debugging. In fact, I used it while compiling this guide to test every software installation!&lt;/p&gt;
&lt;h3 id="inkscape"&gt;Inkscape&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://inkscape.org/"&gt;https://inkscape.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (zip)&lt;br /&gt;
COSTS: Free&lt;br /&gt;
INSTALLATION: exe, winget, zip&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;By all means, pay huge amounts of money to Adobe if you're a professional corporate designer. But if you only occassionly need to create sophisticated vector graphics, Inkscape is legend. It takes some effort to learn--it doen't hold your hand--but it's worth the time.&lt;/p&gt;
&lt;h3 id="paint.net"&gt;Paint.Net&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://getpaint.net/download.html"&gt;https://getpaint.net/download.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;UAC: Y (exe, winget) N (store, zip)&lt;br /&gt;
COSTS: Free | Individual 10/maj ver&lt;br /&gt;
INSTALLATION: exe, winget, store, zip (github)&lt;/p&gt;
&lt;p&gt;DESCRIPTION&lt;/p&gt;
&lt;p&gt;To repeat myself, by all means feed the Adobe leviathan. Photoshop is king. But for most developers, Paint.Net is plenty for basic photo retouching. It's a great tool.&lt;/p&gt;
</description>
      <pubDate>Tue, 2 Jan 2024 21:37:19 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/flatts_favorite_development_tools_2024</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/flatts_favorite_development_tools_2024</guid>
    </item>
    <item>
      <title>Git Demand Flow</title>
      <description>&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/git_demand_flow/git_demand_flow.png" alt="" /&gt;&lt;/p&gt;
&lt;h2 id="the-issue"&gt;The Issue&lt;/h2&gt;
&lt;p&gt;Plenty of research says using a trunk-based version control merge/branch strategy is highly effective. But what if a team isn't ready for this?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The trunk-based strategy expects that every commit to main is ready for production (assuming it passes all automated tests).&lt;/li&gt;
&lt;li&gt;If a commit isn't ready for production, a great technique is to hide the change behind a feature flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our team has this situation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Commits need to be tested on demand.&lt;/li&gt;
&lt;li&gt;But only some of those commits will be deployed to production right away.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, we may be working on a larger feature that--for various reasons--has to be released all together. For now, we cannot use feature flags and we can't easily add more discrete testing environments.&lt;/p&gt;
&lt;p&gt;Git Flow seems like a solution, but it still expects to merge point-in-time commits into main.&lt;/p&gt;
&lt;p&gt;Here is an approach we're trying. It maintains two independent--but related--branches: test and main. Release branches feed main.&lt;/p&gt;
&lt;h2 id="rules"&gt;Rules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No PRs to test or main without a story&lt;/li&gt;
&lt;li&gt;Latest &lt;code&gt;test&lt;/code&gt; can always be deployed to Test&lt;/li&gt;
&lt;li&gt;A PR to &lt;code&gt;test&lt;/code&gt; must be QA-ready&lt;/li&gt;
&lt;li&gt;Latest &lt;code&gt;main&lt;/code&gt; can always be deployed to Production&lt;/li&gt;
&lt;li&gt;A PR to &lt;code&gt;main&lt;/code&gt; must be production-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="work-flow"&gt;Work flow&lt;/h2&gt;
&lt;p&gt;I was tempted to use feature branches for longer-lived changes. But we already link stories to features, so using a feature branch in Git seems unnecessary.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It would also require lots of rebasing and forced pulls, the combination of which is asking for trouble.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Besides branching and merging, the flow below refers to tagging stories, moving them into columns, and triggering pipelines. We use Azure DevOps for all of this. You can ignore that stuff if you want, it's not required for the branch/merge strategy.&lt;/p&gt;
&lt;p&gt;What matters most is we&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PR into &lt;code&gt;test&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cherry-pick into &lt;code&gt;release&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;PR into &lt;code&gt;main&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Flow&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Developer begins coding for a story in a branch, e.g. &lt;code&gt;clf/198222-improve-customer-grid-performance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;When the story is ready for QA:
&lt;ol&gt;
&lt;li&gt;Tag story as Deployable&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;When QA requests testing one or more stories:
&lt;ol&gt;
&lt;li&gt;PR: merge &lt;code&gt;clf/198222-improve-customer-grid-performance&lt;/code&gt; into &lt;code&gt;test&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tag &lt;code&gt;test&lt;/code&gt; branch commit to trigger pipelines&lt;/li&gt;
&lt;li&gt;Remove Deployable tags&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;When stories are fully tested
&lt;ol&gt;
&lt;li&gt;Move to UAT Done&lt;/li&gt;
&lt;li&gt;If deployable to production, tag as Deployable for next release&lt;/li&gt;
&lt;li&gt;Move Deployable to Deploy Doing&lt;/li&gt;
&lt;li&gt;Branch from &lt;code&gt;main&lt;/code&gt; to &lt;code&gt;release/[datetime]&lt;/code&gt;. &lt;em&gt;Cherry pick&lt;/em&gt; story commits into release branch.&lt;/li&gt;
&lt;li&gt;PR: merge &lt;code&gt;release/[datetime]&lt;/code&gt; into &lt;code&gt;main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tag &lt;code&gt;main&lt;/code&gt; branch commit to trigger pipelines&lt;/li&gt;
&lt;li&gt;Delete story branches&lt;/li&gt;
&lt;li&gt;Delete Deployable tags&lt;/li&gt;
&lt;li&gt;Move to Deploy Done&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="wrap-up"&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;This flow seems like it will succeed in keeping both &lt;code&gt;test&lt;/code&gt;--and especially &lt;code&gt;main&lt;/code&gt;--branches clean until we're ready for trunk-based development.&lt;/p&gt;
</description>
      <pubDate>Thu, 28 Dec 2023 20:27:53 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/git_demand_flow</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/git_demand_flow</guid>
    </item>
    <item>
      <title>Better Bugs and Stories</title>
      <description>&lt;h2 id="why"&gt;Why?&lt;/h2&gt;
&lt;p&gt;Written communication is hard. Bugs and stories too often lead to people having to unnecessarily ask someone to explain what's been written because it's vague. There's such a thing as too much detail, but too little, unclear information is more common.&lt;/p&gt;
&lt;p&gt;This article doesn't cover all about writing good user stories or bugs. It focuses on a few practices that I've found help the most.&lt;/p&gt;
&lt;h2 id="bugs"&gt;Bugs&lt;/h2&gt;
&lt;p&gt;The most important parts of a bug report are A) the steps to reproduce the problem, and B) clarity of what the problem is.&lt;/p&gt;
&lt;p&gt;There are many audiences for bugs: the user who's reporting, the developer who's fixing, the product manager or business analyst who's communicating the bug from the user to the team.&lt;/p&gt;
&lt;p&gt;All of these audiences have different mental models of the application and often assume others know what they do. How do we make sure the steps are clear? Here's one tip I like.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Write the repro steps as if you were training a new employee&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here's how the initial user (who &lt;em&gt;could&lt;/em&gt; be a developer or product owner, really anyone) might initially desribe a bug.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-text"&gt;Help! When I search for a customer it should show me the last modified date but isn't.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clarifying this bug may require a few messages or, ideally, watching the person do the work. The bug report might end up like this.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-text"&gt;TITLE: Solaris Activium Search not showing last modified for Nevada customers

REPRO STEPS
1. Open Solaris Activium
2. Choose Menu &amp;gt; Search &amp;gt; Customer Search
3. Enter last name &amp;quot;Calypso&amp;quot;, first name &amp;quot;Bernard&amp;quot; and Search. Note she lives in Nevada.

Expected: A last modified date within the last few years
Actual: 0000-00-00

4. Enter last name &amp;quot;Chattergee&amp;quot; first name &amp;quot;Parag&amp;quot; and Search. Note he lives in Maine.

Actual: 2019-03-24

[screen shot]

MORE INFORMATION
They're only seeing this happen with customers who are in Nevada, but 
haven't tested all states.

ACCEPTANCE CRITERIA
(optional if obvious from the bug.)

Last modified date is shown for customers in all states.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What helps the person who opens the bug?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which system/app is involved?&lt;/li&gt;
&lt;li&gt;What are the exact steps the user performed?&lt;/li&gt;
&lt;li&gt;What was expected? What was actually seen?&lt;/li&gt;
&lt;li&gt;Sometimes a screen shot helps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;quot;Exact steps the user performed&amp;quot; is important. Often someone familiar with the application will try to reproduce the problem but using different steps, leading to &amp;quot;I can't reproduce&amp;quot; confusion.&lt;/p&gt;
&lt;p&gt;Note that while the user might consider the bug fixed if Nevada customers show last modified, the developer should have realized other states could be affected, leading to the more thorough acceptance criteria.&lt;/p&gt;
&lt;h2 id="stories"&gt;Stories&lt;/h2&gt;
&lt;p&gt;Stories, aka &amp;quot;user stories,&amp;quot; are used for planning. They should contain the least detail necessary to understand what the story's about and how to know it's done. They promote conversation. A story will likely change as it gets closer to release.&lt;/p&gt;
&lt;p&gt;There are several techniques to help define the story's value. A common one is the template &amp;quot;As a [Role], I [need/want], because [value]. Here's an example.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-text"&gt;TITLE: Implement Solaris Activium login reset 

VALUE
As a User, if I've forgotten my password I want a 
way to easily reset it so I can quickly get back to work.

MORE INFORMATION
Today, if a user forgets her password she has to submit a support 
ticket. Reviewing the last six months of help desk data, it takes 
an average of four hours for the password to be reset. These users 
often have deadline-based work, so those delays have a serious cost.

DEVELOPER NOTES
[jj] I think we can do this using the standard forgot password pattern.

ACCEPTANCE CRITERIA
The new flow is

*   User clicks &amp;quot;forgot password&amp;quot; on login page.
*   User enters email address and submits.
*   Email arrives in under a minute with link to reset.
*   Link opens a page to enter the new password twice. Password is validated.
*   After submitting valid password, user is immediately taken into app.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key elements above are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We know who, what, and why, stated as simply as possible&lt;/li&gt;
&lt;li&gt;We understand the business value, probably a result of discussion with the user and developers&lt;/li&gt;
&lt;li&gt;Developers can capture key discussion points.&lt;/li&gt;
&lt;li&gt;The story is testable, and the test is simple.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="wrap-up"&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;Hopefully this is useful. What both bugs and stories boil down to are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What are we trying to do?&lt;/li&gt;
&lt;li&gt;Is it clear to everyone?&lt;/li&gt;
&lt;li&gt;How will we know it's done?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Concise, clear sentences make a big difference. This all takes practice but pays for itself quickly.&lt;/p&gt;
</description>
      <pubDate>Thu, 28 Dec 2023 18:40:39 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/better_bugs_and_stories</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/better_bugs_and_stories</guid>
    </item>
    <item>
      <title>One Sheet Summary: Art of Agile Development - Planning</title>
      <description>&lt;p&gt;I make these to post on my wall and help me learn the subject. Be sure to read the book!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.softwaremeadows.com/well-being"&gt;All One Sheet Summaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Art-Agile-Development-James-Shore-ebook/dp/B09JL2JW4V"&gt;Buy the book on Amazon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;This summary is &lt;em&gt;only&lt;/em&gt; for the chapters on planning! And it isn't at all complete.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://www.softwaremeadows.com/posts/one_sheet_summary_art_of_agile_development_-_planning/art-of-agile-development-planning.pdf"&gt;Download the PDF Version&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/one_sheet_summary_art_of_agile_development_-_planning/art-of-agile-development-planning.png" alt="" /&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 26 Nov 2023 15:49:11 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/one_sheet_summary_art_of_agile_development_-_planning</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/one_sheet_summary_art_of_agile_development_-_planning</guid>
    </item>
    <item>
      <title>.NET Framework vs Core Environment Configuration</title>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-source-code"&gt;The Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-crucial-difference"&gt;The Crucial Difference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#whats-in-store"&gt;What's In Store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#brief-history"&gt;Brief History&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#why-run-time-configuration-matters-build-once-deploy-to-many"&gt;Why Run-Time Configuration Matters: Build Once, Deploy To Many&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#show-me-the-code"&gt;Show Me the Code!&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#database"&gt;Database&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#net-framework-version"&gt;.NET Framework Version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#netcore-version"&gt;.NET/Core Version&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#time-out-whats-with-developmentshared-and-how-does-all-this-work"&gt;Time Out! What's With DevelopmentShared? And How Does All This Work?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#proving-how-it-works"&gt;Proving How It Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#wrap-up"&gt;Wrap Up&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2025&lt;/strong&gt;&lt;br /&gt;
This article was intended to simply compare Framework and Core's default configuration approaches. However, reader Phil Ashby (thanks, Phil!) asked me to point out that Core (now just &amp;quot;.NET&amp;quot;)-style configuration can be used in Framework. There are two approaches.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ben Foster showed in 2016 how to use Core-style configs in Framework. I've used this approach myself. &lt;a href="https://benfoster.io/blog/net-core-configuration-legacy-projects/"&gt;Using .NET Core Configuration with legacy projects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Unknown to me until Phil pointed it out, Microsoft included native support for ConfigurationBuilder starting in 2017 with .NET Framework 4.7.1. I haven't read this article, but it seems like a better solution.  &lt;a href="https://learn.microsoft.com/en-us/aspnet/config-builder"&gt;Configuration builders for ASP.NET&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id="the-source-code"&gt;The Source Code&lt;/h2&gt;
&lt;p&gt;Code is found at:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/bladewolf55/ConfigDemo"&gt;https://github.com/bladewolf55/ConfigDemo&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="the-crucial-difference"&gt;The Crucial Difference&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;.NET Framework&lt;/strong&gt; applies environment configurations at &lt;strong&gt;build time&lt;/strong&gt;, transforming environment-specific files to create a single configuration file for the deployed application. The application &lt;em&gt;knows&lt;/em&gt; what environment it's supposed to be in, regardless of where it's deployed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;.NET/Core&lt;/strong&gt; applies environment configurations at &lt;strong&gt;run time&lt;/strong&gt;, using a specific environment variable, and can consume many configuration sources. The application &lt;em&gt;asks&lt;/em&gt; what environment it's deployed in.&lt;/p&gt;
&lt;h2 id="whats-in-store"&gt;What's In Store&lt;/h2&gt;
&lt;p&gt;To show how Framework and Core differ, I'll show two ASP.NET MVC apps that do the same thing using both configuration strategies.&lt;/p&gt;
&lt;h2 id="brief-history"&gt;Brief History&lt;/h2&gt;
&lt;p&gt;.NET's configuration strategy has a &lt;a href="https://grammarist.com/idiom/checkered-past-and-chequered-past/"&gt;checkered past&lt;/a&gt;. The .NET Framework depends on a single &lt;code&gt;web.config&lt;/code&gt; or &lt;code&gt;app.config&lt;/code&gt;&lt;a id="fnref:1" href="#fn:1" class="footnote-ref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. This is a hard dependency, meaning the file &lt;em&gt;must&lt;/em&gt; exist. There's no way to construct a configuration in memory, and if you want to change a configuration value you have to save to the config file.&lt;/p&gt;
&lt;p&gt;Over time, Microsoft tried various ways to allow changed the config file. The most common is arguably &lt;a href="https://learn.microsoft.com/en-us/aspnet/web-forms/overview/deployment/visual-studio-web-deployment/web-config-transformations"&gt;XML Transforms&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a new build configuration such as &amp;quot;Staging&amp;quot;&lt;/li&gt;
&lt;li&gt;Add the corresponding config file, &lt;code&gt;web.Staging.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Write transformations that update the base &lt;code&gt;web.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Apply those transformations when publishing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are several problems with this approach.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It conflates &lt;em&gt;build configuration&lt;/em&gt; with &lt;em&gt;environment configuration&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;It's build-time, as noted above.&lt;/li&gt;
&lt;li&gt;By design, transformations can &lt;em&gt;not&lt;/em&gt; be applied during development. You don't run the app in Visual Studio using the Staging configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last item was a sticking point for developers. Whether we shouldn't be running other than locally, we often need to. So, developers found various, non-supported ways to handle this. The most common is using a pre-build target to apply the transform.&lt;/p&gt;
&lt;p&gt;This led to yet another problem: the &lt;code&gt;web.config&lt;/code&gt; file kept changing and, with the rise of version control, was either accidentally checked in or had to be undone. There are some &lt;a href="https://github.com/bladewolf55/DeftConfig"&gt;clever ways to manage that&lt;/a&gt;, but they're fundamentally workarounds.&lt;/p&gt;
&lt;p&gt;Microsoft pretty much fixed all these problems in .NET Core. It was clear that developers needed to be able to consume environment-based configurations from arbitrary sources during run time.&lt;/p&gt;
&lt;p&gt;In .NET/Core, the build configuration (Debug, Release) are separate from environment configurations. Build configurations determine things like assembly names, optimization settings, and whether you can debug.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I want to be able to Debug in any environment!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No matter the source, all environment configurations must be key-value pairs. A simple way to understand environment configurations is also a simple, supported case: when the application runs, it reads all its configuration from system environment variables.&lt;/p&gt;
&lt;h2 id="why-run-time-configuration-matters-build-once-deploy-to-many"&gt;Why Run-Time Configuration Matters: Build Once, Deploy To Many&lt;/h2&gt;
&lt;p&gt;Quick quiz: if I build the same .NET Framework code using three different transform files, are they all the same or different?&lt;/p&gt;
&lt;p&gt;It's tempting to say, &amp;quot;Well, the code is the same, just the configs are different.&amp;quot; But that's technically false. They are three different binaries. The code, in some way, &lt;em&gt;could&lt;/em&gt; be different. This breaks a principle of continuous deployment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Build once, deploy to many&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We want to have one build artifact which we then deploy to any environment. This way, we &lt;em&gt;know&lt;/em&gt; the code is the same, and the only difference is the environment. We also save considerable time in our CI/CD process.&lt;/p&gt;
&lt;h2 id="show-me-the-code"&gt;Show Me the Code!&lt;/h2&gt;
&lt;p&gt;Our web site does just a couple of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Display an environment-based setting called TestKey&lt;/li&gt;
&lt;li&gt;Display a customer from the environment's database&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="database"&gt;Database&lt;/h3&gt;
&lt;p&gt;The app assumes using a SQL Server; modify to your needs. Here's a script for creating the database, tables, and data.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;use master
go
create database ConfigLocal
go

use ConfigLocal
go
create table Customers (
	CustomerId int primary key identity,
	Name varchar(max)
)

insert Customers(Name) values ('Local Louise')
select * from Customers
------------------------------------------------------

use master
go
create database ConfigDevelopmentShared
go

use ConfigDevelopmentShared
go
create table Customers (
	CustomerId int primary key identity,
	Name varchar(max)
)

insert Customers(Name) values ('Development Shared Dagmar')
select * from Customers
------------------------------------------------------

use master
go
create database ConfigStaging
go

use ConfigStaging
go
create table Customers (
	CustomerId int primary key identity,
	Name varchar(max)
)

insert Customers(Name) values ('Staging Sierra')
select * from Customers
------------------------------------------------------

use master
go
create database ConfigProduction
go

use ConfigProduction
go
create table Customers (
	CustomerId int primary key identity,
	Name varchar(max)
)

insert Customers(Name) values ('Production Pavla')
select * from Customers
------------------------------------------------------
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="net-framework-version"&gt;.NET Framework Version&lt;/h3&gt;
&lt;p&gt;We're going to fly through the coding part while calling out what matters.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create new ASP.NET Web Application (.NET Framework) project named &amp;quot;ConfigFramework&amp;quot;&lt;/li&gt;
&lt;li&gt;Choose MVC template&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;EntityFramework&lt;/code&gt; NuGet package&lt;/li&gt;
&lt;li&gt;Add Data folder
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;Customer.cs&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace ConfigFramework.Data
{
    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;ConfigDb.cs&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Data.Entity;

namespace ConfigFramework.Data
{
    public class ConfigDb: DbContext
    {
        public DbSet&amp;lt;Customer&amp;gt; Customers { get; set; }

        public ConfigDb(): base(&amp;quot;name=ConfigDb&amp;quot;) { }

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Models/CustomerViewModel.cs&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace ConfigFramework.Models
{
    public class CustomerViewModel
    {
        public int CustomerId { get; set; } 
        public string Name { get; set; }
        public string TestKey { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Replace code in &lt;code&gt;Controllers/HomeController.cs&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using ConfigFramework.Data;
using ConfigFramework.Models;
using System.Linq;
using System.Web.Mvc;

namespace ConfigFramework.Controllers
{
    public class HomeController : Controller
    {
        ConfigDb db = new ConfigDb();

        public ActionResult Index()
        {
            var customer = db.Customers.First();
            var model = new CustomerViewModel()
            {
                CustomerId = customer.CustomerId,
                Name = customer.Name,
                TestKey = Settings.TestKey
            };
            return View(model);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Replace code in &lt;code&gt;Views/Home/Index.cshtml&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@model ConfigFramework.Models.CustomerViewModel

&amp;lt;p&amp;gt;Customer:  @(Model.CustomerId.ToString() + &amp;quot; &amp;quot; + Model.Name)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Key: @(Model.TestKey)&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;How Do We Read the Environment Configuration?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add at root &lt;code&gt;Settings.cs&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Web.Configuration;

namespace ConfigFramework
{
    public static class Settings
    {
        public static string TestKey = WebConfigurationManager.AppSettings[&amp;quot;TestKey&amp;quot;];
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;web.config&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;!--&amp;gt; Add under configuration &amp;gt; configSections--&amp;gt;
&amp;lt;connectionStrings&amp;gt;
    &amp;lt;add name=&amp;quot;ConfigDb&amp;quot; connectionString=&amp;quot;Server=.;Database=ConfigLocal;Trusted_Connection=True&amp;quot; 
        providerName=&amp;quot;System.Data.SqlClient&amp;quot;/&amp;gt;
&amp;lt;/connectionStrings&amp;gt;

&amp;lt;!-- Add to appSettings&amp;gt; --&amp;gt;
&amp;lt;add key=&amp;quot;TestKey&amp;quot; value=&amp;quot;Local&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Open Build &amp;gt; Configuration Manager&lt;/li&gt;
&lt;li&gt;Drop down Active solution configuration &amp;gt; New&lt;/li&gt;
&lt;li&gt;Name = &amp;quot;Development&amp;quot;, Copy settings from = &amp;quot;Debug&amp;quot;, Create new project configurations = checked&lt;/li&gt;
&lt;li&gt;OK&lt;/li&gt;
&lt;li&gt;Do the same to create Staging and Production configurations&lt;/li&gt;
&lt;li&gt;If you don't immediately see the &lt;code&gt;Web.[environment].config&lt;/code&gt; files under &lt;code&gt;web.config&lt;/code&gt;
&lt;ol&gt;
&lt;li&gt;Right-click &lt;code&gt;web.config&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Choose Add config transform&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;Web.Debug.config&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;

&amp;lt;configuration xmlns:xdt=&amp;quot;http://schemas.microsoft.com/XML-Document-Transform&amp;quot;&amp;gt;
    &amp;lt;connectionStrings&amp;gt;
        &amp;lt;add name=&amp;quot;ConfigDb&amp;quot; connectionString=&amp;quot;Server=.;Database=ConfigLocal;Trusted_Connection=True&amp;quot; 
            providerName=&amp;quot;System.Data.SqlClient&amp;quot;
        xdt:Transform=&amp;quot;SetAttributes&amp;quot; xdt:Locator=&amp;quot;Match(name)&amp;quot;/&amp;gt;
    &amp;lt;/connectionStrings&amp;gt;
    &amp;lt;appSettings&amp;gt;
        &amp;lt;add key=&amp;quot;TestKey&amp;quot; value=&amp;quot;Local&amp;quot; xdt:Transform=&amp;quot;SetAttributes&amp;quot; xdt:Locator=&amp;quot;Match(key)&amp;quot;/&amp;gt;
    &amp;lt;/appSettings&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Similarly, update Development, Staging, and Release with these values:
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Development:&lt;/strong&gt; Database=ConfigDevelopmentShared, TestKey value=&amp;quot;Development&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Staging:&lt;/strong&gt; Database=ConfigStaging, TestKey value=&amp;quot;Staging&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production:&lt;/strong&gt; Database=ConfigProduction, TestKey value=&amp;quot;Production&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Using an external editor, modify &lt;code&gt;ConfigFramework.csproj&lt;/code&gt;. Add this task node at the bottom.
&lt;blockquote&gt;
&lt;p&gt;This is the magic sauce that allows running the app in Visual Studio using different configurations&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;Target Name=&amp;quot;BeforeBuild&amp;quot;&amp;gt;
    &amp;lt;TransformXml Source=&amp;quot;Web.config&amp;quot; Transform=&amp;quot;Web.$(Configuration).config&amp;quot; Destination=&amp;quot;Web.config&amp;quot; /&amp;gt;
&amp;lt;/Target&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Run It&lt;/strong&gt;&lt;br /&gt;
Setting the configuration to Debug and pressing F5 should, at this point, open the web site and display something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-04-39.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;You might get a message about enabling debug. Go ahead and do that. We aren't going to disable debugging in our environment files, but in a real application we would.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-02-11.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Changing the configuration displays different data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Environments are linked to build configurations.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-06-34.png" alt="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Web site is run using one IIS Express setup, regardless of configuration.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-08-06.png" alt="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;.NET Framework has no dependency injection out of the box. So, we're using a global, static Settings file. This means unit testing depends on the unit testing project having a &lt;code&gt;web.config&lt;/code&gt; file that's configured appropriately rather than injecting configurations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While it's possible to get settings from other sources (such as a database), it's custom work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="netcore-version"&gt;.NET/Core Version&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;The steps here are very similar in .NET Core 3+ and .NET 5+. This code uses .NET 6 and includes improved C# language features such as file-scoped namespaces.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Create a new ASP.NET Core Web App (Model-View-Controller) project named &amp;quot;ConfigCore&amp;quot;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt; Be sure to use the Model-View-Controller template&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Microsoft.EntityFrameworkCore.SqlServer&lt;/code&gt; NuGet package&lt;/li&gt;
&lt;li&gt;Add Data folder
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;Customer.cs&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace ConfigFramework.Data;

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; } = string.Empty;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;ConfigDb.cs&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using Microsoft.EntityFrameworkCore;

namespace ConfigFramework.Data;

public class ConfigDb: DbContext
{
    public DbSet&amp;lt;Customer&amp;gt; Customers { get; set; }

    public ConfigDb(DbContextOptions options) : base(options) { }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;Models/CustomerViewModel.cs&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace ConfigFramework.Models;

public class CustomerViewModel
{
    public int CustomerId { get; set; } 
    public string Name { get; set; } = string.Empty;
    public string TestKey { get; set; } = string.Empty;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Replace code in &lt;code&gt;Controllers/HomeController.cs&lt;/code&gt;
&lt;blockquote&gt;
&lt;p&gt;There's more code, but we're also doing more with dependency injection&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using ConfigFramework.Data;
using ConfigFramework.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

namespace ConfigCore.Controllers;

public class HomeController : Controller
{
    readonly ILogger&amp;lt;HomeController&amp;gt; _logger;
    readonly ConfigDb db;
    readonly Settings settings;

    public HomeController(ILogger&amp;lt;HomeController&amp;gt; logger, ConfigDb db, IOptions&amp;lt;Settings&amp;gt; settings)
    {
        _logger = logger;
        this.db = db;
        this.settings = settings.Value;
    }

    public IActionResult Index()
    {
        var customer = db.Customers.First();
        var model = new CustomerViewModel()
        {
            CustomerId = customer.CustomerId,
            Name = customer.Name,
            TestKey = settings.TestKey
        };
        return View(model);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Replace code in &lt;code&gt;Views/Home/Index.cshtml&lt;/code&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;@model ConfigFramework.Models.CustomerViewModel

&amp;lt;p&amp;gt;Customer:  @(Model.CustomerId.ToString() + &amp;quot; &amp;quot; + Model.Name)&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;Key: @(Model.TestKey)&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;How Do We Read the Environment Configuration?&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here's where we see how very different Framework and Core are&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Add at root &lt;code&gt;Settings.cs&lt;/code&gt;
&lt;blockquote&gt;
&lt;p&gt;Note this does not directly read configurations. Properties get set later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;namespace ConfigCore;

public class Settings
{
    public const string AppSettings = &amp;quot;AppSettings&amp;quot;;

    public string TestKey { get; set; } = String.Empty;
}    
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;Program.cs&lt;/code&gt;
&lt;blockquote&gt;
&lt;p&gt;Set up the DbContext and configuration file dependency injection&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Add after builder.Services.AddControllersWithViews();
builder.Services.AddDbContext&amp;lt;ConfigDb&amp;gt;(options =&amp;gt; options.UseSqlServer(&amp;quot;name=ConnectionStrings:ConfigDb&amp;quot;));
builder.Services.Configure&amp;lt;Settings&amp;gt;(builder.Configuration.GetSection(Settings.AppSettings));
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Add a file named &lt;code&gt;appsettings.Development.json&lt;/code&gt;
&lt;blockquote&gt;
&lt;p&gt;The section names are arbritary, but we still have a supported convention of sections named
ConnectionStrings and AppSettings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
    &amp;quot;Logging&amp;quot;: {
        &amp;quot;LogLevel&amp;quot;: {
        &amp;quot;Default&amp;quot;: &amp;quot;Information&amp;quot;,
        &amp;quot;Microsoft.AspNetCore&amp;quot;: &amp;quot;Warning&amp;quot;
        }
    },
    &amp;quot;ConnectionStrings&amp;quot;: {
        &amp;quot;ConfigDb&amp;quot;: &amp;quot;Server=.;Database=ConfigLocal;Trusted_Connection=True;TrustServerCertificate=true;&amp;quot;
    },
    &amp;quot;AppSettings&amp;quot;: {
        &amp;quot;TestKey&amp;quot;: &amp;quot;Development&amp;quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Add the remaining files with these environment names:
&lt;blockquote&gt;
&lt;p&gt;These files are &lt;em&gt;one&lt;/em&gt; of several source that .NET checks for when configuring&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;DevelopmentShared:&lt;/strong&gt; Database=ConfigDevelopmentShared, TestKey value=&amp;quot;Development&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Staging:&lt;/strong&gt; Database=ConfigStaging, TestKey value=&amp;quot;Staging&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production:&lt;/strong&gt; Database=ConfigProduction, TestKey value=&amp;quot;Production&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;Properties/launchSettings.json&lt;/code&gt;. Replace the IIS Express entry with these new entries.
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;&amp;quot;IIS Express Development&amp;quot;: {
  &amp;quot;commandName&amp;quot;: &amp;quot;IISExpress&amp;quot;,
  &amp;quot;launchBrowser&amp;quot;: true,
  &amp;quot;environmentVariables&amp;quot;: {
    &amp;quot;ASPNETCORE_ENVIRONMENT&amp;quot;: &amp;quot;Development&amp;quot;
  }
},
&amp;quot;IIS Express Development Shared&amp;quot;: {
  &amp;quot;commandName&amp;quot;: &amp;quot;IISExpress&amp;quot;,
  &amp;quot;launchBrowser&amp;quot;: true,
  &amp;quot;environmentVariables&amp;quot;: {
    &amp;quot;ASPNETCORE_ENVIRONMENT&amp;quot;: &amp;quot;DevelopmentShared&amp;quot;
  }
},
&amp;quot;IIS Express Staging&amp;quot;: {
  &amp;quot;commandName&amp;quot;: &amp;quot;IISExpress&amp;quot;,
  &amp;quot;launchBrowser&amp;quot;: true,
  &amp;quot;environmentVariables&amp;quot;: {
    &amp;quot;ASPNETCORE_ENVIRONMENT&amp;quot;: &amp;quot;Staging&amp;quot;
  }
},
&amp;quot;IIS Express  Production&amp;quot;: {
  &amp;quot;commandName&amp;quot;: &amp;quot;IISExpress&amp;quot;,
  &amp;quot;launchBrowser&amp;quot;: true,
  &amp;quot;environmentVariables&amp;quot;: {
    &amp;quot;ASPNETCORE_ENVIRONMENT&amp;quot;: &amp;quot;Production&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Run It&lt;/strong&gt;&lt;br /&gt;
Keep the build configuration as Debug, choose the IIS Express Development runtime configuration and F5 to run.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-37-22.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;You should see this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-11-38-14.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Build configurations are not usually customized&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-12-06-35.png" alt="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IIS Express can start as other environments&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration/2023-10-15-12-08-01.png" alt="" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment is an environment variable, &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment settings come from many sources, including &lt;code&gt;appsettings.[Environment].json&lt;/code&gt; files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;launchSettings.json&lt;/code&gt; is used to set the environment variable for &lt;em&gt;local&lt;/em&gt; development.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;br /&gt;
It may not be obvious, but if you deployed the application to a web server running IIS and wanted it to run as Staging, you would &lt;em&gt;have&lt;/em&gt; to add/set the &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; to &amp;quot;Staging&amp;quot;. Without that, the app will run as Production by default.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="time-out-whats-with-developmentshared-and-how-does-all-this-work"&gt;Time Out! What's With DevelopmentShared? And How Does All This Work?&lt;/h2&gt;
&lt;p&gt;In .NET/Core&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WebApplication.CreateBuilder&lt;/code&gt; reads a bunch of configuration sources by default, in a specific order.&lt;/li&gt;
&lt;li&gt;The &amp;quot;Development&amp;quot; environment has special behaviors that you don't know about unless you read the documentation, which will catch you by surprise.&lt;/li&gt;
&lt;li&gt;&amp;quot;Development&amp;quot; is intended for local work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There's some problematic--but understandable--mental modeling at work here that I've seen over the years. Just as Microsoft conflated build and environment configurations, developers have conflated Debug and Development. .NET Framework accidentally encouraged developers to think of Debug as &amp;quot;local development.&amp;quot; Many teams have a shared development environment (shared web and database). So, they naturally added a Development configuration that meant &amp;quot;remote.&amp;quot;&lt;/p&gt;
&lt;p&gt;In .NET/Core, Debug has nothing to do with environment, and Development equals local. This is stated in the documentation, and is evident in code like this from &lt;code&gt;Program.cs&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler(&amp;quot;/Home/Error&amp;quot;);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Development is the environment where we'd be calling other services with local ports, such as &lt;code&gt;https://localhost:50334&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But more importantly, when the configuration is built up, if the &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; environment is &amp;quot;Development&amp;quot;, user secrets are read if they exist. This is important for keeping sensitive information secure.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-7.0#default-application-configuration-sources"&gt;Default application configuration sources&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don't like it, but as far as I can tell these hidden behaviors are only enabled if &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; is set to &amp;quot;Development&amp;quot;. Not &amp;quot;Dev&amp;quot;, and not any other user-defined value. You can, of course, easily customize the builder, but it's critical to know the default behaviors.&lt;/p&gt;
&lt;p&gt;Also, I prefer sticking with defaults when I can.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, that's why I added a DevelopmentShared environment. I would &lt;em&gt;assume&lt;/em&gt; that any secrets needed in a shared environment come from a shared source such as Azure Key Vault.&lt;/p&gt;
&lt;p&gt;How many configuration sources are looked up by default? Six, and in this order. The later sources will override values of the same keys in earlier sources.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fallback host configuration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;appsettings.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;appsettings.[Environment].json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;User secrets&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Command-line arguments&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="proving-how-it-works"&gt;Proving How It Works&lt;/h2&gt;
&lt;p&gt;As stated earlier, one goal of the new configuration approach is &amp;quot;build once, deploy to many,&amp;quot; meaning I should be able to control my application's settings without changing the appsettings files. Let's try that.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run using IIS Express Staging.&lt;/li&gt;
&lt;li&gt;You should see customer &amp;quot;Staging Sierra&amp;quot; and key &amp;quot;Staging&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We'll run the app using a different environment, similar to running in IIS. For convenience, we'll do this from the command line with in-process environment variables.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open PowerShell&lt;/li&gt;
&lt;li&gt;Run
&lt;pre&gt;&lt;code class="language-powershell"&gt;# cd [path/to/ConfigCore solution]
$Env:ASPNETCORE_ENVIRONMENT = &amp;quot;Production&amp;quot;
dotnet run --project ConfigCore --no-launch-profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;The site runs using the Kestral webhost. Open whatever URL is displayed, typically http://localhost:5000&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should see customer = &amp;quot;Pavla&amp;quot; and key = &amp;quot;Production&amp;quot;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Ctrl-C&lt;/code&gt; to stop the site.&lt;/li&gt;
&lt;li&gt;Run
&lt;pre&gt;&lt;code class="language-powershell"&gt;$Env:AppSettings__TestKey = &amp;quot;Blamo&amp;quot;
dotnet run --project ConfigCore --no-launch-profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Once running, refresh the page.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key should change to &amp;quot;Blamo.&amp;quot;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why is the environment variable name &lt;code&gt;AppSettings__TestKey&lt;/code&gt; with the double-underscore? That's a Microsoft convention that allows converting the key to a hierarchy of the form &amp;quot;AppSettings:TestKey&amp;quot;. In fact, the json file also converts to that format, as does any other configuration source. The double-underscore works with Linux environment variables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When you run using Visual Studio, &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; is usually set in launchSettings. But it doesn't have to be. If you delete the &lt;code&gt;environmentVariables&lt;/code&gt; key, the app will either run as Production (the default) or as whatever is set for &lt;code&gt;ASPNETCORE_ENVIRONMENT&lt;/code&gt; in the user profile or system environment variables.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Remember you have to close/reopen Visual Studio to see new environment variable changes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="wrap-up"&gt;Wrap Up&lt;/h2&gt;
&lt;p&gt;Microsoft fundamentally changed how configuration works in .NET/Core compared to Framework. They solved many problems and provided flexible and testable methods. The biggest barrier I've seen to using the new configuration strategies is understanding what changed and how they're intended to work.&lt;/p&gt;
&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Because, I guess, Microsoft believed two names were better than one. So far I haven't found an article on why they used two names.&lt;a href="#fnref:1" class="footnote-back-ref"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Sun, 15 Oct 2023 09:34:52 -0600</pubDate>
      <link>https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/framework_vs_core_environment_configuration</guid>
    </item>
    <item>
      <title>One Sheet Summary: Software Engineering at Google - Testing</title>
      <description>&lt;p&gt;I make these to post on my wall and help me learn the subject. Be sure to read the book!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.softwaremeadows.com/well-being"&gt;All One Sheet Summaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Software-Engineering-Google-Lessons-Programming-ebook/dp/B0859PF5HB"&gt;Buy the book on Amazon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;This summary is &lt;em&gt;only&lt;/em&gt; for the chapters on testing! And, it's kind of messy. You need to read those chapters yourself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://www.softwaremeadows.com/posts/one_sheet_summary-_engineering-at_google__testing/images/engineering-at_google__testing.pdf"&gt;Download the PDF Version&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/one_sheet_summary-_engineering-at_google__testing/images/engineering-at_google__testing.png" alt="" /&gt;&lt;/p&gt;
</description>
      <pubDate>Sat, 12 Aug 2023 12:30:00 -0600</pubDate>
      <link>https://www.softwaremeadows.com/posts/one_sheet_summary-_engineering-at_google__testing</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/one_sheet_summary-_engineering-at_google__testing</guid>
    </item>
    <item>
      <title>Getting Started With Software (and Business and Life) Skills - 2023</title>
      <description>&lt;p&gt;&lt;img src="https://www.softwaremeadows.com/posts/getting_started_with_software_(and_business_and_life)_skills_2023/images/slate.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contents&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#why-am-i-writing-this"&gt;Why Am I Writing This?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#principles-du-jour"&gt;Principles Du Jour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-big-hitters"&gt;The Big Hitters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#learning"&gt;Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#fufillment"&gt;Fufillment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#productivity"&gt;Productivity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#business"&gt;Business&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#communication-and-presentation"&gt;Communication and Presentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#programming-specific"&gt;Programming-Specific&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#appendix-a---skills-i-think-software-developers-need-to-cultivate"&gt;Appendix A - Skills (I Think) Software Developers Need to Cultivate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#appendix-b---everything-you-might-need-to-know-to-create-an-enterprise-level-web-application"&gt;Appendix B - Everything You Might Need to Know To Create an Enterprise-Level Web Application&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#user-interface"&gt;User Interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#web-service"&gt;Web Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#web-server-back-end"&gt;Web Server Back End&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#data-persistence"&gt;Data Persistence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#version-control"&gt;Version Control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#methodology"&gt;Methodology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#testing"&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#platforms"&gt;Platforms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#miscellaneous"&gt;Miscellaneous&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-am-i-writing-this"&gt;Why Am I Writing This?&lt;/h2&gt;
&lt;p&gt;I wrote my &lt;a href="https://www.softwaremeadows.com/posts/getting_started_with_software_(and_business_and_life)_skills/"&gt;first version of this article&lt;/a&gt; in 2018, inspired by a young violinist-turned-developer. This time I'm thinking about some colleagues who are already in the field and wondering what might help them in their careers.&lt;/p&gt;
&lt;p&gt;What interested me was how to answer a question: &lt;em&gt;What do I think a junior software engineer needs to know?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Most of what I wrote in 2018 holds today, so there's some copy/paste going on below, but I've asked, &amp;quot;What matters to me now?&amp;quot;&lt;/p&gt;
&lt;p&gt;The answer has almost nothing to do with programming. Oh, sure, I could list a whole bunch of programming resources that even I haven't read. But curious developers eventually find those. What I think, based on over twenty-five years of experience in the industry (plus fifteen years in retail, food service, and other jobs before that), is that a successful, fulfilled &lt;strong&gt;person&lt;/strong&gt; needs to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Learn how to learn&lt;/li&gt;
&lt;li&gt;Know what it means to know something&lt;/li&gt;
&lt;li&gt;Communicate well in good and bad situations&lt;/li&gt;
&lt;li&gt;Find a job that aligns with one's purpose and values&lt;/li&gt;
&lt;li&gt;Savor life&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Are there skills specific to being a programmer? Sure. See Appendix A. But I think they don't matter without the basic human stuff. You're not going to find (much) fluff below, because one of my mottos is &amp;quot;show me the science.&amp;quot;&lt;/p&gt;
&lt;p&gt;So . . . here we go!&lt;/p&gt;
&lt;h2 id="principles-du-jour"&gt;Principles Du Jour&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Develop skills. Knowledge will come.&lt;/li&gt;
&lt;li&gt;Little habits add up.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h2 id="the-big-hitters"&gt;The Big Hitters&lt;/h2&gt;
&lt;p&gt;Last time I chose just three books/articles. I can't do that this time. These are my current top recommendations.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Good-Habits-Bad-Science-Positive-ebook/dp/B07PKGTDMB"&gt;Good Habits, Bad Habits&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are other good books on habit-forming out there, but Dr Wood is a premier researcher on the subject. When about 40% of your life is habits, it's a good idea to turn them to your benefit.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Leadership-Language-Hidden-Power-Say-ebook/dp/B07L2KL5XV"&gt;Leadership is Language&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Combining current science with compelling, practical stories, submarine captain David Marquette explains how and why he transformed himself from a command-and-coerce leadership style to collaborate-and-improve. It was literally a matter of life or death. I recommend this book all the time.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Crucial-Conversations-Tools-Talking-Stakes-ebook/dp/B093Y3N433"&gt;Crucial Conversations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I think the essence of this book is, &amp;quot;Be 100% honest, 100% respectful, and keep it safe.&amp;quot; I've always been good at the first one . . . not so good at the other two. This book helped me improve my relationships.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Drive-Surprising-Truth-About-Motivates-ebook/dp/B004P1JDJO"&gt;Drive: The Surprising Truth About What Motivates Us&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Daniel Pink delivers one of the most important books I've read on motivation.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity-ebook/dp/B00KWG9M2E"&gt;Getting Things Done&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've used, adapted, and revisited GTD for over ten years. It's helped me tremendously. In my view, Allen's crucial messages are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get everything you want to do out of your head and into a &lt;em&gt;system you trust&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The purpose of a personal productivity system is to &lt;em&gt;reduce stress&lt;/em&gt;, not get more done.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href="https://www.careerlab.com/"&gt;Career Lab&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a departure from the above books. Are you trying to figure out what your career should be like? Or considering transitioning? Bill is a consultant, and if you can afford to you should pay him for his expertise and experience. For those who can't, he's provided a real treasure: his entire methodology is on his web site. I took a month to work through all his exercises and they really focused me on my values. Hard work, worth it.&lt;/p&gt;
&lt;h2 id="learning"&gt;Learning&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hbr.org/2007/07/the-making-of-an-expert"&gt;The Making of an Expert - Harvard Business Review&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flattland.com/posts/rapid_learning_-_9_articles_reviewed/"&gt;Rapid Learning - 9 Articles Reviewed&lt;/a&gt; &lt;strong&gt;&amp;lt;= my article&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fufillment"&gt;Fufillment&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.coursera.org/learn/the-science-of-well-being#"&gt;The Science of Well-Being | Coursera&lt;/a&gt; &lt;strong&gt;&amp;lt;= Fantastic! Thank you Dr Santos!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.viacharacter.org/www/Character-Strengths-Survey#"&gt;Character Strengths Survey: VIA Character&lt;/a&gt; &lt;strong&gt;&amp;lt;= one of the board members of VIA is Dr Martin Seligman, author of the books &lt;em&gt;Learned Optimism&lt;/em&gt; and &lt;em&gt;Authentic Happiness&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hminnovations.org/meditation-app"&gt;Healthy Minds App&lt;/a&gt; &lt;strong&gt;&amp;lt;= the only app on the lists. It's meditation, but also work, and also science!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="productivity"&gt;Productivity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Habits-Highly-Effective-People-Powerful-ebook/dp/B07WF972WK"&gt;7 Habits of Highly Effective People&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ji5_MqicxSo"&gt;Randy Pausch, The Last Lecture: Achieving Your Childhood Dreams - YouTube&lt;/a&gt; &lt;strong&gt;&amp;lt;= This was literally Dr Pausch's last lecture: he had cancer and a few months to live. Watch this to learn about being human.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Last-Lecture-Randy-Pausch-ebook/dp/B00139VU7E/"&gt;The Last Lecture -- Randy Pausch&lt;/a&gt; &lt;strong&gt;&amp;lt;= and read his book, too&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.softwaremeadows.com/posts/the_50-10_time_box_revising_pomodoro_for_software_development/"&gt;The 50-10 Time Box - Revising Pomodoro For Software Development&lt;/a&gt; &lt;strong&gt;&amp;lt;= my article&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="business"&gt;Business&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Measure-What-Matters-Google-Foundation-ebook/dp/B078FZ9SYB"&gt;Measure What Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nytimes.com/2016/02/28/magazine/what-google-learned-from-its-quest-to-build-the-perfect-team.html?_r=0"&gt;What Google Learned From Its Quest to Build the Perfect Team - The New York Times&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Business Plans&lt;/em&gt;&lt;br /&gt;
In my 2018 meeting, I was asked about business plans. I have limited experience writing a business plan, and I knew there'd be plenty of resources available online, such as those listed.&lt;/p&gt;
&lt;p&gt;Here's my opinion: unless you're seeking investors or a loan, the point of working on a business plan is to get you thinking, and to prepare for conversations with other professionals. This quote sums that up nicely.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;In preparing for battle I have always found that plans are useless, but planning is indispensable.&amp;quot; --Dwight D. Eisenhower&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.entrepreneur.com/article/281416"&gt;7 Steps to a Perfectly Written Business Plan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.businessknowhow.com/startup/businessplanning.htm"&gt;Business Plan Basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://articles.bplans.com/a-standard-business-plan-outline/"&gt;A Standard Business Plan Outline [Updated for 2018] | Bplans&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="communication-and-presentation"&gt;Communication and Presentation&lt;/h2&gt;
&lt;p&gt;Despite not listing any resources below, communication and presentation might be the &lt;em&gt;most&lt;/em&gt; important area any person can work on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interpersonal (Toastmasters, acting, practice presentations and record them).&lt;/li&gt;
&lt;li&gt;Simple courtesies: thank-you notes, formalities, emails.&lt;/li&gt;
&lt;li&gt;Follow through. Under-promise, over-deliver.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="programming-specific"&gt;Programming-Specific&lt;/h2&gt;
&lt;p&gt;Developing a software engineer curriculum is &lt;em&gt;hard&lt;/em&gt;, because there are about twenty subject areas. Start with what interests you, the rest will follow. &lt;em&gt;See &lt;a href="#appendix-b-everything-you-might-need-to-know-to-create-an-enterprise-level-web-application"&gt;Appendix B&lt;/a&gt; for an overwhelming list of what it can take to write a single, professional web application&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn about the fundamentals of programming and what's physically happening in the computer. A lower-level language like C++ helps with this, but don't learn the language, just the concepts. A partial list: what are . . .
&lt;ul&gt;
&lt;li&gt;Memory addresses&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Collections (such as linked lists and dictionaries)&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Loops&lt;/li&gt;
&lt;li&gt;Iterating and Enumerating&lt;/li&gt;
&lt;li&gt;Objects&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://agilemanifesto.org/"&gt;Manifesto for Agile Software Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://agilemanifesto.org/principles.html"&gt;Principles Behind the Agile Manifesto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fundamentals of eXtreme Programming/Scrum/Kanban/Lean. Try one (I like Kanban).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Accelerate-Software-Performing-Technology-Organizations-ebook/dp/B07B9F83WM/"&gt;Accelerate: The Science of Lean Software and DevOps&lt;/a&gt; &lt;strong&gt;&amp;lt;= One of the most important books on development practices today&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Art-Agile-Development-James-Shore-ebook/dp/B09JL2JW4V"&gt;The Art of Agile Development&lt;/a&gt; &lt;strong&gt;&amp;lt;= I trust James Shore's approach and understanding. It's not faux-Agile.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Podcast: &lt;a href="https://developertea.com/"&gt;Developer Tea&lt;/a&gt; &lt;strong&gt;&amp;lt;= Ten minute programs about improvement. I love this show.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Find the [your-language/platform-here] version of &lt;a href="https://www.alvinashcraft.com/"&gt;Morning Dew - Daily links for Windows and .NET developers.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Automate repetitive tasks&lt;/li&gt;
&lt;li&gt;Systematize administrative routines (tasks, calendar) (plain text is great). That is, make it easy to practice GTD or whatever method you choose.&lt;/li&gt;
&lt;li&gt;Tools are an aid, not an end. Learn your tools, but don't become a tool junkie.&lt;/li&gt;
&lt;li&gt;Be ruthless about maintainability (and maintenance)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="appendix-a-skills-i-think-software-developers-need-to-cultivate"&gt;Appendix A - Skills (I Think) Software Developers Need to Cultivate&lt;/h2&gt;
&lt;p&gt;Sorry, I know I'm all about evidence, but I haven't researched this. Here is my opinion on skills/traits specific to software development.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Puzzle/problem solving&lt;/strong&gt;. Programmers have to be able to solve problems. In my opinion, the very best are interested in how to solve problems multiple ways, and never think they have the only right answer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tenacity&lt;/strong&gt;. Programmers are faced with tasks that take hours, days, or months to accomplish. They face problems that often don't have obvious or simple answers. They have to keep after it. And they're sitting in a chair, which is completely unhealthy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstract thinking&lt;/strong&gt;. This is a fact, because software is an abstraction. Programming is one of the few fields where what you see is &lt;em&gt;not&lt;/em&gt; what you get. Developers stare at words that are instructions later interpreted to produce something someone sees. It's not natural or easy. Imagine your job was to describe, in braille, how to write an English document that explained all the steps to painting Van Gogh's &lt;em&gt;Starry Night&lt;/em&gt;, and if the painting doesn't look right the braille book doesn't open.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communicating complexity simply&lt;/strong&gt;. On a scale of 1 to 10, most programmers reach about a 2 on this. A program is like a night at the theater (or movie, or symphony). You, the audience (manager, user) have no idea what it took to create. It looks simple, it must have been. Developers, especially seniors, must be able to explain how something seemingly simple will work, and why it will take a year to do it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Understand everyone else's job&lt;/strong&gt;. Scale of 1 to 10: most programmers are a 3 (but think they're a 7). This really depends on what area of software you're working on, but it's rare for programmers to work on software they use. A consulting shop will work for all kinds of clients. In addition to the gobs of information about their own jobs, programmers often need to understand essentials of diverse fields. I, for example, have needed to rapidly learn about: accounting, manufacturing, aircraft maintenance, and radio-nucleotide decay, to name a few.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research&lt;/strong&gt;. Programmers need to be able to figure out how to query the internet for information, then they have to evaluate the dozen different answers and determine which, if any, fit the issue at hand. I spend as much time researching as I do programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="appendix-b-everything-you-might-need-to-know-to-create-an-enterprise-level-web-application"&gt;Appendix B - Everything You Might Need to Know To Create an Enterprise-Level Web Application&lt;/h2&gt;
&lt;p&gt;Don't worry, I promise you'll get there. And most of the time, you'll work with other people who know the stuff you don't.&lt;/p&gt;
&lt;p&gt;These lists are heavily weighted toward the Microsoft development stack, because that's what I know.&lt;/p&gt;
&lt;h3 id="user-interface"&gt;User Interface&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;IDEs: Visual Studio, Visual Studio Code, text editor(s),&lt;/li&gt;
&lt;li&gt;Design Prototyping: Balsamiq&lt;/li&gt;
&lt;li&gt;Design Images: Photoshop/GIMP/Paint.Net, Illustrator/Inkscape&lt;/li&gt;
&lt;li&gt;Image Formats: JPG, PNG, GIF, SVG&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;CSS&lt;/li&gt;
&lt;li&gt;CSS preprocessors (Less, Sass)&lt;/li&gt;
&lt;li&gt;Dynamic web page languages and templates: WebForms, Razor forms, Blazor&lt;/li&gt;
&lt;li&gt;Javascript language&lt;/li&gt;
&lt;li&gt;Javascript server-side development: Node&lt;/li&gt;
&lt;li&gt;Javascript frameworks: Angular, React, JQuery&lt;/li&gt;
&lt;li&gt;Javascript style checking: ESLint&lt;/li&gt;
&lt;li&gt;Javascript Unit Testing: Jasmine, Karma, Angular-mocks&lt;/li&gt;
&lt;li&gt;Package Managers: NPM&lt;/li&gt;
&lt;li&gt;Integration Testing: Selenium&lt;/li&gt;
&lt;li&gt;Authentication: OAuth, OpenID&lt;/li&gt;
&lt;li&gt;Security: CORS, Cross-site injection&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Other tools: Chrome F12, Fiddler&lt;/li&gt;
&lt;li&gt;Concepts: page layout, colors, user experience, accessibility (handicapped), minification, HTTP protocol, MVVM, MVC (specifically views), REST, mocking, dependency injection&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="web-service"&gt;Web Service&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;IDEs: Visual Studio, text editor(s)&lt;/li&gt;
&lt;li&gt;Diff and Merge: KDiff3, WinMerge, Beyond Compare&lt;/li&gt;
&lt;li&gt;Languages: C#, VB.Net&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;REST&lt;/li&gt;
&lt;li&gt;WebAPI (models and controllers)&lt;/li&gt;
&lt;li&gt;SOAP&lt;/li&gt;
&lt;li&gt;Package Managers: NPM, NuGet&lt;/li&gt;
&lt;li&gt;Unit Testing: MSTest, xUnit, NSubstitute&lt;/li&gt;
&lt;li&gt;Dependency Injection/Inversion of Control: .NET Core dependency framework&lt;/li&gt;
&lt;li&gt;Authentication: OAuth, OpenID&lt;/li&gt;
&lt;li&gt;Security: Cross-site injection, SQL Injection,&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Other tools: Fiddler, PowerShell&lt;/li&gt;
&lt;li&gt;Logging: NLog, Elastic Search, Application Insights&lt;/li&gt;
&lt;li&gt;Architecture: Onion, distributed, (micro)service-oriented&lt;/li&gt;
&lt;li&gt;Concepts: networking, routing, view models&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="web-server-back-end"&gt;Web Server Back End&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;IDEs: Visual Studio, text editor(s)&lt;/li&gt;
&lt;li&gt;Diff and Merge: KDiff3, WinMerge, Beyond Compare&lt;/li&gt;
&lt;li&gt;Languages: C#, VB.NET&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;MVC (specifically models and controllers)&lt;/li&gt;
&lt;li&gt;ORM: Entity Framework, NHibernate, Active Record&lt;/li&gt;
&lt;li&gt;Architecture (layers, onion,...)&lt;/li&gt;
&lt;li&gt;Web Servers: IIS, Apache, Node.js&lt;/li&gt;
&lt;li&gt;Javascript server-side development: Node&lt;/li&gt;
&lt;li&gt;Package Managers: NPM, NuGet&lt;/li&gt;
&lt;li&gt;Unit Testing: MSTest, xUnit, NSubstitute&lt;/li&gt;
&lt;li&gt;Dependency Injection/Inversion of Control: .NET Core dependency framework&lt;/li&gt;
&lt;li&gt;Authentication: OAuth, OpenID&lt;/li&gt;
&lt;li&gt;Security: Cross-site injection, SQL Injection,&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Logging: NLog, Elastic Search, Application Insights&lt;/li&gt;
&lt;li&gt;Architecture: Onion, distributed, (micro)service-oriented&lt;/li&gt;
&lt;li&gt;Concepts: networking, routing, view models&lt;/li&gt;
&lt;li&gt;Other tools: PowerShell&lt;/li&gt;
&lt;li&gt;Concepts: networking, routing, data modeling, business entity modeling, business rules, test-driven development, REST, mocking, dependency injection&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="data-persistence"&gt;Data Persistence&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;IDEs: SQL Server Management Studio, LINQPad, text editor(s)&lt;/li&gt;
&lt;li&gt;Languages: T-SQL, LINQ,&lt;/li&gt;
&lt;li&gt;Databases: SQL (Microsoft, Oracle), No-SQL (MongoDB, Redis)&lt;/li&gt;
&lt;li&gt;ORM: Entity Framework, NHibernate, Active Record&lt;/li&gt;
&lt;li&gt;Authentication (network)&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Other tools: Redgate, PowerShell&lt;/li&gt;
&lt;li&gt;Concepts: database design, data modeling, relational design&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="version-control"&gt;Version Control&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Source control systems: Git&lt;/li&gt;
&lt;li&gt;IDEs: command line, Visual Studio extensions, VS Code extensions, Git Kraken&lt;/li&gt;
&lt;li&gt;Other tools: GitHub, BitBucket, GitLab&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="methodology"&gt;Methodology&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Development Approaches: Agile, Waterfall, Lean&lt;/li&gt;
&lt;li&gt;Agile methodologies: Scrum, Kanban, eXtreme Programming&lt;/li&gt;
&lt;li&gt;Project/Task Management: Kanban/Scrub board, Azure DevOps&lt;/li&gt;
&lt;li&gt;Issue Tracking: Azure DevOps, GitHub, GitLab, BitBucket&lt;/li&gt;
&lt;li&gt;Architecture Approaches: N-Tier, Domain-Driven Design, Onion, Service-Oriented, Microservice, Distributed&lt;/li&gt;
&lt;li&gt;Messaging: service bugs, message queues&lt;/li&gt;
&lt;li&gt;Continuous Integration/Release: Azure DevOps Pipelines (YAML-based), Infrastructure-As-Code&lt;/li&gt;
&lt;li&gt;Concepts: organization, teamwork, communication, creativity, problem-solving, estimating&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="testing"&gt;Testing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Unit: Javascript, web, back-end, mocking, automated&lt;/li&gt;
&lt;li&gt;Integration&lt;/li&gt;
&lt;li&gt;Acceptance&lt;/li&gt;
&lt;li&gt;Exploratory&lt;/li&gt;
&lt;li&gt;My current favorite unit testing stack:
&lt;ul&gt;
&lt;li&gt;xUnit&lt;/li&gt;
&lt;li&gt;NSubstitute&lt;/li&gt;
&lt;li&gt;FluentAssertions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="platforms"&gt;Platforms&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Cloud Hosting: Azure, Amazon Web Services, Google Cloud&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="miscellaneous"&gt;Miscellaneous&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft Office (Word, Excel, PowerPoint)&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Stack Overflow web site for researching problems&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Sat, 21 Jan 2023 09:00:00 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/getting_started_with_software_(and_business_and_life)_skills_2023</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/getting_started_with_software_(and_business_and_life)_skills_2023</guid>
    </item>
    <item>
      <title>Why I Don't Use Dark Mode - Science!</title>
      <description>&lt;p&gt;A colleague asked my thoughts about dark vs light modes, so here's the quick answer I gave him. It doesn't have my usual list of references, you can do your own research this time!&lt;/p&gt;
&lt;p&gt;Generally speaking, our eyes work less when reading dark text on a light background. When trying to read light next on a dark background, our pupils dilate, resulting in the text being fuzzier and both our eyes and brain working harder to read.&lt;/p&gt;
&lt;p&gt;There are exceptions you might see, such as older footage of air traffic control at night where the text is orange. But that's only text, not our graphics-heavy displays, and those orange (or green) choices were based on some science.&lt;/p&gt;
&lt;p&gt;Reducing screen brightness and color range may--probably does?--help reduce eyestrain in a dark environment. I haven't checked the research on that.&lt;/p&gt;
&lt;p&gt;Personally, I generally configure my computer/apps this way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a dark, non-distracting wallpaper (often a single color)&lt;/li&gt;
&lt;li&gt;If the app allows, use darker backgrounds for &amp;quot;background&amp;quot; areas.&lt;/li&gt;
&lt;li&gt;Use dark text on light backgrounds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use &lt;a href="https://justgetflux.com/"&gt;f.lux&lt;/a&gt; to manage my screen color/brightness. I find it better than Windows's built-in utility. I've adjusted it to what's comfortable for both day and night (do enable the extended color range). If I ever have to edit images at night, I need to disable f.lux if I care about color accuracy.&lt;/p&gt;
&lt;p&gt;One other concern I have--my opinion, not researched--is that our brains are evolved to be more afraid in dark environments and light text on a dark background might be triggering my sympathetic nervous system (fight/flight). I don't want any more stress in my life than needed.&lt;/p&gt;
&lt;p&gt;Dark modes &lt;em&gt;look&lt;/em&gt; cool, but I abandoned them quite a while ago based on the evidence as I understand it.&lt;/p&gt;
&lt;p&gt;I take it back: here's one reference.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.wired.co.uk/article/dark-mode-chrome-android-ios-science"&gt;Dark mode isn't as good for your eyes as you believe | WIRED UK&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 14 Dec 2022 09:31:43 -0700</pubDate>
      <link>https://www.softwaremeadows.com/posts/why_i_dont_use_dark_mode_-_science</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/why_i_dont_use_dark_mode_-_science</guid>
    </item>
    <item>
      <title>The Mythical Man-Month: A Short Review of the Essential Essays</title>
      <description>&lt;p&gt;A book club I belong to agreed to read Frederick P. Brooks's seminal essay collection &lt;a href="https://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959"&gt;The Mythical Man-Month&lt;/a&gt;. We somewhat abandoned the book, finding a lot of it hard to relate to because we don't write operating systems for specific hardware in a time-sharing environment. Plus there's no audio version, which is how some of the members like to read. I promised the group I'd read some specific essays because I wanted to, and report back.&lt;/p&gt;
&lt;p&gt;I've made good on that promise. I think the following are worth reading for a few reasons, which I touch on below. Something not clear initially is when the essays were written. I think that's important for the context, so include what the dates seem to be.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Tar Pit (1975)&lt;/em&gt;&lt;br /&gt;
While not essential, this short essay nicely discusses what makes software hard and enjoyable. I think most of what Brooks says holds true today.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Mythical Man-Month (1975)&lt;/em&gt;&lt;br /&gt;
For the title essay, the thesis has held up; adding developers (to a late project) doesn't reduce time-to-completion. Communication is a core challenge of software shops. When new developers are added, there's significant ramp-up time for them, plus other employees' training time devoted to them--taking time away from their own days.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;No Silver Bullet (1986)&lt;/em&gt;&lt;br /&gt;
This is Brooks's other most famous essay, written just as microcomputers are coming on the scene. In it he proposes software development won't see magnitudes of performance improvement from any single tool or process. He also breaks down why that is, and comparing software development to hardware development makes an observation I hadn't considered: it's hardware development that's the outlier. The incredible advances in power coupled with reduced cost hadn't--and haven't--happened in any other industry.&lt;/p&gt;
&lt;p&gt;Reading this essay is watching history unfold. Brooks is excited about new approaches--such as objective-oriented programming!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;'No Silver Bullet' Refired (1995)&lt;/em&gt;&lt;br /&gt;
Here, Brooks examines his own essay nine years later. What a difference those years make! And yet, he argues that there is still no single silver bullet despite many advances. He discusses the various critiques of his essay, acknowledges where they're valid, points out where they're not. I enjoyed that he quotes Capers Jones on the subject of productivity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;NSB,&amp;quot; like most writings at the time, was focused on &lt;em&gt;productivity&lt;/em&gt;, the software output per unit of input. Jones says, &amp;quot;No. Focus on &lt;em&gt;quality&lt;/em&gt;, and productivity will follow.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I completely agree.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The Mythical Man-Month after 20 Years (1995)&lt;/em&gt;&lt;br /&gt;
This might be my favorite essay. Brooks discusses his entire book, where he was right, and where he was wrong. With gracious humility, he says, &amp;quot;I dismissed Parnas's concept [of information hiding] as a 'recipe for disaster' in Chapter 7. Parnas was right, and I was wrong.&amp;quot;&lt;/p&gt;
&lt;p&gt;He reveals discussions with the great James McCarthy of Microsoft who pioneered incremental and iterative processes we take for granted (even when business still don't do them!). But mostly, this essay is a snapshot of the industry approaching a turning point of both powerful personal computers and, in a few years, the codification of Agile values and principles. He names bunches of software, a lot I recognized, and most of which is no longer in use.&lt;/p&gt;
&lt;p&gt;1995 was only a year after I entered the computing industry. I wish I'd found this book then, though I wouldn't have understood it. So much of what we talk and read about seems new, but Brooks and his colleagues were struggling with--and solving--these problems already.&lt;/p&gt;
&lt;p&gt;We owe these masters a debt, and maybe that's why I'm glad I didn't give up on reading more of the book. I feel I've, in a small way, said &amp;quot;thank you&amp;quot; to those who came before me and made my career possible.&lt;/p&gt;
&lt;p&gt;One final item. While the essay &lt;em&gt;Why Did the Tower of Babel Fail&lt;/em&gt; didn't make my list, I wrote a fuller article about it on my blog. It disputes Brooks's Tower metaphor, and won't be to everyone's taste, but here it is for you to decide for yourself.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.softwaremeadows.com/posts/meditation_on_the_mythical_man_month__who_failed_on_the_tower_of_babel_project/"&gt;Meditation On The Mythical Man-Month: Who Failed On The Tower Of Babel Project?&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Fri, 9 Sep 2022 19:20:49 -0600</pubDate>
      <link>https://www.softwaremeadows.com/posts/the_mythical_man-month__a_short_review_of_the_essential_essays</link>
      <guid isPermaLink="true">https://www.softwaremeadows.com/posts/the_mythical_man-month__a_short_review_of_the_essential_essays</guid>
    </item>
  </channel>
</rss>