<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mo</title>
    <description>The latest articles on DEV Community by Mo (@ipazooki).</description>
    <link>https://dev.to/ipazooki</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1127050%2F4677b6e9-5072-42f2-83fd-050e3c322fc4.JPG</url>
      <title>DEV Community: Mo</title>
      <link>https://dev.to/ipazooki</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ipazooki"/>
    <language>en</language>
    <item>
      <title>Claude Opus 4.6 vs. GPT 5.4</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sun, 29 Mar 2026 17:10:27 +0000</pubDate>
      <link>https://dev.to/ipazooki/claude-opus-46-vs-gpt-54-4bcc</link>
      <guid>https://dev.to/ipazooki/claude-opus-46-vs-gpt-54-4bcc</guid>
      <description>&lt;h2&gt;
  
  
  Claude Opus 4.6 vs. GPT 5.4: My Take as a C#/.NET Dev on AI Coding Companions
&lt;/h2&gt;

&lt;p&gt;Alright team, let's talk AI. As a senior engineer who's spent more years than I care to admit wrangling C# and .NET, I've seen my fair share of "game-changing" tech. Most of it is just hype. But these new-gen LLMs? They're different. We're talking about legitimate productivity boosters, especially when you're staring down a tricky bug or architecting a new microservice.&lt;/p&gt;

&lt;p&gt;Lately, I've been putting the big two — Claude Opus 4.6 and GPT 5.4 — through their paces specifically for coding tasks. The question isn't &lt;em&gt;if&lt;/em&gt; they're useful, but &lt;em&gt;which one&lt;/em&gt; to bring to the fight, or if we should be thinking "both." Let's dive into my real-world experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup: My C#/.NET AI Playground
&lt;/h2&gt;

&lt;p&gt;Before we get into the nitty-gritty, a quick word on my testing environment. I wasn't just asking them to write "Hello World." I was throwing real-world problems at them: building complex LINQ queries, designing a robust API controller, refactoring legacy code, even trying to get them to write xUnit tests for some tricky asynchronous logic.&lt;/p&gt;

&lt;p&gt;I wanted to see how they handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Context:&lt;/strong&gt; Can they keep track of a larger codebase or conversation?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Precision:&lt;/strong&gt; Do they generate code that actually compiles and runs correctly the first time?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Nuance:&lt;/strong&gt; Can they understand &lt;em&gt;why&lt;/em&gt; I'm asking for something, not just &lt;em&gt;what&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Debugging:&lt;/strong&gt; How good are they at finding issues in their own code or mine?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GPT 5.4: The Speedy Generalist with a Few Surprises
&lt;/h2&gt;

&lt;p&gt;GPT 5.4 feels like that incredibly bright junior developer who's read &lt;em&gt;every&lt;/em&gt; programming book but sometimes misses the specific context of &lt;em&gt;our&lt;/em&gt; project. It's fast, incredibly broad in its knowledge, and often provides surprisingly elegant solutions right out of the gate.&lt;/p&gt;

&lt;p&gt;When I needed boilerplate code for a new &lt;code&gt;DbContext&lt;/code&gt; or a standard ASP.NET Core controller, GPT 5.4 was lightning-fast and usually spot-on. It's fantastic for generating common design patterns or even suggesting different approaches to a problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it Shines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Broad Knowledge Base:&lt;/strong&gt; If it's a common C# pattern, a widely used .NET library, or a general algorithm, GPT 5.4 knows it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Code Generation Speed:&lt;/strong&gt; It often generates long code blocks quickly, perfect for getting a first draft down.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Exploration:&lt;/strong&gt; Great for brainstorming different ways to solve a problem or exploring new libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where I Pump the Brakes:&lt;/strong&gt;&lt;br&gt;
Sometimes, GPT 5.4 can be a bit &lt;em&gt;too&lt;/em&gt; confident. It occasionally generates plausible-looking code that has subtle bugs, or it might make assumptions about my project that aren't true. I've also found it can "forget" earlier parts of our conversation if the thread gets too long. It's like it gets distracted by the next shiny coding problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzhx5j9eom57y7ktc4wy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzhx5j9eom57y7ktc4wy.gif" alt="GIF" width="450" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Opus 4.6: The Meticulous Architect, Slow and Steady
&lt;/h2&gt;

&lt;p&gt;Claude Opus 4.6, on the other hand, feels more like a seasoned architect. It's often slower to respond, but its answers tend to be incredibly thoughtful, detailed, and deeply contextual. It seems to "think" more before responding, often asking clarifying questions or laying out its reasoning step-by-step.&lt;/p&gt;

&lt;p&gt;For complex refactoring tasks, or when I was trying to optimize a specific piece of asynchronous code for performance, Claude truly stood out. It provided not just the code, but the &lt;em&gt;rationale&lt;/em&gt; behind the choices, often citing best practices or potential pitfalls. It felt like pair programming with someone who meticulously considers every angle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it Shines:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Contextual Understanding:&lt;/strong&gt; It maintains context over very long conversations, making it excellent for multi-step tasks or complex debugging.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deep Reasoning:&lt;/strong&gt; Its explanations are often superb, breaking down complex problems and justifying its code choices.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Fewer Hallucinations:&lt;/strong&gt; I've found it to be more reliable in generating correct, runnable code without subtle errors. It double-checks its work, which is invaluable.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Refactoring &amp;amp; Debugging:&lt;/strong&gt; Excellent at identifying issues in existing code and suggesting robust improvements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where I Feel the Pinch:&lt;/strong&gt;&lt;br&gt;
The speed. Sometimes, when you just need a quick &lt;code&gt;IEnumerable&lt;/code&gt; extension method or a simple DI setup, waiting for Claude's detailed explanation can feel a bit overkill. It's not a rapid-fire code generator in the same way GPT 5.4 can be.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verdict: Don't Choose, Combine!
&lt;/h2&gt;

&lt;p&gt;After weeks of real-world use, my conclusion is clear: &lt;strong&gt;you don't have to pick just one.&lt;/strong&gt; These aren't competitors; they're complementary tools in a modern software engineer's arsenal.&lt;/p&gt;

&lt;p&gt;Think of it this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reach for GPT 5.4 when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You need rapid prototyping or boilerplate generation.&lt;/li&gt;
&lt;li&gt;  You're exploring new libraries or frameworks and need quick examples.&lt;/li&gt;
&lt;li&gt;  You're stuck on a common problem and need a few different potential solutions fast.&lt;/li&gt;
&lt;li&gt;  You need simple, isolated code snippets.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Reach for Claude Opus 4.6 when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You're working on complex architectural decisions or refactoring significant parts of your codebase.&lt;/li&gt;
&lt;li&gt;  You need detailed explanations, best practices, and a deeper understanding of &lt;em&gt;why&lt;/em&gt; certain code is structured a certain way.&lt;/li&gt;
&lt;li&gt;  You're debugging persistent, tricky issues and need a methodical, logical approach.&lt;/li&gt;
&lt;li&gt;  You have a long, ongoing conversation about a specific problem and need the AI to maintain deep context.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjixvobd6qw19ko52yxvr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjixvobd6qw19ko52yxvr.jpeg" alt="Technical Image" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I often start with GPT 5.4 for initial drafts or quick ideas. Then, if I hit a wall, or if the problem requires more nuanced reasoning, I'll port the conversation (or at least the core problem) over to Claude Opus 4.6 for a more in-depth architectural review or a meticulous debugging session. It’s like having a brilliant junior dev for the grunt work and an experienced architect for the heavy lifting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your AI Pair Programming Partner(s)
&lt;/h2&gt;

&lt;p&gt;Adopting these tools isn't about replacing engineers; it's about augmenting our capabilities. It's like having a super-powered pair programmer who never gets tired and has read the internet. For us C# and .NET folks, understanding the strengths of both Claude Opus 4.6 and GPT 5.4 means we can write better code, faster, and with fewer headaches.&lt;/p&gt;

&lt;p&gt;What are your experiences? Have you found one to be clearly superior for your specific tech stack, or are you also seeing the value in a multi-model approach? Let me know in the comments!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>llm</category>
    </item>
    <item>
      <title>C# Keeps Getting Better: My Favourite Modern Language Features</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sat, 28 Mar 2026 11:48:16 +0000</pubDate>
      <link>https://dev.to/ipazooki/c-keeps-getting-better-my-favourite-modern-language-features-2bkh</link>
      <guid>https://dev.to/ipazooki/c-keeps-getting-better-my-favourite-modern-language-features-2bkh</guid>
      <description>&lt;p&gt;If you've been coding in C# for a while, you know it's a language that refuses to sit still. Every new version brings a fresh set of tools, and honestly, as someone who's been wrangling &lt;code&gt;.NET&lt;/code&gt; for years, it's pretty exciting to see how much more expressive, concise, and just plain &lt;em&gt;fun&lt;/em&gt; C# has become. Gone are the days of endless boilerplate for simple tasks!&lt;/p&gt;

&lt;p&gt;Let's dive into some of the features that have genuinely changed how I approach C# development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streamlining Your Code: Less Ceremony, More Action!
&lt;/h2&gt;

&lt;p&gt;One of the biggest shifts in recent C# versions has been a strong push towards reducing boilerplate. We're all busy, right? Why type more when you can say the same thing with less?&lt;/p&gt;

&lt;h3&gt;
  
  
  Top-Level Statements: Kickstarting Your Apps
&lt;/h3&gt;

&lt;p&gt;Remember when even a simple "Hello World" console app needed a &lt;code&gt;namespace&lt;/code&gt;, a &lt;code&gt;class&lt;/code&gt;, and a &lt;code&gt;static void Main(string[] args)&lt;/code&gt;? It felt a bit heavy for quick scripts or learning examples. Well, say hello to top-level statements!&lt;/p&gt;

&lt;p&gt;Now, your entire program can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Program.cs&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, modern C#!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// You can even use async/await directly&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Waiting is over!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fantastic for small utilities, Azure Functions, or just getting an idea off the ground without the cognitive load of a full class structure. It makes C# feel much more scripting-friendly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global Using Directives: De-cluttering Your Files
&lt;/h3&gt;

&lt;p&gt;How many times have you scrolled past a dozen &lt;code&gt;using&lt;/code&gt; statements at the top of every file? &lt;code&gt;System&lt;/code&gt;, &lt;code&gt;System.Collections.Generic&lt;/code&gt;, &lt;code&gt;System.Linq&lt;/code&gt;, &lt;code&gt;Microsoft.EntityFrameworkCore&lt;/code&gt;... the list goes on.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;global using&lt;/code&gt; directives let you declare these common &lt;code&gt;using&lt;/code&gt; statements &lt;em&gt;once&lt;/em&gt; for your entire project. Just drop them into a file (often &lt;code&gt;GlobalUsings.cs&lt;/code&gt; or &lt;code&gt;Usings.cs&lt;/code&gt;), and they're available everywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GlobalUsings.cs&lt;/span&gt;
&lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Linq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.EntityFrameworkCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...and so on&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference this makes in larger projects is immense. Your individual files become cleaner, focusing purely on the code within. No more endless scrolling past &lt;code&gt;using&lt;/code&gt; blocks!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figteocagxkuh775h87t2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figteocagxkuh775h87t2.gif" alt="GIF" width="500" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Embracing Immutability: Records &amp;amp; &lt;code&gt;init&lt;/code&gt; Setters
&lt;/h2&gt;

