Posts

Showing posts from 2022

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...