Skip to main content

Posts

Showing posts from October, 2023

The hub-and- spoke network topology for developers

A common network topology used when building cloud infrastructures is the hub-and-spoke model. As I noticed that this model is not always well understood by developers, here is my attempt to describe this model from a developers viewpoint. What Is a Hub-and-Spoke Network Topology? A hub-and-spoke network topology is a type of network architecture where all devices are connected to a central hub. This central hub acts as a focal point for communication, and all the spokes (devices) communicate through this central hub. Think of it as the hub being the center of a wheel, with spokes radiating outward to various endpoints. This topology is also commonly referred to as a star topology. As the name suggest, this topology has 2 key components: Hub : The central hub is a device that serves as the core of the network. It can be a physical device like a switch or a logical point in the network. The hub is responsible for managing and directing the flow of data between all connec...

Add custom properties to ILogger

By default when logging messages through ILogger only objects that have a placeholder in the message template are logged. For example, when executing the following line of code: the following information is logged: This is something that you can also notice when you check the warning you get when hovering over the message:   But what if you want to log these extra properties? One way to get this done is by using scopes to add custom properties. Typically this is used for multiple log entries, but it also works for single log statements:   More information: Logging in C# - .NET | Microsoft Learn

Property based testing in C#–How to change the number of runs?

After gaving my talk about Property Based Testing , I was contacted by one of the participants with the following question: How to change the number of test runs? In case you have no idea what I’m talking about; by default the property based testing library( FSCheck in my case) will generate a number of inputs and run the tests  for all these inputs. By default 100 inputs are generated and tested:   You can change the number of test runs either by setting the MaxTest property on the [Property] attribute: Or by passing a configuration object when calling Prop.ForAll

VISUG Property based testing in C#–Slides and demos

Yesterday I gave a presentation at the Belgian Visual Studio user group( VISUG ). In case you couldn't be there or you would like to have my slides and demos, here is all the material: Slides: https://github.com/wullemsb/presentations/blob/main/VISUG%20-%202023/Property%20based%20testing%20in%20C%23.pdf Demos: wullemsb/propertybasedtestingdemo: Demo's for the property based testing presentation (github.com)   Also check out my blog series about Property Based Testing: Part 1 – Introduction Part 2 – An example Part 3 – Finding edge cases Part 4 – Writing your own generators Part 5 – Locking input

NuGet.CommandLine.CommandLineException: Error parsing solution file

You have to love these days when everything seems to go haywire at the same time. Your code no longer compiles, your CI build status turns red and your unit tests become flaky. Today turned out to be one of such days as our build started to fail with the following error message: System.AggregateException: One or more errors occurred. ---> NuGet.CommandLine.CommandLineException: Error parsing solution file at D:\b\3\_work\154\s\Source\MyApp\MyApp.sln: Exception has been thrown by the target of an invocation. In our pipeline we were using the NuGetToolnstaller task: - task: NuGetToolInstaller@1 inputs: versionSpec: '4.x' We had just installed the latest version of the Visual Studio Build tools on our build server. This new version has a breaking change with regard to older versions of NuGet. As a fix, we switched to a newer NuGet version: - task: NuGetToolInstaller@1 inputs: versionSpec: '5.x' That’s it!

Rearchitecture is a sign of success not failure

An important lesson for a software architect is to design the system for the requirements you have today not for what a possible future could look like. Generated by Dall-E 2 A lot of systems are built with accidental complexity that could have been avoided. I’ve seen really complex high performant code for a system that is used by 10 users, a microservices solution containing 40+ services all maintained by one small team, a real-time event source setup for a system that is mostly CRUD and I can keep going… There is a reason that Martin Fowler talks about a monolith first approach . So if you need to built a system that should support 50 customers, don’t build one that can support 50.000 customers. Start small and wait until you have that many customers that they start to overload your system.  And that is great news because it means that you are successful! The truth is the majority of applications are never going to reach that stage. And even if you do start to get overload...

.NET 6 - Parallel.ForEachAsync

You maybe used Parallel.ForEach() before. It allows to iterate over a collection in a parallel way. It works similar to a Parallel.For loop. The loop partitions the source collection and schedules the work on multiple threads based  on the available processors in a system. Unfortunately the Parallel.ForEach() cannot be used for asynchronous work. Async vs parallel It is important to understand that "async" and "parallel" are two different concepts. Although they are both related to concurrent programming, they serve different purposes and are used in different contexts. Async is used to make non-blocking I/O operations and asynchronous code execution. It is primarily used for tasks that may take some time to complete, like reading from a file, making a network request, or performing database operations. Parallel however refers to parallel programming, which is about executing multiple tasks or operations simultaneously to improve performance and ...