&lt;p&gt;Immutability is a huge win for robust, predictable software. When an object's state can't change after it's created, you eliminate entire classes of bugs related to unexpected side effects. C# has made it a first-class citizen with records and &lt;code&gt;init&lt;/code&gt; setters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Record Types: The Data-First Class
&lt;/h3&gt;

&lt;p&gt;Records are essentially classes (or structs) designed for immutable data models. They come with a ton of goodies out of the box, like value-based equality, concise syntax, and non-destructive mutation (&lt;code&gt;with&lt;/code&gt; expressions).&lt;/p&gt;

&lt;p&gt;Imagine you're defining a Data Transfer Object (DTO) or an entity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Old way (class) - lots of boilerplate for immutability, equality, and ToString&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Need to override Equals, GetHashCode, ToString manually...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// New way (record) - concise, immutable by default, value equality&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's right, a single line! Records are perfect for scenarios where you just need to represent data. They save you from writing mountains of boilerplate for &lt;code&gt;Equals&lt;/code&gt;, &lt;code&gt;GetHashCode&lt;/code&gt;, and &lt;code&gt;ToString&lt;/code&gt;, and they promote a functional style of programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--V_S5bB_0--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3f3f3f3f3f3f3f3f3f3f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--V_S5bB_0--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3f3f3f3f3f3f3f3f3f3f3.png" alt="Technical Diagram Placeholder" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;init&lt;/code&gt; Setters: Immutable Properties, Flexible Creation
&lt;/h3&gt;

&lt;p&gt;Even with regular classes, &lt;code&gt;init&lt;/code&gt; setters provide a powerful way to ensure properties can only be set during object initialisation, enforcing immutability after creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Can only be set during object creation&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;RegisteredDate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Default value also works&lt;/span&gt;

    &lt;span class="c1"&gt;// Usage&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;UserProfile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"devfriend"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// user.Id = 2; // Error: Init-only setter cannot be used here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the best of both worlds: object initialiser syntax for easy construction, and immutability once the object is fully formed. Super handy for configuration objects or read-only view models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smarter Decisions: Enhanced Pattern Matching
&lt;/h2&gt;

&lt;p&gt;Pattern matching isn't new, but it's been steadily enhanced, making complex conditional logic incredibly readable and concise. It allows you to test an expression against various "patterns" and execute code based on a match.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;switch&lt;/code&gt; Expressions and Property Patterns
&lt;/h3&gt;

&lt;p&gt;Gone are the days of clunky &lt;code&gt;switch&lt;/code&gt; statements with &lt;code&gt;case&lt;/code&gt; and &lt;code&gt;break&lt;/code&gt;. &lt;code&gt;switch&lt;/code&gt; expressions are, well, expressions – they return a value, making them perfect for transformations. Combine that with property patterns, and you have some serious power.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Imagine a DTO or some input object&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ItemType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;UnitPrice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderItem&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// If ItemType is "Book" AND Quantity &amp;gt; 5, apply 10% discount&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ItemType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Book"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnitPrice&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.10M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// If ItemType is "Software" AND UnitPrice &amp;gt; 100, apply 5% discount&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ItemType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Software"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UnitPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnitPrice&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.05M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Any other case&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0M&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Even simpler: type patterns&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetShapeInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Radius&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"Large Circle with radius &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Circle&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"Small Circle with radius &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Radius&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Rectangle&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"Rectangle &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;x&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Unknown shape"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This syntax is incredibly powerful for expressing intent clearly. Instead of nested &lt;code&gt;if/else if&lt;/code&gt; statements, you get a clean, declarative structure that's easy to read and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;These are just a few of my personal highlights from the recent evolutions of C#. From making quick scripts easier with top-level statements to building robust, immutable data models with records, and writing more expressive conditional logic with pattern matching, C# continues to empower developers to write cleaner, more maintainable code.&lt;/p&gt;

&lt;p&gt;It's a fantastic time to be a C# developer, and I'm always excited to see what's next!&lt;/p&gt;

&lt;p&gt;What new C# feature has made the biggest difference in your daily coding life? Let me know in the comments!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>net</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Migration from .NET 4.7 to .NET 10</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sun, 07 Dec 2025 14:32:14 +0000</pubDate>
      <link>https://dev.to/ipazooki/migration-from-net-47-to-net-10-4ig0</link>
      <guid>https://dev.to/ipazooki/migration-from-net-47-to-net-10-4ig0</guid>
      <description>&lt;h2&gt;
  
  
  Travels in Time:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Great Migration from .NET Framework 4.7 to .NET 10 🚀
&lt;/h3&gt;

&lt;p&gt;All of us have encountered this situation: inheriting a project that has remained untouched for years, only to discover it is now outdated. Recently, I was assigned to such a project with a clear directive to modernise a legacy application built on .NET Framework 4.7 and successfully migrate it to the latest LTS release, &lt;strong&gt;.NET 10&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It was a journey filled with architectural archaeology, AI tooling, and some tough decisions. Here is the story of how we managed the upgrade of this legacy application using Visual Studio 2026, and what we learned along the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧐 Phase 1: The Archaeology
&lt;/h2&gt;

&lt;p&gt;My journey began with a classic induction meeting with my Line Manager and Product Owner. Once the pleasantries were done, I popped the hood to see how the project was structured.&lt;/p&gt;

&lt;p&gt;As expected with legacy code, there wasn't much of a "structure" to speak of. It was a flat architecture where almost all business logic lived directly inside the Controllers. Even worse, database contexts were being instantiated right there in the controller methods, something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LegacyController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ActionResult&lt;/span&gt; &lt;span class="nf"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Direct instantiation inside the controller? Check.&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyDbContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I knew that if I started refactoring immediately, I would generate a massive amount of changes that would be impossible to review properly, increasing the risk of failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Initial Health Check
&lt;/h3&gt;

&lt;p&gt;I decided to run the application to understand the flow without getting bogged down in the nitty-gritty of every single class. I also ran the existing unit tests. Unsurprisingly, red lights flashed everywhere.&lt;/p&gt;

&lt;p&gt;The project lacked a proper CI/CD pipeline, so over time, business logic had drifted, while the tests had been forgotten.&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Phase 2: The Battle Plan
&lt;/h2&gt;

&lt;p&gt;I went back to the Azure Board and tagged my Line Manager and PO with a plan. I proposed a strict order of operations to mitigate risk:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Stabilize:&lt;/strong&gt; Pass all current unit tests to ensure the application works &lt;em&gt;before&lt;/em&gt; we touch the framework.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Upgrade:&lt;/strong&gt; Move the project directly from .NET Framework 4.7 to .NET 10.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Modernise:&lt;/strong&gt; Once stable on .NET 10, implement a proper CI/CD pipeline in Azure DevOps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I spent a few days fixing bugs in the test suite until everything was green. Only then was I ready for the big lift.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Phase 3: The Upgrade (Dependencies &amp;amp; AI Tools)
&lt;/h2&gt;

&lt;p&gt;Using the newly released &lt;strong&gt;Visual Studio 2026&lt;/strong&gt;, I started by auditing our NuGet packages and third-party references.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Third-Party Challenge
&lt;/h3&gt;

&lt;p&gt;One significant hurdle was a reference to &lt;strong&gt;Excel-DNA&lt;/strong&gt;. When upgrading, checking vendor compatibility is non-negotiable. I had to comb through their documentation to find their specific upgrade process for .NET 10 compatibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Entity Framework Dilemma
&lt;/h3&gt;

&lt;p&gt;We were also using &lt;strong&gt;Entity Framework 6 (EF6)&lt;/strong&gt;. While EF6 is technically compatible with .NET 10, the long-term goal is obviously Entity Framework Core. However, trying to do that migration simultaneously would have blown up the scope. My manager and I agreed: get to .NET 10 first, upgrade to EF Core later.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI vs. Legacy Tools
&lt;/h3&gt;

&lt;p&gt;Visual Studio 2026 offers a tool called &lt;strong&gt;Modernizer&lt;/strong&gt;, which leverages AI (ChatGPT, Gemini, Claude) to handle upgrades.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modernizer (AI)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fantastic for simple class libraries. It proposed excellent upgrade plans and did the heavy lifting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Legacy Upgrade Assistant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Necessary for the complex UI projects. The AI struggled with our old AngularJS/MVC mix, so I had to enable this legacy tool via &lt;code&gt;Tools &amp;gt; Options&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🏗 Phase 4: Execution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Low-Hanging Fruit
&lt;/h3&gt;

&lt;p&gt;I started with the solution's four projects. Three were simple class libraries, so I used the &lt;strong&gt;Modernizer&lt;/strong&gt; AI tool to upgrade them to .NET 10 first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro Tip:&lt;/strong&gt; When upgrading, resist the urge to use new features immediately. .NET 10 has cool toys like file-scoped namespaces, but mixing feature changes with framework upgrades creates noisy Pull Requests (PRs). I kept the code changes minimal so my team could actually review the PR.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 2: The Web Project (The Beast)
&lt;/h3&gt;

&lt;p&gt;The main website was an ASP.NET MVC application with &lt;strong&gt;AngularJS&lt;/strong&gt;. The Legacy Upgrade Assistant handled the C# conversion well, but it had no idea what to do with the UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bundling Problem:&lt;/strong&gt;&lt;br&gt;
Old ASP.NET had built-in bundling for CSS and JS. .NET 10 doesn't work that way. I had to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Find npm equivalents for our NuGet client-side packages.&lt;/li&gt;
&lt;li&gt; Implement a new build process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I decided to use &lt;strong&gt;Gulp&lt;/strong&gt; to compile our TypeScript and LESS files and bundle them. I utilised AI heavily to generate the Gulp tasks (which worked perfectly), creating a single output file referenced in our &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: The Inevitable Refactor
&lt;/h3&gt;

&lt;p&gt;Here is where I had to break my own rule about "minimal changes." The old code was so non-SOLID that I literally couldn't inject the services I needed into the controllers.&lt;/p&gt;

&lt;p&gt;I had to refactor the presentation layer, introducing the &lt;strong&gt;Unit of Work&lt;/strong&gt; pattern and cleaning up the dependency injection. It made the PR larger, but it was unavoidable to get the application running.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Phase 5: Crossing the Finish Line
&lt;/h2&gt;

&lt;p&gt;With the refactoring done, I ran the project. Miraculously (or perhaps due to the preparation), it worked.&lt;/p&gt;

&lt;p&gt;I performed end-to-end testing, deployed to the test environment, and handed it over to QA. Everything looked green. I opened the PR, which was only "50% of the job" considering the future work needed, but the platform was now on .NET 10.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 What's Next?
&lt;/h2&gt;

&lt;p&gt;We successfully reached .NET 10, but the journey isn't over. We still need to upgrade to EF Core and add observability.&lt;/p&gt;

