Posts

Permission Denied error saving in Draw.io on Linux

Image
 I installed the desktop version of Draw.io on my Ubuntu system using the Ubuntu Store (snap).  When trying to save files to my Windows partition (or mounted device other than / (root), a received the following error: After some digging, I found that the permission for the snap defaulted external devices as disallowed. Had to simply enable "Read/write files on removable storage devices", and viola! Hope this helps other seeing the same behave from this or other snaps. Cheers!

Using Linux Fulltime on my Surface Book

As much as I do like Windows 11, I don't like how Windows and Office are now filled with ads and privacy really isn't front and center. Yes, you can turn a lot of data sharing off, but not all of it. A couple years ago I test-drove Linux as a development rig and was very impressed with the experience. So, I decided to take another look at Linux for daily use. Linux was my primary OS for 5 years in the early 2000's. Distro The last time I did this, I was using Fedora. I still like RedHat and derivatives, but this time I decided to go with Ubuntu 22.04 LTS. So far it works great on my Microsoft Surface Book 2 using the modifed linux-surface kernel . Even the pen works! So does detach. It plays nicer than Windows with my KVM. In Windows 11, if I undock and redock, I lose the external devices--e.g., monitor, mouse, and keyboard--and have to reboot the KVM. With Ubuntu, it's a seamless transition as expected. Dev Environment Nearly all my development work is in dotnet and ...

Yield in C#

Image
The yield keyword is used when the method or accessor is an enumerator. Using yield return returns one element at a time. The thing to remember here is that IEnumerable/IEnumerable<T> is a stream, not a collection. This is where many developers misuse IEnumerable (myself included once upon a time). Consider the following code: This is probably what you are used to seeing, but is actually a misuse of IEnumerable. The code works just fine, but it is not leveraging the benefits of IEnumerable being a stream. Let's refactor to use yield return: What we are doing now is streaming the elements one at a time. Each iteration by the consumer of this method comes back to the point of the yield and executes the next statement, in this case the while. The benefit? We eliminated a loop and an object allocation. Rather than looping through all the records, building up a list, then looping through the list, we just loop through the records once.

Test Driven Development (TDD) Simplified

Test Driven Development (TDD) is a development/design approach in which we write our tests first, then implement the code to make these tests pass. What TDD is Not These initial tests we write are not unit tests in the traditional sense. I'll repeat that: TDD tests are not unit tests. What are they then? TDD tests are specification tests. They are an example of how to use the thing being built. Sure, we'll use a "unit testing" framework to build, them, but don't get hung up on terminology. The idea is, we're testing, and showing an example of, the API, not testing the logic of an individual piece of the several pieces that make up the implementation of that API.  Let's look at a simple example: Let's take a feature and a scenario: Vendor Lookup Feature: Users can search for Vendors in the system. Scenario: Search by a company name beginning with the search term. Given the following vendors | CompanyName | | Acme Supply | When the company name...

Configuration Reload in .Net

The 12 Factor App guidelines suggest separating configuration from code as a best practice. More specifically, it should be deployed separately as well. We shouldn't have to redeploy the entire application in order to make a configuration change. Ideally, we don't want to have to restart our app either.  This eliminates downtime when making configuration changes that don't otherwise require downtime such as timeout values, retry configuration, logging level, and distributed trace sampling rate. For providers that support it, Microsoft.Extensions.Configuration can reload the configuration when it changes. Let's take a look. We'll be using the JSON file provider for these examples with the following configuration: IConfigurationRoot When we change a configuration value, the value in the IConfiguration instance also changes. The key to making it all work is the reloadOnChange parameter. Given a simple console app, we can see the behavior as we modify the appsettin...

Never use float for money

The web is riddled with articles on this very topic, yet it bares repeating: never use float for money. I repeat: never never never never never use a floating point data type to represent monetary values or do financial math. Why? Single and Double precision floating point numbers are not accurate. Ironically, it's by design. They are optimized for performance where absolute accuracy is not a concern. Microsoft talks about it briefly here:  https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types [...]there's no double or float instance that exactly represents 0.1. Because of this difference in numeric types, unexpected rounding errors can occur in arithmetic calculations when you use double or float for decimal data. Baeldung has an excellent writeup on the science behind why floats behave the way they do:  https://www.baeldung.com/cs/floating-point-numbers-inaccuracy So what should we use for money and financial calculation...

AES256 Encryption in C#

Every few years, I find myself having to write an AES256 encryption routine for a project. I always end up having to lookup the specifics, so I thought I would write it down this time. What is AES256 AES--Advanced Encryption Standard--is a symmetrical block cipher standard. Symmetrical meaning it uses the same key to both encrypt and decrypt, as opposed to Asymmetrical (eg. TLS) which uses a public/private key pair--a different key to encrypt than to decrypt. Block cipher meaning the encryption is performed by chunking the plain text into blocks and encrypting each block separately. In the case of AES, each block is 128 bits in length. Chunks smaller than 128 bits are padded to create a 128 bit block. At the time of this writing, bank-grade and government standard uses a 256 bit key (AES256) and a CBC--Cipher Block Chaining--mode. With CBC, each plain text block is XOR with the previous encrypted block before being encrypted itself. This requires an initialization vector--a unique, ran...

Pragmatic Architecture. Pragmatic Microservices.

Image
Customer-First. Team-Focused. I like to take a customer-first approach to architecture and software design. A system architecture should always deliver value to the customer. Either directly--features, user experience--or indirectly by enabling teams to deliver value. If a team is going to be able to deliver value, the system needs to be easy to reason over, easy to maintain, easy and safe to extend, and easy to operate. Every architecture or design decision should answer: How does this deliver value to my customer? How does this deliver value to my team? Competing Styles. The Swinging Pendulum. It seems the big debate lately is monolith vs microservices. Academically, each at the opposite end of the spectrum: the massive, single deployable unit monolith on one end and the highly decomposed highly distributed microservices on the other. Each come with their pros and cons and serve teams better depending on team size, skill level, and goals. Notice I didn't include the customer in t...

A .Net Development Rig in Linux

Image
After playing with Rider for a while, I decided to play around with Linux again to see what .Net development is like on Linux rig in 2020. So I fired up an Ubuntu 20.04 LTS VM and started installing. .Net Core After updating the OS with all the latest patches, I installed both .Net Core 2.1 LTS and 3.1 LTS following Microsoft's instructions . wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages-microsoft-prod.deb sudo apt-get update; \ sudo apt-get install -y apt-transport-https && \ sudo apt-get update && \ sudo apt-get install -y dotnet-sdk-3.1 dotnet-sdk-2.1 JetBrains IDEs I have a JetBrains Ultimate subscription, so my next setup was installing JetBrains Toolbox. There is zero documentation on doing so, but it's pretty simple. Just download the tar ball from JetBrains, extract it to a directory of your choosing, and run it. Using the ToolBox, I installed my IDEs--Rider, In...

My Experience with JetBrains Rider

Disclaimer: This is an OpEd and mostly anecdotal. Performance wasn't measured, just perceived based on whether it left like the IDE was hanging a lot or productivity was impacted. I'll start off by saying: there is no replacement for Visual Studio. None. That's my opinion anyway. That said, JetBrains Rider is a decent .Net IDE, especially if you are a ReShaper fan (I am not) or IntelliJ fan (I am). What made me decide to give it a go? Well, I started work at Linedata as a Cloud Solution Architect and Application Architect. They are heavy users of ReSharper, and use it to enforce code formatting, quality, standards, and test coverage ( dotCover ) as part of their CI builds. It only took a few hours of me getting fed up with ReSharper crippling Visual Studio for me to install Rider and give it a go. I've been using it at work since. Some take-aways After using Rider as my primary C# IDE for a few months, here's my impression... Good Impressions P...

Static Readonly instead of Const in C#

I have always considered it a best practice to use  static readonly  instead of  const  in C#. Here’s why… The  const  keyword tells the compiler to replace the constant token in your code with the literal value you have defined for the constant. You can see this if you look at the IL: The C# code… const string HELLO = "Hello" ; ... Console . WriteLine ( HELLO ); Console . WriteLine ( HELLO ); Compiles to the IL… .field private static literal string HELLO = "Hello" ... IL_0001: ldstr "Hello" IL_0006: call void [System.Console]System.Console::WriteLine(string) IL_000b: nop IL_000c: ldstr "Hello" IL_0011: call void [System.Console]System.Console::WriteLine(string) Notice that the literal  "Hello"  is loaded twice. Using  static readonly  provides us similar semantics–a global value that cannot be changed–but rather than references being replaced with literals by the compiler, it remains ...

Code Coverage for Multiple Projects in a Single Build using Dotnet Test and Coverlet

Most of the time, your solution will have more than one project and a test unit project for each of those. Azure DevOps only, as of this writing, only allows you to update a single code coverage summary. If you upload more than one, each overwrites the next and only the last one remains. To accomplish this, we can use the merge functionality in Coverlet . I use the MSBuild extension, because it is better suited for CI pipelines. In your test project XML, add the package... <PackageReference Include="coverlet.msbuild" Version="2.7.0">     <PrivateAssets>all</PrivateAssets>     <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference> Then, in your dotnet test command or msbuild command, tell it to use Coverlet and to merge results. If you're using Azure DevOps, your test task looks this... (line wrapped for read ability in the article) - task: DotNetCoreCLI@2 displayName: Test i...

.Net Full Framework Tests with the New Project System

I ran into a scenario where my solution had libraries targeting netStandard2.0 and/or net461. For the libraries targeting just net461, I created a “MSTest Unit Test Project (.Net Framework)” project–the “old” project system. The tests ran fine in Visual Studio, but in my CI build, I wanted to keep it simple and run all the tests with dotnet test. However, this tooling cannot see/run the old test project. So, as an experiment, I tried creating a test project in the new project system, and changing the target moniker from NetCoreApp to net461.  It worked! both dotnet test and Visual Studio can run the tests. It’s worth noting that the library is also the new project system. I haven’t tested if that matters. Test Project XML <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net461</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include="Mic...

Incorporating Snyk into Continuous Integration with Azure Yaml Pipelines

Image
Automate all the things! The same goes for security checks in our application. Continuous Security is the automation of these checks as part of the continuous delivery pipeline. The type of check determines where the check can, or should, go. Static testing (SaST), for example, should happen outside of, but be triggered by, CI. Dynamic Testing (DaST) happens outside of, but triggered by, deployment. Another scan we can, and should, perform is a security analysis of packages we’re pulling into our applications. This can happen during CI, and the build or pull request can be rejected if packages with known vulnerabilities are used. There are several tools emerging in this space, one of which is  Snyk.io . These tools compare your imported packages and versions to those listed in various CVE databases to determine if a package has a known vulnerability, and, if applicable, report the version you should upgrade to in order to patch the vulnerability. Some tools, like Snyk or eve...

Using NHibernate in Asp.Net Core

Starting with version 5.1, NHibernate now supports .Net Core and .Netstandard as well as the full framework. Let’s take a quick look at how to set it up in an ASP.Net Core 2.x/3.x application. Configuration As of this writing, NHibernate doesn’t support the configuration system within Asp.Net Core based on Microsoft.Extensions.Configuration. The good news is, you don’t have to use a  hibernate.cfg.xml  file or the   section in app.config. You can add the properies manually, and pull the values from Asp.Net Core’s configuration, taking advantage of all the goodies that come with it. This opens up a world of configuration deployment possibilities. var config = new Configuration (); IDictionary < string , string > properties = new Dictionary < string , string > { { "connection.connection_string" , Configuration . GetConnectionString ( "Default" ) }, { "dialect" , "NHibernate.Dialect.SQLiteDialect" }, ...