Login failed for user ''

When trying to connect to an Azure SQL database using Azure Data Studio, the connection failed with the following error message: Login failed for user '<token-identified principal>' I’m trying to connect using Azure Active Directory:   Although the error itself was not very clear to me, the error happened because the AAD user I’m using to connect does not exist as a user in the Azure SQL database. To fix this, we need to create the user first. This can be done using the following command: CREATE USER <Azure_AD_principal_name> FROM EXTERNAL PROVIDER; After executing this command, you should be able to connect. Of course, we still need to assign a specific role before we can do anything useful. ALTER ROLE db_datareader ADD MEMBER <Azure_AD_principal_name>; More information Create contained database users in your database mapped to Azure AD identities

Source Generator playground

If you are new to source generators and want to experiment with its possibilities, I can recommend the Source Generator Playground . This Blazor app gives you a simple console application and a source generator and allows you to observe the generated output. You can try it out live here: https://wengier.com/SourceGeneratorPlayground   They are some sample generators available that you can start modifying to see what happens: This is a great way to learn what is possible.

GraphQL Conf 2023

The 2023 edition of GraphQLConf is over. In case you had to miss this great experience, you can still watch all session recordings and get the speaker slides by going to the event schedule .   It is great to see how the GraphQL ecosystem keeps growing and what new innovations and tools are appearing. Start by watching Uri Goldshtein's keynote on the state of GraphQL focused on highlighting the biggest open source innovations from the last year. Then have a look at the GraphQL Fusion presentation given by Michael Staib , introducing a new open spec for remote execution and federation of services that challenges the existing patterns of specification-less Federation protocols with a fresh approach. Learn how GrapQL and CQRS can be combined , how AI is also finding its way in GraphQL land and much more….

Gall’s law and how it applies to software architecture

When it comes to software architecture, complexity can quickly become a daunting adversary. In the ever-evolving world of technology, designing software systems that are not only functional but also maintainable and scalable is a constant challenge. That's where Gall's Law comes into play. Named after John Gall , an American pediatrician, and systems theorist, this principle sheds light on the fundamental idea that underlies software architecture: "A complex system that works is invariably found to have evolved from a simple system that worked." In this post, we'll delve into Gall's Law and explore its profound implications for software architecture. Generated by Dall-E 2 Understanding Gall's Law John Gall's Law, often paraphrased as "Complex systems evolve from simple systems that worked" encapsulates a deep insight into how complex systems come into existence. Gall originally formulated this law in the context of systems theory...

Simplify Source Generator creation the RoslynGenerator template

I’m currently writing my own Source generator which can become quite challenge. Yesterday I talked about RoslynQuoter as one of the tools that helped me along the way. Today I want to show you an easy way to get started thanks to the F0.Templates project . Start by installing the F0.templates using dotnet new --install F0.Templates : Now create a new project using the installed RoslynGenerator template dotnet new roslyngenerator . This will create not only a SourceGenerator project but also a unit and integration tests project and a benchmark project: Inside the projects we find a simple example of an incremental source generator that searches for methods with the [HelloWorld] attribute and generates an implementation: Remark: If you are looking for a list of existing generators, take a look here: amis92/csharp-source-generators: A list of C# Source Generators (not necessarily awesome) and associated resources: articles, talks, demos. (github.com) Learn more

Simplify Source Generator creation with RoslynQuoter

I’m currently writing my own Source generator which can become a challenge when you start to create more complex constructs. One of the tools that helped me during the process was RoslynQuoter . RoslynQuoter is a tool that for a given C# program shows the syntax factory API calls to construct its syntax tree. You can try it out live at: http://roslynquoter.azurewebsites.net .   Nice! More information Source Generators - C# | Microsoft Learn roslyn/docs/features/source-generators.cookbook.md at main · dotnet/roslyn (github.com) roslyn-sdk/samples/CSharp/SourceGenerators at main · dotnet/roslyn-sdk (github.com) KirillOsenkov/RoslynQuoter: Roslyn tool that for a given C# program shows syntax tree API calls to construct its syntax tree (github.com)

ArcGIS - MapViewer is really slow

At one of my client, we are using a lot of GIS related functionality. There are a lot of GIS related products out there, but we are using the ArcGIS JavaScripts Maps SDK from ESRI. We are quite happy with the product and the feature it has to offer. However last week we got the feedback that the MapViewer we had integrated in our applications was quite slow when running in a virtual machine. We could easily reproduce the issue by browsing to the example page from ArcGIS MapViewer: We noticed that not only the map itself was loaded quite slowly, any other activity(zooming, scrolling, …) was also with a noticeable delay. When we looked at the browser console, we noticed the following warnings: Especially the following warning captured our interest: [.WebGL-000026F40027F100]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels As we are running in a Virtual Machine it looks like Chrome didn’t want to use GPU acceleration. Luckily we c...