&lt;p&gt;However, the business has shifted priorities. The old AngularJS frontend is now a security vulnerability. We aren't just upgrading to modern Angular; my manager wants a complete rewrite of the presentation layer using &lt;strong&gt;React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There’s just one catch: I don't know React very well yet.&lt;/p&gt;

&lt;p&gt;It’s going to be a challenging task, but I plan to tackle it head-on. Stay tuned, I’ll be sharing how I manage that learning curve in my next post.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>🚀 Event-Driven Architecture (EDA): The Power of Reacting to Events</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Mon, 03 Nov 2025 07:48:16 +0000</pubDate>
      <link>https://dev.to/ipazooki/event-driven-architecture-eda-the-power-of-reacting-to-events-1eb7</link>
      <guid>https://dev.to/ipazooki/event-driven-architecture-eda-the-power-of-reacting-to-events-1eb7</guid>
      <description>&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/jinuKuAwlx4"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;Hey everyone 👋&lt;/p&gt;

&lt;p&gt;Today, we’re diving into one of my favourite software architecture topics, &lt;strong&gt;Event-Driven Architecture (EDA)&lt;/strong&gt;. It’s one of those patterns that sounds a bit fancy at first, but once you understand it, you start seeing it &lt;em&gt;everywhere&lt;/em&gt;: in cloud applications, microservices, and even your daily notifications!&lt;/p&gt;

&lt;p&gt;Let’s break it down step by step. ☕&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 What Is Event-Driven Architecture?
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;strong&gt;Event-Driven Architecture&lt;/strong&gt; is all about &lt;em&gt;reacting to events&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;event&lt;/strong&gt; is simply &lt;em&gt;something that happened&lt;/em&gt;, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An order was placed 🛒&lt;/li&gt;
&lt;li&gt;A payment was completed 💳&lt;/li&gt;
&lt;li&gt;A user logged in 👤&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of having tightly coupled services that directly call each other (as in layered or traditional microservice architectures), &lt;strong&gt;EDA&lt;/strong&gt; uses &lt;em&gt;events&lt;/em&gt; as the main form of communication.&lt;/p&gt;

&lt;p&gt;Here’s where the magic happens ✨:&lt;br&gt;
In EDA, each service acts independently. When something happens, a service simply &lt;em&gt;publishes&lt;/em&gt; an event, it’s like saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, an order was placed!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But here’s the cool bit: the service that emits the event doesn’t know (or care) who is listening, when they’ll react, or how they’ll process it.&lt;/p&gt;

&lt;p&gt;That’s a big contrast to traditional architectures, where services often directly call one another through APIs.&lt;/p&gt;

&lt;p&gt;EDA, on the other hand, is &lt;em&gt;asynchronous&lt;/em&gt; and &lt;em&gt;decoupled&lt;/em&gt;. Services communicate via an &lt;strong&gt;event broker&lt;/strong&gt; (or message queue), meaning they’re completely independent; they just publish events into a queue without caring who processes them later.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Why EDA Matters
&lt;/h2&gt;

&lt;p&gt;This independence makes EDA:&lt;br&gt;
✅ Highly scalable&lt;br&gt;
✅ Fault-tolerant&lt;br&gt;
✅ Easier to evolve over time&lt;/p&gt;

&lt;p&gt;But it’s not always simple. While EDA offers powerful flexibility, it also introduces &lt;strong&gt;complexity&lt;/strong&gt;. So before jumping in, we need to answer a few important questions 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Key Questions to Understand EDA
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What’s the difference between an &lt;strong&gt;event&lt;/strong&gt; and a &lt;strong&gt;message&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How do we ensure &lt;strong&gt;no data loss&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How many &lt;strong&gt;brokers or queues&lt;/strong&gt; do we need?&lt;/li&gt;
&lt;li&gt;How do we &lt;strong&gt;track state&lt;/strong&gt; across multiple services?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s explore each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 Events vs. Messages
&lt;/h2&gt;

&lt;p&gt;In EDA, the main concept is an &lt;strong&gt;event&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When an event is raised, we don’t care who processes it or when. The system just publishes the event, &lt;em&gt;fire and forget&lt;/em&gt;. 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Events&lt;/strong&gt;: Fire and forget. The publisher emits and moves on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Messages&lt;/strong&gt;: Commands or queries, requests that expect a result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, in &lt;strong&gt;message-driven architecture&lt;/strong&gt;, a message waits for a response, while in &lt;strong&gt;event-driven architecture&lt;/strong&gt;, we publish and continue working asynchronously.&lt;/p&gt;

&lt;p&gt;Most EDA systems use a &lt;strong&gt;Pub/Sub pattern&lt;/strong&gt;, one service &lt;em&gt;publishes&lt;/em&gt; events and others &lt;em&gt;subscribe&lt;/em&gt; to them.&lt;br&gt;
In contrast, message-driven systems usually use &lt;strong&gt;point-to-point communication&lt;/strong&gt; since the sender knows exactly which service should handle the message.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Ensuring No Data Loss
&lt;/h2&gt;

&lt;p&gt;One of the biggest challenges in EDA is &lt;strong&gt;data integrity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A service publishes an event to a queue, but right after that, the queue crashes, and the event is gone! 😱&lt;/li&gt;
&lt;li&gt;Or maybe the consumer reads the event but fails before saving it to the database, and the data is lost again!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To prevent this, we can use the &lt;strong&gt;Event Forwarding Pattern&lt;/strong&gt; 🛡️&lt;/p&gt;

&lt;p&gt;Here’s how it helps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Persist Events&lt;/strong&gt;, Before a service sends an event to the queue, it first &lt;em&gt;persists&lt;/em&gt; it in durable storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recover Gracefully&lt;/strong&gt;, If a service crashes after reading an event, it can re-fetch it later because the queue retained a persisted copy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track Consumers&lt;/strong&gt;, Store client IDs so each service knows which messages it has processed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirm Completion&lt;/strong&gt;, After saving to the database, the service confirms success so the event can safely be removed from the queue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ensures strong data integrity ✅, but it comes with trade-offs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower performance (because of synchronous writes)&lt;/li&gt;
&lt;li&gt;Possible duplicate data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, use this approach when &lt;strong&gt;data reliability&lt;/strong&gt; is more important than &lt;strong&gt;throughput&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ How Many Brokers Do We Need?
&lt;/h2&gt;

&lt;p&gt;Good question! Should each microservice have its own broker, or should they all share one?&lt;/p&gt;

&lt;p&gt;Let’s look at the concept of &lt;strong&gt;Architectural Quantum&lt;/strong&gt;, introduced in &lt;em&gt;Building Evolutionary Architectures&lt;/em&gt; 🧠&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An &lt;em&gt;Architectural Quantum&lt;/em&gt; is an independently deployable component with high functional cohesion that includes everything needed for the system to work properly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If all services depend on a single broker, then if that broker goes down, &lt;em&gt;everything&lt;/em&gt; goes down.&lt;br&gt;
This means the entire system is one single &lt;em&gt;architectural quantum&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But if each service has its own broker, then you have multiple independent systems, more resilient, but also more expensive 💸.&lt;/p&gt;

&lt;p&gt;A balanced approach is the &lt;strong&gt;Domain Broker Pattern&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;em&gt;domain&lt;/em&gt; gets one broker.&lt;/li&gt;
&lt;li&gt;Services within a domain share the same broker.&lt;/li&gt;
&lt;li&gt;Domains remain independent of one another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you a nice balance between &lt;strong&gt;cost&lt;/strong&gt; and &lt;strong&gt;independence&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Managing State in EDA
&lt;/h2&gt;

&lt;p&gt;Tracking the state of an entity (like an order) across distributed services can be tricky. Let’s say you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;em&gt;Order Service&lt;/em&gt; 🛒&lt;/li&gt;
&lt;li&gt;An &lt;em&gt;Inventory Service&lt;/em&gt; 📦&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;Delivery Service&lt;/em&gt; 🚚&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a user asks, “What’s the status of my order?”, where should we look?&lt;/p&gt;

&lt;p&gt;There are two main patterns for managing state:&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Push-Based Pattern
&lt;/h3&gt;

&lt;p&gt;Each service writes status updates to a &lt;em&gt;shared queue&lt;/em&gt;.&lt;br&gt;
The &lt;em&gt;Order Service&lt;/em&gt; listens to this queue and keeps the latest status in its database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralized status tracking&lt;/li&gt;
&lt;li&gt;Easy to query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All services depend on one queue → &lt;em&gt;Architectural quantum = 1&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;A single failure can bring down the whole system&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2️⃣ Pull-Based Pattern
&lt;/h3&gt;

&lt;p&gt;In this model, a separate &lt;em&gt;Status Service&lt;/em&gt; listens to events from all brokers.&lt;br&gt;
It collects and stores the latest status for each order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No shared dependency,  more resilient&lt;/li&gt;
&lt;li&gt;Central point for querying order status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires building and maintaining an extra service&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Event-Driven Architecture is incredibly powerful; it enables &lt;strong&gt;scalable&lt;/strong&gt;, &lt;strong&gt;resilient&lt;/strong&gt;, and &lt;strong&gt;decoupled&lt;/strong&gt; systems. But like any architecture, it’s not a one-size-fits-all solution.&lt;/p&gt;

&lt;p&gt;EDA shines when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have many independent services that react to real-time changes&lt;/li&gt;
&lt;li&gt;You need asynchronous communication&lt;/li&gt;
&lt;li&gt;You care more about flexibility and responsiveness than strict performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it adds complexity in state management, data integrity, and broker design, so plan carefully before adopting it.&lt;/p&gt;




&lt;p&gt;Thanks for reading! 🙌&lt;br&gt;
If you found this useful, don’t forget to share it with your fellow developers and let’s keep learning together 💬&lt;/p&gt;

</description>
      <category>programming</category>
      <category>eventdriven</category>
      <category>tutorial</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Proper Logging in ASP.NET Core</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Wed, 19 Mar 2025 06:49:53 +0000</pubDate>
      <link>https://dev.to/ipazooki/proper-logging-in-aspnet-core-4l61</link>
      <guid>https://dev.to/ipazooki/proper-logging-in-aspnet-core-4l61</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/d6HPSdiP0lw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hey there, fellow code warriors! 👋 Today, we're diving deep into &lt;strong&gt;proper logging in ASP.NET Core&lt;/strong&gt;. If you've ever found yourself lost in a sea of mysterious bugs or scratching your head over your application's behaviour, this guide is your lighthouse! 🏝️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o2qdrcgih5ya884ehxt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o2qdrcgih5ya884ehxt.gif" alt="Logging details" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Logging Matters 🤔
&lt;/h2&gt;

&lt;p&gt;Before we jump into the code, let's talk about why logging is the unsung hero of software development. Proper logging is like giving your future self (and your team) a roadmap to understand what's happening in your application. It's not just about catching errors; it's about gaining insights, improving performance, and making your development life easier.&lt;/p&gt;

&lt;p&gt;Here's why logging is crucial for your projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Application Behavior Monitoring&lt;/strong&gt;: It's like having a 24/7 surveillance camera on your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Capturing&lt;/strong&gt;: Every important moment in your app's life, documented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Insights&lt;/strong&gt;: Because sometimes, your app needs a health check.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But logging isn't just about writing stuff down. It's part of a trio of concepts that make your applications robust, maintainable, and scalable:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Holy Trinity of Application Observability 🛠️
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Logging&lt;/strong&gt;: Your app's diary 📔&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Records events, errors, and important information&lt;/li&gt;
&lt;li&gt;Helps debug issues quickly&lt;/li&gt;
&lt;li&gt;Provides insights into application behaviour&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traceability&lt;/strong&gt;: Following the breadcrumbs of your code 🍞&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracks the flow of application processes&lt;/li&gt;
&lt;li&gt;Follows the lifecycle of requests or commands&lt;/li&gt;
&lt;li&gt;Especially helpful for distributed systems or microservices&lt;/li&gt;
&lt;li&gt;Facilitates debugging and enhances reliability&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt;: Measuring what matters 📊&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provides measurable data about application performance&lt;/li&gt;
&lt;li&gt;Helps make data-driven decisions&lt;/li&gt;
&lt;li&gt;Enhances user experiences through targeted optimizations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzntdde5tnisna1kfalx4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzntdde5tnisna1kfalx4.gif" alt="logging is a hero" width="520" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Logging with Serilog in ASP.NET Core 🛠️
&lt;/h2&gt;

&lt;p&gt;Let's roll up our sleeves and get our hands dirty with some code! We'll be using Serilog, a powerful logging library for .NET.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Serilog
&lt;/h3&gt;

&lt;p&gt;First, add the Serilog.AspNetCore NuGet package to your project. If you're planning to use Azure Application Insights, grab Serilog.Sinks.AzureApp too.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;Program.cs&lt;/code&gt;, set up Serilog like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ClearProviders&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSerilog&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFrom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code clears any existing logging providers and tells Serilog to read its configuration from the &lt;code&gt;appsettings.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring Serilog
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;appsettings.json&lt;/code&gt;, you can configure Serilog like a boss:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Serilog"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Using"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Serilog.Sinks.Console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"Serilog.Sinks.File"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"MinimumLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Information"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Override"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Microsoft"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warning"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"System"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warning"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"WriteTo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"theme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"outputTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"File"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Logs/log-.txt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"rollingInterval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"rollOnFileSizeLimit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"outputTemplate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"fileSizeLimitBytes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1073741824&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AzureApp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"instrumentationKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_instrumentation_key"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Enrich"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"FromLogContext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"WithMachineName"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"WithThreadId"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration sets up Serilog to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use both console and file sinks&lt;/li&gt;
&lt;li&gt;Set default log levels (Information for production, Debug for development)&lt;/li&gt;
&lt;li&gt;Write logs to the console and a file&lt;/li&gt;
&lt;li&gt;Send logs to Azure Application Insights&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Logging in Action: GlobalExceptionHandler 🎭
&lt;/h2&gt;

&lt;p&gt;Our &lt;code&gt;GlobalExceptionHandler&lt;/code&gt; class is like a superhero for exceptions. It catches them, logs them, and sends back a nicely formatted response to the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;ValueTask&lt;/span&gt; &lt;span class="nf"&gt;TryHandleAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpContext&lt;/span&gt; &lt;span class="n"&gt;httpContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (exception handling logic)&lt;/span&gt;

    &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"An error occurred while processing the request {DateTime} {Path}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// ... (return problem details)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class inherits from &lt;code&gt;IExceptionHandler&lt;/code&gt; and is registered in our dependency injection setup. It formats errors based on their type and logs them in a structured way before returning a user-friendly response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request Logging with LoggingBehaviour 🕵️
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;LoggingBehaviour&lt;/code&gt; class is our secret agent, tracking every request that passes through our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RequestHandlerDelegate&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Stopwatch&lt;/span&gt; &lt;span class="n"&gt;stopWatch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Stopwatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Handling request {Name}, {DateTime} "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// ... (request handling)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stopWatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ElapsedMilliseconds&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SlowRequestThresholdMilliseconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Request took too long to handle {Name}, {DateTime}, {ElapsedMilliseconds}ms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stopWatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ElapsedMilliseconds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Request handled successfully {Name}, {DateTime}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Request failed to handle {Name}, {DateTime}, {@Error}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ... (log success or failure)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This class implements &lt;code&gt;IPipelineBehavior&lt;/code&gt; from the MediatR library, acting as a pipeline for each request. It measures request duration, logs warnings for slow requests, and records the outcome of each request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pro Tips for Logging Like a Boss 😎
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use Structured Logging&lt;/strong&gt;: Always include relevant context in your logs. Serilog makes this easy with templates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Levels Matter&lt;/strong&gt;: Use the right log level for the right situation. Not everything is an error!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Matters&lt;/strong&gt;: Logging can impact performance, so use it wisely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensitive Data Alert&lt;/strong&gt;: Be careful not to log sensitive information. Your logs shouldn't be a security risk!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the "@" Symbol&lt;/strong&gt;: When logging objects with Serilog, use the "@" symbol (e.g., &lt;code&gt;{@Error}&lt;/code&gt;) to serialize the entire object. This makes querying logs easier, especially with tools like Seq.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping Up 🎁
&lt;/h2&gt;

&lt;p&gt;Proper logging is an essential skill for any developer working with ASP.NET Core. It's not just about catching errors; it's about gaining insights, improving performance, and making your development life easier.&lt;/p&gt;

&lt;p&gt;Remember, your logs are your best friend when things go wrong (and even when they don't). They're your application's black box, recording every important event and helping you understand what's happening under the hood.&lt;/p&gt;

&lt;p&gt;So, the next time you're debugging a tricky issue or trying to understand why your app is behaving weirdly, remember: that your logs are there to help. Happy logging, developers! 🚀&lt;/p&gt;

&lt;p&gt;The source code is available in my &lt;a href="https://github.com/iPazooki/CleanArchitecture" rel="noopener noreferrer"&gt;Github&lt;/a&gt; repo.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>aspnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>JWT Authentication &amp; Authorization in ASP.NET</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Tue, 04 Mar 2025 18:06:31 +0000</pubDate>
      <link>https://dev.to/ipazooki/jwt-authentication-authorization-in-aspnet-1j9</link>
      <guid>https://dev.to/ipazooki/jwt-authentication-authorization-in-aspnet-1j9</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZCoc8s1X2JY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hey everyone, welcome to our deep dive into JWTs in ASP.NET Core! Whether you’re a beginner or a seasoned developer, this article will guide you through the ins and outs of implementing secure authentication and authorization using JSON Web Tokens (JWT). Grab your favourite beverage, sit back, and let’s get started! 😊&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu33l7swkcxefz850h4g8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu33l7swkcxefz850h4g8.gif" alt="What is JWT" width="500" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is JWT? 🔍
&lt;/h2&gt;

&lt;p&gt;JWT stands for &lt;strong&gt;JSON Web Token&lt;/strong&gt;. Think of it as a digital passport that securely transmits information between parties. It’s &lt;strong&gt;compact&lt;/strong&gt;, &lt;strong&gt;URL-safe&lt;/strong&gt;, and &lt;strong&gt;self-contained&lt;/strong&gt;, meaning all the necessary data for authentication is right inside the token. A JWT consists of three key parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Header:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Specifies the token type and the hashing algorithm used (e.g., HMAC SHA256).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payload:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Contains the &lt;strong&gt;claims&lt;/strong&gt;—statements about an entity (usually the user) such as their ID, email, and roles. These claims are essential for both authentication and authorization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Signature:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ensures that the token hasn’t been tampered with. It’s created using the header, payload, and a secret key.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can explore JWTs and see their inner workings at &lt;a href="https://jwt.io" rel="noopener noreferrer"&gt;jwt.io&lt;/a&gt; 🔗.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl61k8ey1rof96dxa69ko.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl61k8ey1rof96dxa69ko.gif" alt="Authentication &amp;amp; Authorization" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does the Authentication &amp;amp; Authorization Process Work? 🛡️
&lt;/h2&gt;

&lt;p&gt;When a client sends a request to a secure API, here’s what happens behind the scenes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Request:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The client sends a request including the JWT in the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ASP.NET authentication provider extracts the JWT.
&lt;/li&gt;
&lt;li&gt;It validates the token’s signature, expiration, and issuer.
&lt;/li&gt;
&lt;li&gt;If valid, the user is authenticated.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authorization:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server checks if the user has the required &lt;strong&gt;claims&lt;/strong&gt; to access the resource.
&lt;/li&gt;
&lt;li&gt;If the claims match the required policy, access is granted; otherwise, a &lt;code&gt;403 Forbidden&lt;/code&gt; error is returned.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpbcizrkm95wiocckhyw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpbcizrkm95wiocckhyw.gif" alt="Policy-Based vs. Role-Based Access Control" width="513" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy-Based vs. Role-Based Access Control 🔐
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Role-Based Access Control (RBAC)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RBAC&lt;/strong&gt; assigns roles directly to users.
&lt;/li&gt;
&lt;li&gt;For example, only users with an &lt;strong&gt;Admin&lt;/strong&gt; role might access certain endpoints.
&lt;/li&gt;
&lt;li&gt;This method can become unwieldy as your user base grows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Policy-Based Access Control
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Policy-Based&lt;/strong&gt; access control defines policies (like &lt;code&gt;CanRead&lt;/code&gt;) that are assigned to roles.
&lt;/li&gt;
&lt;li&gt;When a user’s role changes, their permissions update automatically without modifying each user individually.
&lt;/li&gt;
&lt;li&gt;This approach is more flexible and scalable, especially for larger applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our demo, we focus on policy-based access control for that extra bit of flexibility!&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementing JWT in ASP.NET Core: A Step-by-Step Guide 💻
&lt;/h2&gt;

&lt;p&gt;Let’s walk through how to set up JWT authentication in an ASP.NET Core application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone the project
&lt;/h3&gt;

&lt;p&gt;Clone the project from &lt;a href="https://github.com/iPazooki/CleanArchitecture" rel="noopener noreferrer"&gt;Github&lt;/a&gt; and take a look at the authentication and authorisation configuration in the &lt;code&gt;DependencyInjection.cs&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAuthentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JwtBearerDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationScheme&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;AddJwtBearer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IAuthorizationHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PermissionAuthorizationHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IAuthorizationPolicyProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PermissionAuthorizationPolicyProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have all authentication configuration in the &lt;code&gt;JwtBearerOptionsSetup&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtBearerOptionsSetup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;JwtOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jwtOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;IPostConfigureOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;JwtBearerOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;JwtOptions&lt;/span&gt; &lt;span class="n"&gt;_jwtOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PostConfigure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;JwtBearerOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequireHttpsMetadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SaveToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TokenValidationParameters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TokenValidationParameters&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ValidateIssuer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ValidIssuer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ValidateAudience&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ValidAudience&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Audience&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ValidateIssuerSigningKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;IssuerSigningKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SymmetricSecurityKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretKey&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="n"&gt;ValidateLifetime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ClockSkew&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Zero&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup ensures that every token is validated against your issuer, audience, and signing key.&lt;/p&gt;

&lt;p&gt;To add permission authorisation, we have added two files &lt;code&gt;PermissionAuthorizationHandler&lt;/code&gt; and &lt;code&gt;PermissionAuthorizationPolicyProvider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;PermissionAuthorizationHandler&lt;/code&gt; we make sure that the request has enough permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PermissionAuthorizationHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AuthorizationHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PermissionRequirement&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;HandleRequirementAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthorizationHandlerContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PermissionRequirement&lt;/span&gt; &lt;span class="n"&gt;requirement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Claims&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToHashSet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requirement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Succeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requirement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, only requests with a valid JWT will be able to access these endpoints.&lt;/p&gt;

&lt;p&gt;Another important file is &lt;code&gt;JwtProvider&lt;/code&gt; which is responsible for creating the JWT token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;JwtOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jwtOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IPermissionService&lt;/span&gt; &lt;span class="n"&gt;permissionService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IJwtProvider&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;JwtOptions&lt;/span&gt; &lt;span class="n"&gt;_jwtOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GenerateJwtTokenAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Claim&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JwtRegisteredClaimNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JwtRegisteredClaimNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;!),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JwtRegisteredClaimNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Jti&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="n"&gt;HashSet&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;permissionService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPermissionsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;permission&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Permissions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

        &lt;span class="n"&gt;SigningCredentials&lt;/span&gt; &lt;span class="n"&gt;signingCredentials&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SymmetricSecurityKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecretKey&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;SecurityAlgorithms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HmacSha256&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;JwtSecurityToken&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Audience&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_jwtOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutMinutes&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;signingCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;signingCredentials&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JwtSecurityTokenHandler&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WriteToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all the configuration we need to know about JWT authentication and authorisation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrap-Up &amp;amp; Key Takeaways 📝