Create an ASP.NET Core backgroundservice that runs at regular intervals using PeriodicTimer

Today I had to implement an ASP.NET Core backgroundservice that need to execute at certain intervals. Before .NET 6 I would have used Task.Delay or System.Threading.Timer , but in .NET 6 we have a better alternative through the PeriodicTimer . The PeriodicTimer uses an asynchronous approach based on the System.Threading.Tasks. It has a method WaitForNextTickAsync that allows to pause execution until the next time the timer is elapsed. I first created a backgroundservice: In the ExecuteAsync method I can now introduce the PeriodicTimer and call the WaitForNextTickAsync() method in a while loop . The loop shall run while no cancellation of the background service is requested in the CancellationToken and wait for the next tick of the timer:   Remark: The PeriodicTimer is intended to be used only by a single consumer at a time: only one call to WaitForNextTickAsync() may be in flight at any given moment. So make sure that your business logic is executed before the int...

How are you doing TODAY?

How one extra word can make a big difference… A question people probably ask you a lot is How are you doing? Most of the time, this question is used as a polite way to say hello, and the question asker doesn’t really expect you to say anything about how you are really feeling.  The expected answer is Great, thank you. And we follow up by asking the same polite question How are you doing? What if... But what if you add one simple word and change the question to this: How are you doing TODAY? Now this question becomes really specific and it creates an opening to let the polite answer pass and give a real answer on how you are feeling in this moment. Although only one word was added I noticed that it was a lot harder for people to just answer with a “Great, how are you?”. At least I noticed a small hesitation before people answered the question reflecting on their answer, at best they opened and really shared what was on their mind. So my suggestion t...

Using Problem Details in .NET 7

When comparing API's, I see a lot of different ways how error messages are returned. With the introduction of Problem Details for HTTP APIs ( https://tools.ietf.org/html/rfc7807 ) , we finally have a standardized error payload to return when an unhandled exception occurs. Although the standard was introduced before .NET 7, there was no out-of-the-box way to introduce the ProblemDetails spec into your ASP.NET Core application. A solution was to use the third party Hellang.Middleware.ProblemDetails nuget package: Starting from .NET 7 this nuget package is no longer necessary. You only need to add the following line to your service configuration: If someone now calls your API and an exception occurs, the returned result will look like this: We can further customize the behavior through CustomizeProblemDetails : More information Handle errors in ASP.NET Core web APIs | Microsoft Learn

Applying the smart constructor pattern in C#

In Domain-Driven Design (DDD), domain invariants are fundamental principles or rules that must always hold true within a specific domain. These invariants define constraints or conditions that govern the behavior and state of the entities, value objects, and aggregates within the domain. They emphasize the Always-valid rule: Your domain model should always be in a valid state. By using invariants, your domain model guarantees that it cannot represent illegal states. These invariants define the domain class: that class is what it is because of them. Therefore, you can’t possibly violate these invariants. If you do so, the domain class would simply cease being the thing you expect it to be; it’d become something else. As Greg Young explains it: A unicorn without a horn is a horse, not a unicorn. There are multiple ways to protect those invariants. Using value objects and taking advantage of the type system are a great help here. However not all invariants can be enf...

Angular–Generate your OpenAPI client model

Most Angular applications need some kind of data typically provided through an OpenAPI or GraphQL API. Manually creating all the necessary model classes and client can be a time-consuming and error-prone task. In this post we have a look at ng-openapi-gen to help you automate this process. We start by installing the ng-openapi-gen module by executing the following command: npm install -g ng-openapi-gen Now we can generate our models and web client in the Angular application using the following command: ng-openapi-gen --input <path-to-openapi-json> --output <angular-app-path>/src/app/shared/api If you look at the command above you see that it requires to an OpenAPI specification file. This can be in JSON or YAML format. So we first need a way to get this specification file. If you are using ASP.NET Core with the OpenAPI integration , you can either download the OpenAPI file manually by going to the swagger UI and download it there or you can generate the OpenAPI...

Azure DevOps–Contribution graph

If you ever used Github, you’ve certainly seen the contribution graph. This graph shows the contribution of a user in one or more repo's over time: This feature is not available out of the box in Azure DevOps (Server) but thanks to the Contribution Graph plugin from Otto Streifel, you can add this feature there as well. After installing this extension, you can find it under Boards > Contribution Graph : When you open the graph you see the contributions you made over time(similar to the Github experience): You can filter the visible information by expanding the Activity filters : It is possible to select multiple users and repositories and filter the type of activities you want to visualize. Nice!