&lt;/h2&gt;

&lt;p&gt;Today, we explored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JWT Fundamentals:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Understanding JWT as a secure, compact way to transfer claims between parties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication &amp;amp; Authorization Flow:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
From initial user login to token validation and access control.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Policy-Based Access Control:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Offering flexibility over traditional role-based approaches by defining policies like &lt;code&gt;CanRead&lt;/code&gt; that are associated with roles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation in ASP.NET Core:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A step-by-step guide including configuration, creating a login endpoint, and securing your APIs with JWT.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing JWT in your ASP.NET Core applications not only simplifies authentication but also scales beautifully with your growing user base. If you have any questions or feedback, feel free to drop a comment below!&lt;/p&gt;

&lt;p&gt;Happy coding! 💻✨&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>learning</category>
      <category>security</category>
    </item>
    <item>
      <title>🚀Clean Architecture in .NET</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Tue, 11 Feb 2025 15:51:35 +0000</pubDate>
      <link>https://dev.to/ipazooki/clean-architecture-in-net-1hid</link>
      <guid>https://dev.to/ipazooki/clean-architecture-in-net-1hid</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/C-BYhrlJiRU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hello, fellow developers! 👋 Hope you’re doing well.  &lt;/p&gt;

&lt;p&gt;In the world of &lt;strong&gt;software architecture&lt;/strong&gt;, structuring our code properly is crucial for &lt;strong&gt;maintainability, scalability, and testability&lt;/strong&gt;. In our last discussion, we explored different architectural patterns, including &lt;strong&gt;Hexagonal Architecture, Layered Architecture, Onion Architecture&lt;/strong&gt;, and &lt;strong&gt;Clean Architecture&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Today, we’re going to &lt;strong&gt;dive deep into Clean Architecture&lt;/strong&gt;, what it is, why it matters, and how we can implement it in a real-world &lt;strong&gt;.NET&lt;/strong&gt; application. 💡  &lt;/p&gt;

&lt;p&gt;The full source code is available on &lt;a href="https://github.com/iPazooki/CleanArchitecture" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, so feel free to download it and follow along! 🛠️  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What is Clean Architecture?&lt;/strong&gt; 🤔
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt;, introduced by &lt;strong&gt;Uncle Bob (Robert C. Martin)&lt;/strong&gt;, is a &lt;strong&gt;domain-centric&lt;/strong&gt; approach that helps us build software that is:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Flexible&lt;/strong&gt; – Easy to swap technologies (databases, frameworks, UI).&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Maintainable&lt;/strong&gt; – Well-structured code with minimal dependencies.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Testable&lt;/strong&gt; – Business logic remains independent of external concerns.  &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Layer Breakdown 🏗️&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Clean Architecture is structured into &lt;strong&gt;four key layers&lt;/strong&gt;:  &lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;Domain Layer (Core Business Logic)&lt;/strong&gt; – Contains entities, value objects, and domain services.&lt;br&gt;&lt;br&gt;
2️⃣ &lt;strong&gt;Application Layer (Use Cases &amp;amp; CQRS)&lt;/strong&gt; – Defines business rules, CQRS commands/queries, and interfaces.&lt;br&gt;&lt;br&gt;
3️⃣ &lt;strong&gt;Infrastructure Layer (Implementations &amp;amp; DB Access)&lt;/strong&gt; – Implements interfaces from the Application Layer.&lt;br&gt;&lt;br&gt;
4️⃣ &lt;strong&gt;Presentation Layer (API/UI Controllers)&lt;/strong&gt; – Exposes the functionality via endpoints or UI.  &lt;/p&gt;

&lt;p&gt;At its core, Clean Architecture follows the &lt;strong&gt;Dependency Rule&lt;/strong&gt;:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Inner layers should not depend on outer layers.&lt;/strong&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that &lt;strong&gt;business logic is independent&lt;/strong&gt; of frameworks, databases, and UI technologies. 🚀  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Implementing Clean Architecture in .NET&lt;/strong&gt; 🏗️
&lt;/h2&gt;

&lt;p&gt;Let’s break down how we’ve structured a &lt;strong&gt;.NET application&lt;/strong&gt; using Clean Architecture principles.  &lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;1️⃣ Domain Layer – The Heart of Clean Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Domain Layer&lt;/strong&gt; is the &lt;strong&gt;most important part&lt;/strong&gt; of Clean Architecture. It contains:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Entities&lt;/strong&gt; (&lt;code&gt;Book&lt;/code&gt;, &lt;code&gt;Person&lt;/code&gt;) – Define core data structures.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Value Objects&lt;/strong&gt; (&lt;code&gt;Genre&lt;/code&gt;, &lt;code&gt;Address&lt;/code&gt;) – Immutable objects with validation.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;BaseEntity &amp;amp; BaseAuditableEntity&lt;/strong&gt; – Common properties like &lt;code&gt;Id&lt;/code&gt;, &lt;code&gt;CreatedDate&lt;/code&gt;, &lt;code&gt;UpdatedDate&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Domain Exceptions&lt;/strong&gt; (&lt;code&gt;UnsupportedGenreException&lt;/code&gt;) – Custom exceptions for domain-level errors.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Domain Events&lt;/strong&gt; – Handling important business events.  &lt;/p&gt;

&lt;p&gt;A key decision here:&lt;br&gt;&lt;br&gt;
📌 &lt;strong&gt;Using &lt;code&gt;DateTimeOffset&lt;/code&gt; instead of &lt;code&gt;DateTime&lt;/code&gt;&lt;/strong&gt; ensures &lt;strong&gt;proper time zone handling&lt;/strong&gt; across different regions.  &lt;/p&gt;

&lt;p&gt;👉 The &lt;strong&gt;Domain Layer has no dependencies&lt;/strong&gt; on external frameworks or databases, keeping it &lt;strong&gt;pure and reusable&lt;/strong&gt;.  &lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2️⃣ Application Layer – Business Logic &amp;amp; CQRS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Application Layer&lt;/strong&gt; is where we define &lt;strong&gt;use cases and business rules&lt;/strong&gt;. It consists of:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;CQRS (Command Query Responsibility Segregation)&lt;/strong&gt; – Separating read and write operations.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Interfaces&lt;/strong&gt; (e.g., &lt;code&gt;IEmailService&lt;/code&gt;) – Abstractions for external dependencies.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Command Handlers&lt;/strong&gt; (&lt;code&gt;CreateBookCommandHandler&lt;/code&gt;, &lt;code&gt;DeleteBookCommandHandler&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Validation Rules&lt;/strong&gt; – Using &lt;strong&gt;FluentValidation&lt;/strong&gt; to enforce constraints.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Unit of Work Pattern&lt;/strong&gt; – Ensuring atomic transactions.  &lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Key concept&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commands&lt;/strong&gt; modify data (&lt;code&gt;CreateBookCommand&lt;/code&gt;, &lt;code&gt;UpdateBookCommand&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queries&lt;/strong&gt; retrieve data (&lt;code&gt;GetBookByIdQuery&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Application Layer only contains interfaces&lt;/strong&gt;, keeping it decoupled from the infrastructure.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;3️⃣ Infrastructure Layer – Implementation Details&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Infrastructure Layer&lt;/strong&gt; provides &lt;strong&gt;concrete implementations&lt;/strong&gt; of the interfaces defined in the &lt;strong&gt;Application Layer&lt;/strong&gt;. It includes:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Entity Framework Core (EF Core) Configuration&lt;/strong&gt; – Setting up database persistence.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;ApplicationDbContext&lt;/strong&gt; – The actual database context.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Unit of Work Implementation&lt;/strong&gt; – Managing transactions efficiently.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Email Service Implementation&lt;/strong&gt; – Sending emails using external services.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Global Exception Handling&lt;/strong&gt; – Standardizing error responses.  &lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Infrastructure should depend on Application&lt;/strong&gt;, not the other way around. This keeps the &lt;strong&gt;core logic flexible&lt;/strong&gt; while allowing technology choices to change without affecting the domain.  &lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;4️⃣ Presentation Layer – Exposing APIs &amp;amp; Dependency Injection&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Presentation Layer&lt;/strong&gt; (CleanArchitecture.API) is the &lt;strong&gt;entry point&lt;/strong&gt; of the application, responsible for:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;API Controllers&lt;/strong&gt; – Handling requests and responses.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Swagger Documentation&lt;/strong&gt; – Interactive API documentation.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Dependency Injection (DI) Setup&lt;/strong&gt; – Registering services.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Global Exception Handling&lt;/strong&gt; – Formatting errors consistently.  &lt;/p&gt;

&lt;p&gt;📌 In &lt;code&gt;Program.cs&lt;/code&gt;, we wire everything together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddApplicationServices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInfrastructureServices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPresentationServices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures &lt;strong&gt;all dependencies are properly injected&lt;/strong&gt; across the application.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Key Benefits of Clean Architecture&lt;/strong&gt; 🏆
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Separation of Concerns&lt;/strong&gt; – Code is modular and easier to maintain.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Scalability&lt;/strong&gt; – Easily swap out technologies without major refactoring.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Testability&lt;/strong&gt; – Business logic remains independent and can be tested in isolation.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Flexibility&lt;/strong&gt; – The application can evolve over time with minimal disruption.  &lt;/p&gt;

&lt;p&gt;By following this structure, we ensure our &lt;strong&gt;.NET applications&lt;/strong&gt; are &lt;strong&gt;robust, maintainable, and scalable&lt;/strong&gt;. 🚀  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping Up &amp;amp; Next Steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;That’s a complete walkthrough of &lt;strong&gt;Clean Architecture in .NET&lt;/strong&gt;! 🎉  &lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;What’s Next?&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 Download the &lt;strong&gt;source code&lt;/strong&gt; from my GitHub repo and try it yourself!
&lt;/li&gt;
&lt;li&gt;👍 If you found this helpful, &lt;strong&gt;give it a star&lt;/strong&gt; on GitHub!
&lt;/li&gt;
&lt;li&gt;📢 Have questions? &lt;strong&gt;Drop a comment below!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔔 &lt;strong&gt;Subscribe&lt;/strong&gt; for more &lt;strong&gt;.NET &amp;amp; Software Architecture&lt;/strong&gt; content!
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading, and happy coding! 🎯  &lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>dotnet</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Blue-Green Deployment with Azure</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Wed, 22 Jan 2025 07:16:54 +0000</pubDate>
      <link>https://dev.to/ipazooki/blue-green-deployment-with-azure-2g42</link>
      <guid>https://dev.to/ipazooki/blue-green-deployment-with-azure-2g42</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EtpCEs2_xtM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hello, everyone! In this article, we’re diving into &lt;strong&gt;Blue-Green Deployment&lt;/strong&gt;, a brilliant technique for rolling out updates without breaking a sweat—or your app.  &lt;/p&gt;

&lt;p&gt;Here’s what we’ll cover:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;What is Blue-Green Deployment?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Pros and Cons&lt;/strong&gt;—because no approach is perfect.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When Should You Use It?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step-by-Step Demo with Azure&lt;/strong&gt;—complete with automation tips to make your life easier.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, grab a cuppa ☕ and let’s get started! 🚀  &lt;/p&gt;




&lt;h2&gt;
  
  
  What is Blue-Green Deployment? 🤔
&lt;/h2&gt;

&lt;p&gt;Imagine you’ve got two versions of your application running—one is "Blue" (your live environment), and the other is "Green" (your shiny new version).  &lt;/p&gt;

&lt;p&gt;Instead of directly updating the live version and risking downtime, you deploy changes to the Green environment first. Once you’re sure everything’s working perfectly, you simply swap traffic from Blue to Green. Users won’t notice a thing—except the new features! 🎉  &lt;/p&gt;

&lt;p&gt;Think of it like swapping stage sets in a play between scenes—seamless and smooth. 🎭  &lt;/p&gt;




&lt;h2&gt;
  
  
  The Pros and Cons 🛠️
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero Downtime&lt;/strong&gt;: No 'under maintenance' messages—just uninterrupted service.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Rollbacks&lt;/strong&gt;: Found a bug? Flip back to Blue and fix it.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-like Testing&lt;/strong&gt;: Test your new version in a real-world environment.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better User Experience&lt;/strong&gt;: Smooth updates = happy users.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cons:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Higher Costs&lt;/strong&gt;: You’re running two environments, which can double infrastructure costs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Setup&lt;/strong&gt;: Managing two environments isn’t simple—it requires planning and good tools.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Synchronisation&lt;/strong&gt;: Handling databases and real-time data can get tricky.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing Overheads&lt;/strong&gt;: Blue and Green must be identical apart from the new features.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  When Should You Use It? 🎯
&lt;/h2&gt;

&lt;p&gt;Blue-Green Deployment shines when downtime isn’t an option—think e-commerce sites, banking systems, or services that need constant availability.  &lt;/p&gt;

&lt;p&gt;If you’re working on a smaller project or have a tight budget, the added complexity and cost might not be worth it.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Demo with Azure 🖥️
&lt;/h2&gt;

&lt;p&gt;Let’s put theory into practice! I’ll guide you through setting up Blue-Green Deployment using Azure.  &lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1: Create a Web App 🌐
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Set up a &lt;strong&gt;resource group&lt;/strong&gt; called &lt;code&gt;BlueGreenResource&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;web app&lt;/strong&gt; named &lt;code&gt;BlueGreenWebApp&lt;/code&gt;. Use &lt;code&gt;.NET 8&lt;/code&gt;, deploy to &lt;em&gt;UK South&lt;/em&gt;, and choose the &lt;em&gt;Standard S1&lt;/em&gt; pricing tier.
&lt;/li&gt;
&lt;li&gt;Disable &lt;strong&gt;App Insights&lt;/strong&gt; (optional for simple setups).
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 2: Publish the First Version ✅
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use Visual Studio to deploy your app to the live environment.
&lt;/li&gt;
&lt;li&gt;This is &lt;strong&gt;version 1&lt;/strong&gt;, which users can now see. 🎉
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 3: Add a Staging Slot 🛠️
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;staging slot&lt;/strong&gt; to your web app. It’ll have its own domain (e.g., &lt;code&gt;staging.bluegreenwebapp.azurewebsites.net&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Publish &lt;strong&gt;version 2&lt;/strong&gt; to this staging slot. Users won’t see this version yet, but it’s ready for testing.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 4: Swap the Slots 🔄
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Once QA approves, use the &lt;strong&gt;Swap&lt;/strong&gt; button in Azure to swap the staging slot with the live slot. Now, users are on &lt;strong&gt;version 2&lt;/strong&gt;! 🎊
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 5: Clean Up 🧹
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Delete the staging slot to save costs.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Automate the Process with Azure DevOps 🤖
&lt;/h3&gt;

&lt;p&gt;To avoid manual effort, we’ll set up a CI/CD pipeline in Azure DevOps:  &lt;/p&gt;

&lt;h4&gt;
  
  
  Build Pipeline (YAML File):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;vmImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;windows-latest'&lt;/span&gt;

&lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;solution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**/*.sln'&lt;/span&gt;
  &lt;span class="na"&gt;buildPlatform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Any&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CPU'&lt;/span&gt;
  &lt;span class="na"&gt;buildConfiguration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Release'&lt;/span&gt;

&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NuGetToolInstaller@1&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NuGetCommand@2&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;restoreSolution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(solution)'&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DotNetCoreCLI@2&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;**/*.csproj'&lt;/span&gt;
    &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--configuration&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$(buildConfiguration)'&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DotNetCoreCLI@2&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish&lt;/span&gt;
    &lt;span class="na"&gt;publishWebProjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;
    &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--configuration&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$(BuildConfiguration)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--output&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$(Build.ArtifactStagingDirectory)'&lt;/span&gt;
    &lt;span class="na"&gt;zipAfterPublish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;True&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PublishPipelineArtifact@1&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;targetPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(Build.ArtifactStagingDirectory)'&lt;/span&gt; 
    &lt;span class="na"&gt;artifactName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deploymentapp-artifact'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline triggers on changes to the &lt;code&gt;master&lt;/code&gt; branch. It builds the app, restores NuGet packages, and creates deployment artifacts.  &lt;/p&gt;




&lt;h4&gt;
  
  
  Release Pipeline:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Staging Slot&lt;/strong&gt;:
Use this script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   az webapp deployment slot create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;webAppName&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;resourceGroupName&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--slot&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;slotName&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy to Staging&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Set the staging slot as the target in the pipeline.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Swap Slots&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Use the &lt;strong&gt;Azure App Service Manage&lt;/strong&gt; task to swap environments.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delete Staging Slot&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Clean up with this script:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   az webapp deployment slot delete &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;webAppName&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;resourceGroupName&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--slot&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;slotName&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Testing the Setup 🚀
&lt;/h3&gt;

&lt;p&gt;Push changes to the &lt;code&gt;master&lt;/code&gt; branch, and watch the magic happen:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build triggers automatically.
&lt;/li&gt;
&lt;li&gt;Deployment to the staging slot occurs.
&lt;/li&gt;
&lt;li&gt;QA approves the changes.
&lt;/li&gt;
&lt;li&gt;Slots are swapped, and the staging slot is deleted.
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final Thoughts 💡
&lt;/h2&gt;

&lt;p&gt;Blue-Green Deployment makes updates safer, faster, and smoother, especially for critical systems. While it’s not without challenges, automation tools like Azure DevOps make it easier to manage.  &lt;/p&gt;

&lt;p&gt;Have you tried Blue-Green Deployment? Share your experiences in the comments! 👇 Don’t forget to like, share, and bookmark this article for future reference. 😊  &lt;/p&gt;

</description>
      <category>azure</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Generic Class &amp; Constraints in C#</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sun, 05 Jan 2025 13:36:58 +0000</pubDate>
      <link>https://dev.to/ipazooki/generic-class-constraints-in-c-48n7</link>
      <guid>https://dev.to/ipazooki/generic-class-constraints-in-c-48n7</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Tf8KtZPDQEs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Generics are one of the most powerful tools in C#, enabling reusable, type-safe, and flexible code. But with great power comes great responsibility, and that’s where &lt;strong&gt;constraints&lt;/strong&gt; on generics come into play. In this article, we’ll dive deep into generic constraints in C#, starting from the basics and progressing to advanced use cases.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need Generics?
&lt;/h2&gt;

&lt;p&gt;Let’s first understand why generics exist. Imagine you’re writing a class to process integers and strings. Without generics, you’d need to write separate methods or overloads for each type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Processor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing integer: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing string: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this works, it quickly becomes unmanageable if you need to handle multiple types like &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, or custom objects. The code becomes verbose, error-prone, and harder to maintain.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Enter Generics
&lt;/h3&gt;

&lt;p&gt;Generics solves this problem by allowing you to write a single class or method that works with any type. Here’s how the same &lt;code&gt;Processor&lt;/code&gt; class looks with generics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;intProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;intProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stringProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;stringProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With generics, the &lt;code&gt;Processor&lt;/code&gt; class works with any type, eliminating redundancy and ensuring type safety.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Class-Level vs Method-Level Generics
&lt;/h2&gt;

&lt;p&gt;When working with generics, you can define them at the class level or method level.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Class-Level Generics:&lt;/strong&gt; Use when the type parameter applies to the entire class.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method-Level Generics:&lt;/strong&gt; Use when you need type flexibility for only a specific method.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Class-level generic&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_items&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; added to storage."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Method-level generic&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Utility&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Printing: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, storage!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Utility&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Understanding Generic Constraints
&lt;/h2&gt;

&lt;p&gt;While generics are flexible, sometimes you need to restrict what types can be used. Constraints allow you to enforce specific requirements, such as the type being a value type, a reference type, or implementing an interface.  &lt;/p&gt;

&lt;p&gt;Let’s explore the various constraints and their usage.  &lt;/p&gt;




&lt;h3&gt;
  
  
  1. Value Type Constraint (&lt;code&gt;struct&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;struct&lt;/code&gt; constraint ensures that the type parameter is a value type, such as &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, or a custom struct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ValueProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing value: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;intProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ValueProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;intProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;floatProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ValueProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;floatProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;99.99f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is perfect for scenarios where you’re working with numeric types, enums, or other non-nullable structures.  &lt;/p&gt;




&lt;h3&gt;
  
  
  2. Reference Type Constraint (&lt;code&gt;class&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;class&lt;/code&gt; constraint ensures that the type parameter is a reference type, such as &lt;code&gt;string&lt;/code&gt; or a custom object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReferenceProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing reference: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stringProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ReferenceProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;stringProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Reference!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;objectProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ReferenceProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;objectProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"C#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is ideal for working with objects that support nullability.  &lt;/p&gt;




&lt;h3&gt;
  
  
  3. Nullable Types
&lt;/h3&gt;

&lt;p&gt;If you want to allow &lt;strong&gt;nullable value types&lt;/strong&gt;, you can use a nullable type in your constraint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NullableProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessNullable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Processing nullable value: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;nullableIntProcessor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NullableProcessor&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;nullableIntProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessNullable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;nullableIntProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessNullable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is great for handling scenarios like optional parameters or database fields that may contain null values.  &lt;/p&gt;




&lt;h3&gt;
  
  
  4. Constructor Constraint (&lt;code&gt;new()&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;new()&lt;/code&gt; constraint ensures that the type parameter has a parameterless constructor, allowing you to create new instances.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InstanceCreator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;T&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InstanceCreator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StringBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from InstanceCreator!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful when you need to instantiate objects dynamically.  &lt;/p&gt;




&lt;h3&gt;
  
  
  5. Interface and Multiple Constraints
&lt;/h3&gt;

&lt;p&gt;You can combine multiple constraints to enforce stricter rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IEntity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_items&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Added entity with ID: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Laptop"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;T&lt;/code&gt; must:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Be a reference type (&lt;code&gt;class&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;Implement the &lt;code&gt;IEntity&lt;/code&gt; interface.
&lt;/li&gt;
&lt;li&gt;Have a parameterless constructor (&lt;code&gt;new()&lt;/code&gt;).
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This combination provides structure and consistency for your types.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Generics and their constraints are indispensable tools for writing reusable, type-safe, and maintainable code in C#. Whether you’re enforcing type safety or structuring your code better, constraints help you achieve flexibility without sacrificing reliability.  &lt;/p&gt;

&lt;p&gt;Take some time to experiment with these constraints in your projects, and see how they can simplify your codebase!  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;What’s your favourite use case for generics? Let me know in the comments!&lt;/em&gt; &lt;/p&gt;

</description>
      <category>csharp</category>
      <category>tutorial</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>Evolution of Software Architecture</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sat, 07 Dec 2024 13:14:02 +0000</pubDate>
      <link>https://dev.to/ipazooki/evolution-of-software-architecture-3ja8</link>
      <guid>https://dev.to/ipazooki/evolution-of-software-architecture-3ja8</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/rBNb3xHJUZk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Exploring the Evolution of Software Architecture
&lt;/h2&gt;

&lt;p&gt;Hello everyone! 👋 Welcome back to the channel where we dive into the world of software development, one fascinating concept at a time. Today, we're embarking on a journey through the &lt;strong&gt;evolution of software architecture&lt;/strong&gt;—from the foundational &lt;strong&gt;Layered Architecture&lt;/strong&gt;, through &lt;strong&gt;Hexagonal&lt;/strong&gt; and &lt;strong&gt;Onion Architecture&lt;/strong&gt;, all the way to the increasingly popular &lt;strong&gt;Clean Architecture&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Have you ever wondered:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How did these architectural patterns come to be?
&lt;/li&gt;
&lt;li&gt;Why do some designs suit certain applications better than others?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As Jamie, my colleague, says: &lt;em&gt;"It depends—no one architecture fits all."&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;By the end of this article, you'll have a clear understanding of these styles, their historical progression, key principles, and practical applications. Whether you're new to software architecture or a seasoned developer looking for a refresher, this one's for you! 🎉  &lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Layered Architecture: The Starting Point
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Layered Architecture&lt;/strong&gt; (a.k.a. N-tier architecture) breaks a system into distinct layers like:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Presentation Layer&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Business Logic Layer (BLL)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Access Layer (DAL)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Features:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Easy to understand, implement, and use.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structure&lt;/strong&gt;: The Presentation Layer depends on the BLL, which in turn depends on the DAL.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this creates &lt;strong&gt;tight coupling&lt;/strong&gt; between layers, making the system rigid and hard to scale. Architects have since evolved designs to address these limitations.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b4a51o1bphcjnz2mn8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1b4a51o1bphcjnz2mn8a.png" alt="Layered Architecture" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔧 Making Business Logic the Focal Point
&lt;/h3&gt;

&lt;p&gt;To improve the architecture:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shift dependency to the &lt;strong&gt;business logic layer&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Introduce &lt;strong&gt;interfaces&lt;/strong&gt; like:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IRepository&lt;/code&gt; in the core, with its implementation in the DAL.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IEmailService&lt;/code&gt; to abstract email communication systems.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This strategy gives rise to &lt;strong&gt;Hexagonal Architecture&lt;/strong&gt;, enhancing modularity and flexibility.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9a6u5i1xvaqpuqqixgoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9a6u5i1xvaqpuqqixgoa.png" alt="Business Logic Layer" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11gzfy6likf3sfss776n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11gzfy6likf3sfss776n.png" alt="Interfaces" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔷 Hexagonal Architecture: Breaking Free from Coupling
&lt;/h2&gt;

&lt;p&gt;Also called the &lt;strong&gt;Ports and Adapters&lt;/strong&gt; pattern, Hexagonal Architecture emphasises &lt;strong&gt;business logic&lt;/strong&gt; as the core of the system.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Visualising the Structure:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary (Driving) Adapters&lt;/strong&gt;: User interfaces like CLI or APIs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secondary (Driven) Adapters&lt;/strong&gt;: External systems like databases or email services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core Application&lt;/strong&gt;: Processes requests and directs flows.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system interacts with external dependencies via &lt;strong&gt;ports (interfaces)&lt;/strong&gt; and &lt;strong&gt;adapters (implementations)&lt;/strong&gt;, enabling a loosely coupled design. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb4i6lx5xnfz3sdea1yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmb4i6lx5xnfz3sdea1yf.png" alt="Hexagonal Architecture" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌀 Onion Architecture: A Step Further
&lt;/h2&gt;

&lt;p&gt;Building on hexagonal principles, &lt;strong&gt;Onion Architecture&lt;/strong&gt; arranges systems into &lt;strong&gt;concentric circles&lt;/strong&gt;:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Domain Models and Business Rules&lt;/strong&gt;: At the centre.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Services and Infrastructure&lt;/strong&gt;: Surrounding layers.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Core Principles:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Inversion&lt;/strong&gt;: Outer layers depend on inner layers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Changes to UI or external systems don't affect business logic.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design supports &lt;strong&gt;testability&lt;/strong&gt; and aligns well with &lt;strong&gt;Agile development&lt;/strong&gt; practices. 🎯  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzx0oz8ji1dcclnda9jm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzx0oz8ji1dcclnda9jm.png" alt="Onion Architecture" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04hvflrlorjp0e2cyfrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04hvflrlorjp0e2cyfrz.png" alt="Onion Architecture" width="708" height="697"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Clean Architecture: The Best of All Worlds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt; simplifies earlier patterns while retaining their strengths.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Highlights:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Business Rules at the Centre&lt;/strong&gt;: The domain layer handles all core logic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus on Use Cases&lt;/strong&gt;: Emphasises &lt;em&gt;what the system does&lt;/em&gt; rather than &lt;em&gt;how it achieves it&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple implementations for &lt;code&gt;IEmail&lt;/code&gt; can exist, but the &lt;strong&gt;Web UI layer&lt;/strong&gt; decides which to use dynamically.
&lt;/li&gt;
&lt;li&gt;Independence from frameworks makes systems more &lt;strong&gt;maintainable&lt;/strong&gt; and &lt;strong&gt;adaptable&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk677rvs5vj8rnz3fm2he.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk677rvs5vj8rnz3fm2he.png" alt="Clean Architecture" width="698" height="697"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🛠️ From Hexagonal to Clean Architecture
&lt;/h3&gt;

&lt;p&gt;The journey from Hexagonal to Clean Architecture focuses on:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Making the application core resilient to changes.
&lt;/li&gt;
&lt;li&gt;Enhancing maintainability by layering the core logically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqp32jkjvj3h4to9ihr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqp32jkjvj3h4to9ihr0.png" alt="Hexagonal to Clean Architecture" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Summary of the Journey
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Layered Architecture&lt;/strong&gt;: Introduced clear separations but had tight coupling.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hexagonal Architecture&lt;/strong&gt;: Decoupled business logic via ports and adapters.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onion Architecture&lt;/strong&gt;: Emphasised domain models with dependency inversion.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Architecture&lt;/strong&gt;: Focused on simplicity, use cases, and maintainability.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each pattern represents a step forward in designing &lt;strong&gt;robust&lt;/strong&gt;, &lt;strong&gt;scalable&lt;/strong&gt;, and &lt;strong&gt;adaptable&lt;/strong&gt; systems. 💡  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qvphizlcfyzpsm36c6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qvphizlcfyzpsm36c6x.png" alt="Summary" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That wraps up our deep dive into software architecture! From foundational layers to the elegance of Clean Architecture, we've traced how these patterns evolved and adapted over time. Hopefully, you've gained insights to inspire your next project.  &lt;/p&gt;

&lt;p&gt;If you enjoyed this, please:&lt;br&gt;&lt;br&gt;
👍 Like&lt;br&gt;&lt;br&gt;
📢 Share&lt;br&gt;&lt;br&gt;
💬 Comment below!  &lt;/p&gt;

&lt;p&gt;Thanks for reading, and I'll see you in the next one. Cheers! ☕ &lt;/p&gt;

</description>
      <category>architecture</category>
      <category>community</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>Fundamentals of Software Architecture</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Sat, 19 Oct 2024 08:15:07 +0000</pubDate>
      <link>https://dev.to/ipazooki/fundamentals-of-software-architecture-44ia</link>
      <guid>https://dev.to/ipazooki/fundamentals-of-software-architecture-44ia</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/IfpKsJWlhhw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hey everyone! 👋 Welcome back to the channel! If you’re new here, hit that like button so you don’t miss out on any of our upcoming content. Today we’re diving into the &lt;em&gt;fundamentals&lt;/em&gt; of software architecture, an incredibly important topic for developers and tech enthusiasts alike. By the end of this video, you'll have a solid understanding of what software architecture is and why it’s crucial for building scalable and reliable software systems.&lt;/p&gt;

&lt;p&gt;We'll also cover the differences between &lt;em&gt;architecture patterns&lt;/em&gt; and &lt;em&gt;architecture styles&lt;/em&gt;, two terms that often confuse people but are key to designing great systems.&lt;/p&gt;

&lt;p&gt;So let's jump right in!" 🚀  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What Is Software Architecture?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So let’s start with the basics: &lt;em&gt;what exactly is software architecture&lt;/em&gt;? In simple terms, software architecture is all about making critical decisions on how your system is structured and functions, while keeping the business's needs in mind. At its core, architecture is about the important stuff. It’s the foundation that holds the entire system together.&lt;/p&gt;

&lt;p&gt;What’s a great architecture for one project might be totally wrong for another because business requirements vary. For example, if the business needs to handle massive user loads quickly, your architecture should be designed with performance in mind. But if cost is a higher priority, you may need to design with efficiency and cost-saving strategies. &lt;/p&gt;

&lt;p&gt;In short, there isn’t a &lt;em&gt;single&lt;/em&gt; correct architecture for every scenario—it’s all about tailoring your system to meet the specific goals of the business! 🏗️  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Who is a Software Architect?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now &lt;em&gt;who&lt;/em&gt; exactly is a software architect? It sounds a bit mysterious, doesn’t it? Some might think architects are mythical beings who know everything about every technology out there! 🧙‍♂️ Well, not quite! A software architect bridges the gap between the technical and business sides of things.&lt;/p&gt;

&lt;p&gt;Software architects need a mix of &lt;em&gt;technical&lt;/em&gt; and &lt;em&gt;soft skills&lt;/em&gt;. They’re familiar with various architecture styles, frameworks, and anti-patterns but also need to be excellent communicators. Architects work closely with developers, stakeholders, and sometimes clients to ensure everyone is aligned on the system’s goals.&lt;/p&gt;

&lt;p&gt;And here’s the thing—becoming a software architect isn’t always a straightforward path. It’s a journey filled with experience, learning, and a deep understanding of solving complex problems. 🎯&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Four Pillars of Software Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s talk about the &lt;em&gt;four key pillars&lt;/em&gt; of software architecture:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Structure or Style&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Characteristics&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture Decisions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design Principles&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structure or Style&lt;/strong&gt;: How is your system organized? Are you building a &lt;em&gt;monolithic&lt;/em&gt; system, or are you using &lt;em&gt;microservices&lt;/em&gt;? Maybe an &lt;em&gt;event-driven&lt;/em&gt; approach is best. Each style affects how your system functions and scales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture Characteristics&lt;/strong&gt;: These are the non-negotiables—your &lt;em&gt;functional&lt;/em&gt; and &lt;em&gt;non-functional&lt;/em&gt; requirements. Do you need high &lt;em&gt;availability&lt;/em&gt;? What about &lt;em&gt;scalability&lt;/em&gt; or &lt;em&gt;performance&lt;/em&gt;? These characteristics shape your architectural decisions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture Decisions&lt;/strong&gt;: These are the high-level rules you set. For instance, you might decide that only the &lt;em&gt;business logic&lt;/em&gt; layer interacts with the database directly. 🗂️ Decisions like this help maintain structure and consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Design Principles&lt;/strong&gt;: This is where implementation happens! What technologies will you use? Maybe you'll opt for &lt;em&gt;CQRS&lt;/em&gt;, &lt;em&gt;Clean Architecture&lt;/em&gt;, or &lt;em&gt;asynchronous programming&lt;/em&gt;. 💡&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture Pattern vs. Architecture Style&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s clear up a common confusion: &lt;em&gt;What’s the difference between an architecture pattern and an architecture style&lt;/em&gt;? 🤔&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture Pattern&lt;/strong&gt;: A solution to a specific problem. For example, the &lt;em&gt;CQRS&lt;/em&gt; (Command Query Responsibility Segregation) pattern helps separate &lt;em&gt;write&lt;/em&gt; and &lt;em&gt;read&lt;/em&gt; operations, making your system more efficient for certain scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture Style&lt;/strong&gt;: This is the overall structure of your system. Are you designing with &lt;em&gt;microservices&lt;/em&gt;, a &lt;em&gt;layered architecture&lt;/em&gt;, or something else entirely? Your choice here dictates how the system is organized, but not how individual problems are solved. 🏗️  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;We’ve only scratched the surface of software architecture today. Next time, we’ll dive deeper into patterns like &lt;em&gt;Clean Architecture&lt;/em&gt; and explore the benefits of &lt;em&gt;asynchronous programming&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you enjoyed the content, don’t forget to subscribe and hit the notification bell so you won’t miss out. Until next time, take care and happy coding! 💻  &lt;/p&gt;

</description>
      <category>software</category>
      <category>architecture</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Software Architecture: A Journey Through Time 🕰️</title>
      <dc:creator>Mo</dc:creator>
      <pubDate>Fri, 04 Oct 2024 05:39:52 +0000</pubDate>
      <link>https://dev.to/ipazooki/software-architecture-a-journey-through-time-map</link>
      <guid>https://dev.to/ipazooki/software-architecture-a-journey-through-time-map</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Ad5F968YTI8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Hello everyone! Hope you're all doing well! 😊 In today’s post, we’re diving into the fascinating world of &lt;em&gt;Software Architecture&lt;/em&gt;. We'll journey through its history, explore the &lt;em&gt;differences between architecture and design&lt;/em&gt;, and clarify the often-confused terms &lt;em&gt;software architecture&lt;/em&gt; and &lt;em&gt;software design&lt;/em&gt;. So, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief History of Software Architecture 🏛️
&lt;/h2&gt;

&lt;p&gt;To truly appreciate software architecture as we know it today, we need to rewind the clock and explore how it evolved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1950s&lt;/strong&gt;: The early days of computing, where coding was mostly low-level and done in assembly languages. The concept of "architecture" didn't exist yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1960s&lt;/strong&gt;: The rise of &lt;em&gt;structured programming&lt;/em&gt; and the birth of &lt;em&gt;object-oriented programming (OOP)&lt;/em&gt;, marking the first steps towards modularity and component-based design. A small step for programming, but a giant leap for architecture! 🚀&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Late 1960s&lt;/strong&gt;: Enter &lt;em&gt;monolithic architectures&lt;/em&gt;—systems where everything was built as one large unit. People started theorising about how to structure software, laying the groundwork for more sophisticated architectures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1970s&lt;/strong&gt;: Big innovations like &lt;em&gt;microkernel architecture&lt;/em&gt; came along. This modular design had a core system (the microkernel) surrounded by components. Plus, &lt;em&gt;event-driven programming&lt;/em&gt; made it possible for systems to respond to events, creating a more dynamic interaction between modules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1978&lt;/strong&gt;: The rise of &lt;em&gt;Client-Server architecture&lt;/em&gt;. Initially, servers handled everything, but soon the &lt;em&gt;Model-View-Controller (MVC)&lt;/em&gt; pattern was introduced to divide responsibilities more efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;1980s &amp;amp; 1990s&lt;/strong&gt;: More refined architectures came into play like &lt;em&gt;Command-Query Separation (CQS)&lt;/em&gt;. This was also the era when the web browser was born! 🌐 With the rise of the internet, architectures like &lt;em&gt;Service-Oriented Architecture (SOA)&lt;/em&gt; and &lt;em&gt;Domain-Driven Design (DDD)&lt;/em&gt; emerged.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;2000s&lt;/strong&gt;: The modern age of &lt;em&gt;Microservices&lt;/em&gt;, &lt;em&gt;Onion Architecture&lt;/em&gt;, &lt;em&gt;CQRS&lt;/em&gt; (Command Query Responsibility Segregation), and &lt;em&gt;Clean Architecture&lt;/em&gt;. These patterns are designed for scalability, maintainability, and modularity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Architecture vs Design 🏗️🛠️
&lt;/h2&gt;

&lt;p&gt;Let’s clear up a common point of confusion: what's the difference between &lt;em&gt;software architecture&lt;/em&gt; and &lt;em&gt;software design&lt;/em&gt;? 🤔&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture&lt;/strong&gt;: The Big Picture
&lt;/h3&gt;

&lt;p&gt;Think of architecture as the &lt;em&gt;blueprint&lt;/em&gt; of your system. It defines the structure, how components interact, and the guiding principles like scalability and modularity.&lt;/p&gt;

&lt;p&gt;For example, in C#, you might decide that your system will follow a &lt;em&gt;Microservices&lt;/em&gt; architecture to ensure modularity and ease of scaling. Here’s how you might define a service in C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_userRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetUserByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The architect's role is to ensure that this blueprint serves both the business's functional and non-functional requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Design&lt;/strong&gt;: The Nitty-Gritty Details
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Design&lt;/em&gt; is where the actual implementation happens. If architecture is the &lt;em&gt;what&lt;/em&gt;, design is the &lt;em&gt;how&lt;/em&gt;. While architecture decides the overall structure, design dives into the technical aspects, like which libraries to use and how classes will be structured.&lt;/p&gt;

&lt;p&gt;For instance, in our Microservices example, design would focus on &lt;em&gt;how&lt;/em&gt; the &lt;code&gt;UserService&lt;/code&gt; interacts with the repository, which libraries are employed, and which coding patterns (like Dependency Injection) are used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUserRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the architecture stays the same (we still have a service and a repository), but the &lt;em&gt;design&lt;/em&gt; handles the specifics of &lt;em&gt;how&lt;/em&gt; data is fetched from a database.&lt;/p&gt;




&lt;h2&gt;
  
  
  Software Architecture vs Software Design 🔍
&lt;/h2&gt;

&lt;p&gt;It’s easy to confuse these terms, but they serve different purposes. To simplify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Software Architecture&lt;/strong&gt; is the &lt;em&gt;high-level&lt;/em&gt; structure of a system. It deals with how the system is divided into components, how data flows between those components, and which architectural pattern (e.g. monolithic, microservices) is best suited to solve the problem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Software Design&lt;/strong&gt; is the &lt;em&gt;low-level&lt;/em&gt; implementation. It focuses on fleshing out the architecture with specific libraries, technologies, and coding techniques.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine you’re building a house 🏡. The &lt;em&gt;architecture&lt;/em&gt; is like the blueprint, determining how rooms and spaces are arranged. The &lt;em&gt;design&lt;/em&gt;, on the other hand, would be things like which materials to use for the walls, the placement of electrical wiring, and the style of windows. Both are crucial, but they address different levels of the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up 🎁
&lt;/h2&gt;

&lt;p&gt;In summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Software Architecture&lt;/strong&gt; focuses on the big picture: the structure, modularity, and high-level organisation of a system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software Design&lt;/strong&gt; is all about the technical implementation: choosing the right tools and ensuring everything works efficiently within the architectural framework.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding the &lt;em&gt;history of software architecture&lt;/em&gt; helps us see why different patterns like &lt;em&gt;Microservices&lt;/em&gt; or &lt;em&gt;Clean Architecture&lt;/em&gt; emerged and how they continue to shape modern software development. 💻&lt;/p&gt;

&lt;p&gt;In our next article (and video!), we’ll dive deeper into architectural patterns like &lt;em&gt;Clean Architecture&lt;/em&gt; vs &lt;em&gt;Microservices&lt;/em&gt; and discuss how they can impact your projects.&lt;/p&gt;

&lt;p&gt;Stay tuned, and happy coding! 👨‍💻👩‍💻&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
