<?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: Majdi Zlitni</title>
    <description>The latest articles on DEV Community by Majdi Zlitni (@majdizlitni).</description>
    <link>https://dev.to/majdizlitni</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%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg</url>
      <title>DEV Community: Majdi Zlitni</title>
      <link>https://dev.to/majdizlitni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/majdizlitni"/>
    <language>en</language>
    <item>
      <title>Augmented Coding Patterns: The Developer's Playbook for Working With AI</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Fri, 06 Feb 2026 11:19:11 +0000</pubDate>
      <link>https://dev.to/majdizlitni/augmented-coding-patterns-the-developers-playbook-for-working-with-ai-4pbc</link>
      <guid>https://dev.to/majdizlitni/augmented-coding-patterns-the-developers-playbook-for-working-with-ai-4pbc</guid>
      <description>&lt;h2&gt;
  
  
  AI as your new pair partner but are you using it right?
&lt;/h2&gt;

&lt;p&gt;Every developer I know has tried AI-assisted coding but most are doing it wrong.&lt;/p&gt;

&lt;p&gt;They paste code, get output, accept or reject. Rinse, repeat. That's not augmented coding that's autocomplete with extra steps.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://lexler.github.io/augmented-coding-patterns/" rel="noopener noreferrer"&gt;&lt;strong&gt;Augmented Coding Patterns&lt;/strong&gt;&lt;/a&gt; project created by Lada Kesseler&lt;br&gt;
changes that. &lt;br&gt;
It's a living catalog of &lt;strong&gt;patterns&lt;/strong&gt;, &lt;strong&gt;anti-patterns&lt;/strong&gt;, and &lt;strong&gt;obstacles&lt;/strong&gt; that define how developers should truly collaborate with LLMs in their daily workflow.&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%2F5eji2bms3wmdmmtrd3sm.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%2F5eji2bms3wmdmmtrd3sm.png" alt="Augmented Coding: Mapping the Uncharted Territory" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What Are Augmented Coding Patterns?
&lt;/h2&gt;

&lt;p&gt;Think of them like the Gang of Four design patterns but for human-AI collaboration. They're recurring solutions to recurring problems that arise when you use LLMs (Claude, GPT, Copilot, etc.) as coding partners.&lt;/p&gt;

&lt;p&gt;The catalog is organized into three pillars:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;What It Covers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Patterns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proven techniques that work feedback loops, semantic zooming, visible context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Anti-Patterns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Traps developers fall into blind trust, context starvation, over-delegation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Obstacles&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inherent limitations of LLMs you must design around&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Pattern 1: Feedback Loops
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You give the AI a big task. It gives you 200 lines. You read them, find 3 bugs, rewrite half of it. You just wasted 15 minutes.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Pattern
&lt;/h3&gt;

&lt;p&gt;Build &lt;strong&gt;small, iterative cycles&lt;/strong&gt;. Ask for one function. Validate. Ask for the next. Correct course early.&lt;/p&gt;
&lt;h3&gt;
  
  
  Real Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Anti-pattern (one-shot prompting):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Build me a complete ASP.NET Core REST API with authentication,
JWT, validation, rate limiting, and SQL Server integration for a Todo app."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern (feedback loop):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1: "Create the Express server setup with CORS and JSON middleware."
→ Review → Approve

Step 2: "Add a POST /api/todos route with Zod validation for title (string, 
required) and completed (boolean, default false)."
→ Review → Fix the Zod schema import → Approve

Step 3: "Add JWT middleware. Here's my auth flow: [describe]."
→ Review → Adjust token expiry → Approve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each iteration is small enough to validate in under 60 seconds. Errors are caught before they compound.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation in Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Step 1&lt;/em&gt;: You ask AI to scaffold the validation layer&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Step 2&lt;/em&gt;: You ask AI to create the route handler using your schema&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Step 3&lt;/em&gt;: You review: AI used &lt;code&gt;safeParse&lt;/code&gt; correctly, returns flattened errors.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Step 4&lt;/em&gt;: Let's say it didn't add the &lt;code&gt;userId&lt;/code&gt; from JWT. You correct: "Add &lt;code&gt;userId&lt;/code&gt; from &lt;code&gt;req.user.id&lt;/code&gt; to the created todo."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key: &lt;strong&gt;never let more than 30 lines go unreviewed&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pattern 2: Semantic Zooming
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You're stuck at one level of abstraction. Either you're in the weeds asking about semicolons, or you're at 30,000 feet asking "how should I architect this?"&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Shift between levels deliberately.&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start high (architecture)&lt;/li&gt;
&lt;li&gt;Toom to mid-level (module design)&lt;/li&gt;
&lt;li&gt;Dive to low-level (implementation)&lt;/li&gt;
&lt;li&gt;Zoom out to verify the big picture still holds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZOOM LEVEL 1 Architecture:
"I'm building a notification service. I need to support email, SMS, and push notifications. What's the best pattern? I want it extensible."

AI Response: Strategy pattern + factory + message queue.

ZOOM LEVEL 2 Module Design:
"Show me the interface for the NotificationStrategy and the factory that selects the right one."

ZOOM LEVEL 3 Implementation:
"Implement the EmailStrategy using AWS SES. Here are my SES configuration constraints: [details]."

ZOOM BACK TO LEVEL 1:
"Given what we've built, does this architecture handle the case where SMS fails and we need to retry with exponential backoff? What needs to change?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each zoom level gives the AI the right amount of context to produce useful output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 1: &lt;em&gt;The architecture AI suggested&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Level 2: &lt;em&gt;The factory&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Level 3: &lt;em&gt;The implementation&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Pattern 3: Visible Context Show Your Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;You ask the AI to fix a bug but don't show it the error message, the test that failed, or the surrounding code. It hallucinates a solution for a problem it can't see.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Externalize everything the AI needs&lt;/strong&gt;: error logs, test output, type definitions, database schemas, business rules. Make the invisible visible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Context-starved prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"My user registration is broken. Fix it."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Context-rich prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"My user registration throws this error:

  PrismaClientKnownRequestError: Unique constraint failed 
  on the fields: (`email`)

Here's my register function: [paste code]
Here's my Prisma schema for User: [paste schema]
Here's the test that fails: [paste test]

The test creates a user, then tries to create another with 
the same email. I expect a 409 Conflict response but I'm 
getting a 500."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI now has a crystal-clear picture and can respond with accurate response.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Top 3 Anti-Patterns to Avoid
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Blind Trust
&lt;/h3&gt;

&lt;p&gt;Never accept AI output without reading it. Period. The AI doesn't know your business rules, your deployment constraints, or your team conventions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Context Starvation
&lt;/h3&gt;

&lt;p&gt;The less context you give, the more the AI hallucinates. Every prompt should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Relevant code&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Errors&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Types&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Over-Delegation
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;"Build me a production-ready microservices architecture"&lt;/code&gt; is not a prompt it's a prayer. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break it down&lt;/li&gt;
&lt;li&gt;Own the decisions&lt;/li&gt;
&lt;li&gt;AI will handle the implementation&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The developers who will thrive in the AI era aren't the ones who prompt the best. They're the ones who &lt;strong&gt;collaborate&lt;/strong&gt; the best.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;References:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lexler.github.io/augmented-coding-patterns/" rel="noopener noreferrer"&gt;&lt;em&gt;Augmented Coding Patterns&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://soundcloud.com/heavybit/o11ycast-ep-87-augmented-coding-patterns-with-lada-kesseler" rel="noopener noreferrer"&gt;&lt;em&gt;O11ycast Ep. #87: Augmented Coding Patterns with Lada Kesseler&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lexler/augmented-coding-patterns" rel="noopener noreferrer"&gt;&lt;em&gt;Augmented-coding-patterns GitHub Repo&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A reading first GH-300 cert prep: what to study, what to skip, and what actually matters</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sun, 28 Dec 2025 18:50:27 +0000</pubDate>
      <link>https://dev.to/majdizlitni/a-reading-first-gh-300-cert-prep-what-to-study-what-to-skip-and-what-actually-matters-3n6</link>
      <guid>https://dev.to/majdizlitni/a-reading-first-gh-300-cert-prep-what-to-study-what-to-skip-and-what-actually-matters-3n6</guid>
      <description>&lt;h2&gt;
  
  
  How I passed the GH-300 (GitHub copilot) certification
&lt;/h2&gt;

&lt;p&gt;In this blog I will explains how I prepared for the &lt;strong&gt;GH-300 GitHub Copilot certification&lt;/strong&gt;, what resources actually mattered, and what I learned especially if you prefer &lt;strong&gt;reading over watching videos&lt;/strong&gt;, like I do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is GH-300?&lt;/li&gt;
&lt;li&gt;Exam basics (quick Facts)&lt;/li&gt;
&lt;li&gt;Assessment&lt;/li&gt;
&lt;li&gt;Main course I used (core resource)&lt;/li&gt;
&lt;li&gt;
What I learned the most

&lt;ul&gt;
&lt;li&gt;Principles of prompt engineering&lt;/li&gt;
&lt;li&gt;How Copilot learns from our prompts&lt;/li&gt;
&lt;li&gt;How GitHub copilot processes our input&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Extra Microsoft learn modules I found useful&lt;/li&gt;

&lt;li&gt;GitHub and advanced topics I explored&lt;/li&gt;

&lt;li&gt;Practice questions&lt;/li&gt;

&lt;li&gt;My final tips&lt;/li&gt;

&lt;li&gt;Final thoughts&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is GH-300?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GH-300&lt;/strong&gt; is a Microsoft certification exam focused on &lt;strong&gt;GitHub Copilot&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
It validates the ability to &lt;strong&gt;use GitHub Copilot effectively and responsibly&lt;/strong&gt; in real-world development workflows.&lt;/p&gt;

&lt;p&gt;Key topics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsible AI (7%)&lt;/li&gt;
&lt;li&gt;GitHub copilot plans and features (31%)&lt;/li&gt;
&lt;li&gt;How GitHub copilot works and handles data (15%)&lt;/li&gt;
&lt;li&gt;Prompt crafting and prompt engineering (9%)&lt;/li&gt;
&lt;li&gt;Testing with GitHub copilot (9%)&lt;/li&gt;
&lt;li&gt;Privacy fundamentals and context exclusions (15%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details provided by Microsoft on their &lt;a href="https://learn.microsoft.com/en-us/credentials/certifications/resources/study-guides/gh-300" rel="noopener noreferrer"&gt;exam study guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check the official: Microsoft course &lt;a href="https://learn.microsoft.com/en-us/training/courses/gh-300t00" rel="noopener noreferrer"&gt;GH-300T00-A: GitHub Copilot&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Exam basics (quick facts)
&lt;/h2&gt;

&lt;p&gt;What you need to know before the exam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exam code:&lt;/strong&gt; GH-300
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passing score:&lt;/strong&gt; 700 / 1000&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duration:&lt;/strong&gt; 1 hour 40 minutes
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questions:&lt;/strong&gt; ~60–65
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format:&lt;/strong&gt; Multiple choice, multiple answer, scenario-based
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Generally easy, especially if you already use GitHub Copilot in your IDE&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Assessment
&lt;/h2&gt;

&lt;p&gt;You can check your knowledge and try the &lt;a href="https://learn.microsoft.com/en-us/credentials/certifications/practice-assessments-for-microsoft-certifications" rel="noopener noreferrer"&gt;official practical exam&lt;/a&gt; which is free and a great way to identify your weak areas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Main course I used (core resource)
&lt;/h2&gt;

&lt;p&gt;I relied primarily on the &lt;a href="https://learn.microsoft.com/en-us/training/courses/gh-300t00" rel="noopener noreferrer"&gt;&lt;strong&gt;Microsoft Learn GH-300 course&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this worked for me
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Text-based content&lt;/li&gt;
&lt;li&gt;Easy to skim and navigate&lt;/li&gt;
&lt;li&gt;Clear learning objectives&lt;/li&gt;
&lt;li&gt;No unnecessary fluff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since I prefer &lt;strong&gt;reading over videos&lt;/strong&gt;, this format let me focus on what matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned the most
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Principles of prompt engineering
&lt;/h3&gt;

&lt;h4&gt;
  
  
  The 4 Ss of prompt engineering
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single&lt;/strong&gt; → One well-defined task
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specific&lt;/strong&gt; → Clear and explicit instructions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short&lt;/strong&gt; → Concise, straight to the point
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surround&lt;/strong&gt; → Use descriptive filenames &amp;amp; keep related files open for context
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This alone improves Copilot output dramatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Practical example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BAD: "Write a function"

GOOD: "Write a TypeScript function that validates email addresses using regex. Include error handling and return a Boolean."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;How Copilot learns from our prompts&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero-shot learning&lt;/strong&gt;&lt;br&gt;
The model generates an answer based only on your prompt, without any examples.&lt;br&gt;&lt;br&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%2F3vj48wxt3q5mzy7b51x3.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%2F3vj48wxt3q5mzy7b51x3.png" alt="Zero-shot learning" width="749" height="230"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One-shot learning&lt;/strong&gt;&lt;br&gt;
The model is given one example along with the prompt, helping it understand the desired format or logic.&lt;br&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%2Frv2mysry3chiq2a00bht.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%2Frv2mysry3chiq2a00bht.png" alt="One-shot learning" width="698" height="317"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Few-shot learning&lt;/strong&gt;&lt;br&gt;
The model is provided with several examples in the prompt, allowing it to better generalize and produce more accurate or relevant outputs.&lt;br&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%2Fijdaa5y5gvzn3cfn250m.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%2Fijdaa5y5gvzn3cfn250m.png" alt="Few-shot learning" width="800" height="842"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  How GitHub copilot processes our input
&lt;/h3&gt;

&lt;p&gt;Understanding this helps with both &lt;strong&gt;exam questions&lt;/strong&gt; and &lt;strong&gt;real usage&lt;/strong&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%2Fjew2qp5xh0gnjed3k5t6.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%2Fjew2qp5xh0gnjed3k5t6.png" alt="Data processing" width="800" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Secure prompt transmission&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Your prompt is securely sent to GitHub servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy filtering&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Blocks prompt injection attacks&lt;/li&gt;
&lt;li&gt;Prevents system manipulation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toxicity filtering&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Blocks hate speech&lt;/li&gt;
&lt;li&gt;Filters inappropriate content&lt;/li&gt;
&lt;li&gt;Redacts detected personal data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code generation using LLMs&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Models trained on public code&lt;/li&gt;
&lt;li&gt;Generates based on context and prompts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 If you want to see my detailed study notes you can check it via &lt;a href="https://www.notion.so/GitHub-Copilot-Microsoft-learn-Course-2d1610a9edd080068d92d750cedcee0f" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Extra Microsoft learn modules I found useful
&lt;/h2&gt;

&lt;p&gt;These are &lt;strong&gt;not strictly required&lt;/strong&gt; for GH-300, but they clarify concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/training/modules/introduction-to-github-copilot-enterprise/" rel="noopener noreferrer"&gt;Introduction to GitHub Copilot Enterprise&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/training/modules/introduction-to-github-copilot-for-business/" rel="noopener noreferrer"&gt;Copilot for Business&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/training/paths/accelerate-app-development-using-github-copilot/" rel="noopener noreferrer"&gt;Accelerate app development using Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/training/modules/introduction-vibe-coding/" rel="noopener noreferrer"&gt;Introduction to Vibe Coding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  GitHub and advanced topics I explored
&lt;/h2&gt;

&lt;p&gt;These helped me understand &lt;strong&gt;real-world usage&lt;/strong&gt; beyond the exam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://resources.github.com/learn/pathways/copilot/essentials/how-github-copilot-handles-data/" rel="noopener noreferrer"&gt;How Copilot handles data&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/copilot" rel="noopener noreferrer"&gt;Official Copilot docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/training/modules/spec-driven-development-github-spec-kit-enterprise-developers/" rel="noopener noreferrer"&gt;Spec-driven development with GitHub Spec Kit&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/training/modules/code-reviews-pull-requests-github-copilot/4-issues-early-automated-reviews-copilot" rel="noopener noreferrer"&gt;Code reviews &amp;amp; PR issues with Copilot&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/training/modules/mcp-server/3-configure-connect" rel="noopener noreferrer"&gt;MCP Server setup in VS Code&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Practice questions
&lt;/h2&gt;

&lt;p&gt;This open source &lt;a href="https://github.com/FidelusAleksander/ghcertified" rel="noopener noreferrer"&gt;repo&lt;/a&gt; is a life saving because it contain really good practical questions with explanations and hints directing to official sources you can check it &lt;a href="https://ghcertified.com/practice_tests/copilot/" rel="noopener noreferrer"&gt;practical copilot exam&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%2Fukyqh8u33965u16yzsyg.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%2Fukyqh8u33965u16yzsyg.png" alt="ghcertified" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exam-style practice questions&lt;/li&gt;
&lt;li&gt;Detailed explanations for each answer&lt;/li&gt;
&lt;li&gt;Links directing to official Microsoft Learn resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a question dump&lt;/strong&gt; it's a legitimate study project to help people pass GitHub certifications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Final Tips
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DO:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;strong&gt;practice assessments&lt;/strong&gt; to identify gaps&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Microsoft Learn&lt;/strong&gt;, it's the source of truth&lt;/li&gt;
&lt;li&gt;Focus on &lt;strong&gt;concepts and reasoning&lt;/strong&gt;, not memorization&lt;/li&gt;
&lt;li&gt;Understand &lt;strong&gt;why&lt;/strong&gt; Copilot behaves the way it does&lt;/li&gt;
&lt;li&gt;Study &lt;strong&gt;Responsible AI&lt;/strong&gt; thoroughly it's heavily weighted&lt;/li&gt;
&lt;li&gt;Practice &lt;strong&gt;prompt engineering&lt;/strong&gt; with real examples&lt;/li&gt;
&lt;li&gt;Review &lt;strong&gt;enterprise features&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DON'T:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skip the "boring" sections on ethics and privacy&lt;/li&gt;
&lt;li&gt;Memorize answers without understanding reasoning&lt;/li&gt;
&lt;li&gt;Ignore the official study guide&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;GH-300 is &lt;strong&gt;not&lt;/strong&gt; about being a "Copilot power user." It's about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understanding how Copilot works&lt;/strong&gt; data flow, security, limitations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using it responsibly&lt;/strong&gt; ethics, bias awareness, copyright considerations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrating it effectively&lt;/strong&gt; real developer workflows, best practices&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowing when to trust (and distrust) AI-generated code&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good luck!&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>certification</category>
      <category>learning</category>
      <category>github</category>
    </item>
    <item>
      <title>Learning resources I used, where to practice your knowledge and how you can earned your GitHub cert too.</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 25 Oct 2025 17:10:31 +0000</pubDate>
      <link>https://dev.to/majdizlitni/learning-resources-i-used-where-to-practice-your-knowledge-and-how-you-can-earned-your-github-cert-3o0d</link>
      <guid>https://dev.to/majdizlitni/learning-resources-i-used-where-to-practice-your-knowledge-and-how-you-can-earned-your-github-cert-3o0d</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dumb.dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af" class="crayons-story__hidden-navigation-link"&gt;I’ve earned my GitHub Foundations Certification for that I’ve shared my learning resources, and how you can earned your GitHub cert too.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-status"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/majdizlitni" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg" alt="majdizlitni profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/majdizlitni" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Majdi Zlitni
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Majdi Zlitni
                
              
              &lt;div id="story-author-preview-content-2960075" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/majdizlitni" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Majdi Zlitni&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dumb.dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 25 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-status"&gt;
        &lt;a href="https://dumb.dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af" id="article-link-2960075"&gt;
          I’ve earned my GitHub Foundations Certification for that I’ve shared my learning resources, and how you can earned your GitHub cert too.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__contentpreview text-styles"&gt;
          &lt;div class="ltag__link"&gt;
  &lt;a href="/majdizlitni" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg" alt="majdizlitni"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/majdizlitni/how-you-can-earned-your-github-certification-lessons-resources-the-story-behind-mona-the-octocat-hhh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How You can Earn Your GitHub Certification; Lessons, Resources &amp;amp; the Story Behind Mona the Octocat&lt;/h2&gt;
      &lt;h3&gt;Majdi Zlitni ・ Oct 25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#git&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dumb.dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>github</category>
      <category>git</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I’ve earned my GitHub Foundations Certification for that I’ve shared my learning resources, and how you can earned your GitHub cert too.</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 25 Oct 2025 17:08:32 +0000</pubDate>
      <link>https://dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af</link>
      <guid>https://dev.to/majdizlitni/ive-earned-my-github-foundations-certification-for-that-ive-shared-my-learning-resources-and-how-31af</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/majdizlitni" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg" alt="majdizlitni"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/majdizlitni/how-you-can-earned-your-github-certification-lessons-resources-the-story-behind-mona-the-octocat-hhh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How You can Earn Your GitHub Certification; Lessons, Resources &amp;amp; the Story Behind Mona the Octocat&lt;/h2&gt;
      &lt;h3&gt;Majdi Zlitni ・ Oct 25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#git&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>github</category>
      <category>git</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How You can Earn Your GitHub Certification; Lessons, Resources &amp; the Story Behind Mona the Octocat</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 25 Oct 2025 15:31:47 +0000</pubDate>
      <link>https://dev.to/majdizlitni/how-you-can-earned-your-github-certification-lessons-resources-the-story-behind-mona-the-octocat-hhh</link>
      <guid>https://dev.to/majdizlitni/how-you-can-earned-your-github-certification-lessons-resources-the-story-behind-mona-the-octocat-hhh</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The mascot behind the GitHub logo&lt;/li&gt;
&lt;li&gt;The fun story behind Mona the GitHub mascot&lt;/li&gt;
&lt;li&gt;GitHub Certification&lt;/li&gt;
&lt;li&gt;Exam Details&lt;/li&gt;
&lt;li&gt;My Study Method&lt;/li&gt;
&lt;li&gt;Key Lesson&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The mascot behind the GitHub logo
&lt;/h2&gt;

&lt;p&gt;In the early days of GitHub (around 2008), the founders wanted something fun for their &lt;strong&gt;error pages&lt;/strong&gt;, specifically the &lt;a href="https://github.com/404" rel="noopener noreferrer"&gt;&lt;em&gt;404 Not Found&lt;/em&gt; page&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%2Fr65m5r7aqzseedhunzej.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%2Fr65m5r7aqzseedhunzej.png" alt="GitHub 404 Not Found page" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They bought a stock illustration from &lt;strong&gt;iStockphoto&lt;/strong&gt; created by &lt;a href="https://the-development.github.io/thedevelopment/posts/2014/02/24/simon-oxley.html" rel="noopener noreferrer"&gt;Simon Oxley&lt;/a&gt;, the same artist who designed the &lt;strong&gt;original Twitter bird&lt;/strong&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%2Fvbn865s6axlfkxa3v9b5.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%2Fvbn865s6axlfkxa3v9b5.png" alt="Original Twitter bird by Simon Oxley" width="286" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That illustration was called &lt;strong&gt;“Octopuss”&lt;/strong&gt;, a cute half-cat, half-octopus standing in a puddle.  &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%2F6rkqe10zbttrzscqet8a.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%2F6rkqe10zbttrzscqet8a.png" alt="The Octopuss, by Simon Oxley" width="290" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When GitHub used it, they renamed it &lt;strong&gt;“Octocat”&lt;/strong&gt; for obvious reasons😹.&lt;/p&gt;

&lt;p&gt;Later, GitHub designer &lt;a href="https://cameronmcefee.com" rel="noopener noreferrer"&gt;Cameron McEfee&lt;/a&gt; gave Mona her unique identity and created themed variations to expand on the Octocat for various internal uses, including slide decks, blog posts, and event promotions. He began illustrating the Octocat in different costumes and with different personalities, which proved to be very popular.&lt;br&gt;
&lt;a href="https://octodex.github.com" rel="noopener noreferrer"&gt;&lt;br&gt;
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia4.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExYjJjY2Z3Z3Nud2w0eDVjZWpjY2xnYnhwa3E1MGphaDk0ZHh1amZscSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2Fu1983FQL1LJksc89W9%2Fgiphy.gif" alt="GitHub Octodex GIF" width="480" height="270"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The fun story behind Mona the GitHub mascot
&lt;/h2&gt;

&lt;p&gt;In the early days of GitHub, the daughter of one of GitHub’s developers fell in love with the Octocat. In that love, she wrote a story.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Once upon a time, there was a cat whose name was Monalisa. Monalisa and her owner went to the beach. When Monalisa got to the beach, her owner Kelly gave her goggles so Monalisa could swim and see what was in the ocean. When Monalisa went in the water she found lots of fish. When Monalisa was swimming she was so excited she opened her mouth and swallowed a coral that made you grow legs like an octopus but keep your normal face. So Monalisa grew legs and became Mrs. Monalisa Octocat. [sic]&lt;/p&gt;
&lt;/blockquote&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%2Fa8cy8u0f0ofb7s386epb.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%2Fa8cy8u0f0ofb7s386epb.png" alt="Mona the GitHub mascot" width="451" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Octocat is more than a logo; it is a &lt;strong&gt;symbol of creativity, curiosity, and collaboration&lt;/strong&gt; which are the values that reflect GitHub’s developer community.  &lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Certification
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;GitHub Foundations Certification&lt;/strong&gt; validates your understanding of:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub’s &lt;strong&gt;core features&lt;/strong&gt; (repos, branching, pull requests)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration tools&lt;/strong&gt; (Issues, Projects, Discussions)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions &amp;amp; Automation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Compliance features&lt;/strong&gt; (like Dependabot, code scanning)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Billing &amp;amp; licensing models&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are a student with the &lt;a href="https://education.github.com/pack" rel="noopener noreferrer"&gt;GitHub Student Developer Pack&lt;/a&gt;, you receive a one-time &lt;strong&gt;free passing voucher&lt;/strong&gt;, so you can save &lt;strong&gt;$99 USD&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Exam Details
&lt;/h2&gt;

&lt;p&gt;The exam duration is &lt;strong&gt;120 minutes&lt;/strong&gt;, so you can get &lt;strong&gt;~1.6 minutes/question&lt;/strong&gt; with a total of &lt;strong&gt;75 questions&lt;/strong&gt; in &lt;strong&gt;multiple-choice&lt;/strong&gt; and &lt;strong&gt;multiple-answer&lt;/strong&gt; formats.&lt;/p&gt;

&lt;p&gt;The passing score is &lt;strong&gt;700/1000&lt;/strong&gt;. You can take the exam either in a &lt;strong&gt;test center&lt;/strong&gt; or &lt;strong&gt;online&lt;/strong&gt;; I prefer the test center to avoid the extensive online proctoring process.&lt;/p&gt;

&lt;p&gt;There is &lt;strong&gt;no penalty&lt;/strong&gt; for wrong answers, so leave nothing empty!&lt;/p&gt;

&lt;p&gt;The certification is valid for &lt;strong&gt;two years&lt;/strong&gt; from the date of achievement.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Study Method
&lt;/h2&gt;

&lt;p&gt;I use GitHub daily, so I focused on &lt;strong&gt;filling knowledge gaps&lt;/strong&gt; and &lt;strong&gt;understanding advanced features&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;I started with the &lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/credentials/certifications/github-foundations/practice/assessment?assessment-type=practice&amp;amp;assessmentId=954809103&amp;amp;practice-assessment-type=certification" rel="noopener noreferrer"&gt;Microsoft Practice Assessment&lt;/a&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
I reviewed my weak topics using the &lt;strong&gt;Microsoft Learn modules&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
I studied &lt;a href="https://learn.microsoft.com/en-us/training/paths/github-foundations" rel="noopener noreferrer"&gt;GitHub Foundations Part 1&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/training/paths/github-foundations-2" rel="noopener noreferrer"&gt;GitHub Foundations Part 2&lt;/a&gt;, took &lt;strong&gt;notes&lt;/strong&gt;, and used &lt;strong&gt;AI prompts&lt;/strong&gt; to deeply explain difficult concepts.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s an example of an AI prompt that I used:&lt;/strong&gt;  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You are a GitHub expert trainer. I’m preparing for the Foundations certification. Your goal is to help me master every concept through challenging, exam-style practice questions and explanations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used the Role + Context + Goal to create a good prompt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role → Define who the assistant should be.
Example: “You are a GitHub certification coach.”&lt;/li&gt;
&lt;li&gt;Context → Describe the situation or task.
Example: “We’re preparing for the GitHub Foundations certification.”&lt;/li&gt;
&lt;li&gt;Goal → Specify the outcome you want.
Example: “Generate tricky, realistic exam-style questions with detailed explanations.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach enhanced my knowledge particularly in areas I found tricky.&lt;br&gt;&lt;br&gt;
I practiced using &lt;a href="https://ghcertified.com/practice_tests" rel="noopener noreferrer"&gt;ghcertified&lt;/a&gt;, which is a great open-source project you can contribute to or get started with on GitHub: &lt;a href="https://github.com/Shahbaz-Alee/GitHub-Foundation-Exam-Prep/blob/main/Slides.pdf" rel="noopener noreferrer"&gt;https://github.com/Shahbaz-Alee/GitHub-Foundation-Exam-Prep/blob/main/Slides.pdf&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: They don’t include official exam questions; all content is original.&lt;/em&gt;  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I skim-read &lt;a href="https://github.com/Shahbaz-Alee/GitHub-Foundation-Exam-Prep/blob/main/Slides.pdf" rel="noopener noreferrer"&gt;Andrew Brown's slides&lt;/a&gt; provided by &lt;a href="https://www.freecodecamp.org" rel="noopener noreferrer"&gt;FreeCodeCamp&lt;/a&gt; a great resource with images and examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Lesson
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub is not just a code host,&lt;/strong&gt; it’s a &lt;strong&gt;collaboration hub&lt;/strong&gt;, and this certification is just the beginning toward more advanced &lt;a href="https://learn.github.com/credentials" rel="noopener noreferrer"&gt;GitHub certifications&lt;/a&gt;. It is the initial step to understand the core concepts, products, and workflows for collaborating on GitHub.&lt;/p&gt;

&lt;p&gt;If you’re starting this journey, take your time, keep learning, and remember every &lt;code&gt;git commit -m "init"&lt;/code&gt; is a step forward in your progress.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why I changed to Cloudflare and you should too</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Wed, 15 Oct 2025 00:08:11 +0000</pubDate>
      <link>https://dev.to/majdizlitni/why-i-changed-to-cloudflare-and-you-should-too-4544</link>
      <guid>https://dev.to/majdizlitni/why-i-changed-to-cloudflare-and-you-should-too-4544</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First Stop&lt;/li&gt;
&lt;li&gt;Comparing Hosting Platforms&lt;/li&gt;
&lt;li&gt;Why I Chose Cloudflare Pages&lt;/li&gt;
&lt;li&gt;Setting Up My Domain &lt;/li&gt;
&lt;li&gt;Goodbye Vercel&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I used to deploy on &lt;strong&gt;Vercel&lt;/strong&gt;, and it was my go to because it made everything &lt;strong&gt;free, fast, and globally available&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Until this happened:&lt;br&gt;&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1972669025525158031-960" src="https://platform.twitter.com/embed/Tweet.html?id=1972669025525158031"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1972669025525158031-960');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1972669025525158031&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Seeing that post made it clear, I had to quit Vercel and move to something else not just for technical reasons, but for &lt;strong&gt;principles&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
I wanted to support platforms that align with transparency, openness, and independence.&lt;/p&gt;


&lt;h2&gt;
  
  
  First Stop
&lt;/h2&gt;

&lt;p&gt;At first, I tried &lt;a href="https://dev.to/helloreplit"&gt;Replit&lt;/a&gt; (&lt;a class="mentioned-user" href="https://dev.to/helloreplit"&gt;@helloreplit&lt;/a&gt;).&lt;br&gt;&lt;br&gt;
Many developers were migrating there in support of the &lt;strong&gt;Pro-Palestine movement&lt;/strong&gt;, and I wanted to contribute, even in the smallest way. Everyone was talking about Replit.  &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1972706418794045832-179" src="https://platform.twitter.com/embed/Tweet.html?id=1972706418794045832"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1972706418794045832-179');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1972706418794045832&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The migration was smooth:&lt;br&gt;&lt;br&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%2F6sp73pkq1e06mifbedob.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%2F6sp73pkq1e06mifbedob.png" alt="Moving to Replit" width="744" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With just a few clicks after linking my &lt;a href="https://github.com/Majdi-Zlitni" rel="noopener noreferrer"&gt;GitHub account&lt;/a&gt; and selecting the &lt;strong&gt;Starter plan&lt;/strong&gt;, Replit’s &lt;strong&gt;AI agent&lt;/strong&gt; handled most of the setup automatically:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tr&gt;
&lt;td&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%2Fx602ajwioxjny30n0nww.png" alt="Adding GitHub" width="800" height="625"&gt;&lt;/td&gt;
&lt;td&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%2Fvkpgbg9t2or4wcpirmnb.png" alt="AI setup" width="444" height="642"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, when publishing, it asked to &lt;strong&gt;upgrade my plan&lt;/strong&gt;, and with Tunisia’s &lt;strong&gt;monetary regulations and foreign currency restrictions&lt;/strong&gt;, that wasn’t an option.&lt;br&gt;&lt;br&gt;
So, I canceled and looked for another free way to publish my &lt;a href="https://majdiz.tn" rel="noopener noreferrer"&gt;portfolio&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%2Fp4zzmufozwrpst3c629z.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%2Fp4zzmufozwrpst3c629z.png" alt="Replit requires payment to publish" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amjad Masad, CEO of Replit, made great moves to attract users and even offered &lt;strong&gt;$50 in credits&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1972805067771355518-983" src="https://platform.twitter.com/embed/Tweet.html?id=1972805067771355518"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1972805067771355518-983');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1972805067771355518&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparing Hosting Platforms
&lt;/h2&gt;

&lt;p&gt;Here’s a technical breakdown of alternatives I researched:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Free Plan&lt;/th&gt;
&lt;th&gt;Custom Domain&lt;/th&gt;
&lt;th&gt;CI/CD Support&lt;/th&gt;
&lt;th&gt;Backend Support&lt;/th&gt;
&lt;th&gt;Ease of Use&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cloudflare Pages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed Hosting&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes (GitHub/GitLab)&lt;/td&gt;
&lt;td&gt;⚠️ Limited (Static + Workers)&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
&lt;td&gt;Static &amp;amp; JAMStack Sites&lt;/td&gt;
&lt;td&gt;Excellent docs, global CDN, easy migration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed Hosting&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Limited (manual CI/CD)&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;⭐⭐⭐&lt;/td&gt;
&lt;td&gt;Portfolios, docs, static sites&lt;/td&gt;
&lt;td&gt;Simple but lacks backend/dynamic features.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed Hosting&lt;/td&gt;
&lt;td&gt;✅ Yes (limited hours)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Full backend (Node, Python, etc.)&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
&lt;td&gt;Full-stack &amp;amp; API apps&lt;/td&gt;
&lt;td&gt;Auto SSL, DBs, background workers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hetzner Cloud&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-Hosted VPS&lt;/td&gt;
&lt;td&gt;❌ No (paid)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Custom via CI/CD tools&lt;/td&gt;
&lt;td&gt;✅ Full backend&lt;/td&gt;
&lt;td&gt;⭐⭐⭐&lt;/td&gt;
&lt;td&gt;Devs who want control&lt;/td&gt;
&lt;td&gt;Cheap, powerful VPS for custom infra.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Docker + Coolify (Self-Hosted)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Self-Hosted&lt;/td&gt;
&lt;td&gt;⚠️ Free (if self-hosted)&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes (custom)&lt;/td&gt;
&lt;td&gt;✅ Full backend&lt;/td&gt;
&lt;td&gt;⭐⭐&lt;/td&gt;
&lt;td&gt;Experienced devs&lt;/td&gt;
&lt;td&gt;Great for learning DevOps &amp;amp; full control.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why I Chose Cloudflare Pages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Deployed on &lt;strong&gt;300+ global edge locations&lt;/strong&gt; → ultra-fast performance. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in CI/CD&lt;/strong&gt; with GitHub/GitLab auto builds &amp;amp; previews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serverless backend&lt;/strong&gt; via Cloudflare Workers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free SSL, CDN, DDoS protection&lt;/strong&gt;, and image optimization included.&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;Next.js, Astro, Remix, SvelteKit&lt;/strong&gt;, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero config, instant scaling&lt;/strong&gt;, and excellent documentation.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In short: Cloudflare Pages + Workers = frontend + backend on the edge globally distributed, secure, and free.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Setting Up My Domain
&lt;/h2&gt;

&lt;p&gt;After deployment, I updated my DNS records using &lt;strong&gt;&lt;a href="https://ati.tn" rel="noopener noreferrer"&gt;ATI.tn&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Tunisia’s official domain registry which offers &lt;strong&gt;custom domains for 12 TND/year&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Having your own domain means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control over your brand identity
&lt;/li&gt;
&lt;li&gt;A professional, portable online presence
&lt;/li&gt;
&lt;li&gt;Freedom from platform lock-in
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;“Customization isn’t free, but it’s worth it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After switching to &lt;strong&gt;Cloudflare nameservers&lt;/strong&gt;, everything synced perfectly:&lt;br&gt;&lt;br&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%2F9qpo0jc0f882drxjuqbw.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%2F9qpo0jc0f882drxjuqbw.png" alt="Cloudflare DNS" width="744" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment successful!&lt;/strong&gt;&lt;br&gt;&lt;br&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%2Fkxaasnk7cjx4fv6k5s76.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%2Fkxaasnk7cjx4fv6k5s76.png" alt="Successfully deployed to Cloudflare" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Goodbye Vercel
&lt;/h2&gt;

&lt;p&gt;Finally, I deleted my &lt;strong&gt;Vercel&lt;/strong&gt; account and officially joined the &lt;strong&gt;boycott movement&lt;/strong&gt;, a small but meaningful step to align with my values.&lt;br&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%2Fk3ecxx0vfxl2y9v3xr86.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%2Fk3ecxx0vfxl2y9v3xr86.png" alt="Vercel account deleted" width="744" height="189"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Pages&lt;/strong&gt; is the best &lt;strong&gt;free edge hosting&lt;/strong&gt; option for developers in 2025.
&lt;/li&gt;
&lt;li&gt;For more control or backend apps, &lt;strong&gt;Hetzner + Coolify&lt;/strong&gt; is an amazing combo.
&lt;/li&gt;
&lt;li&gt;Your hosting choices can reflect your &lt;strong&gt;values, independence, and technical standards&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In the end, the best stack is the one you own ethically, technically, and creatively.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Keywords for SEO
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;cloudflare pages&lt;/code&gt;, &lt;code&gt;vercel alternative&lt;/code&gt;, &lt;code&gt;free deployment&lt;/code&gt;, &lt;code&gt;jamstack hosting&lt;/code&gt;, &lt;code&gt;self-hosted devops&lt;/code&gt;, &lt;code&gt;hetzner&lt;/code&gt;, &lt;code&gt;coolify&lt;/code&gt;, &lt;code&gt;static site hosting&lt;/code&gt;, &lt;code&gt;tunisia domain&lt;/code&gt;, &lt;code&gt;ati.tn&lt;/code&gt;, &lt;code&gt;developer migration&lt;/code&gt;&lt;/p&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>devops</category>
      <category>webdev</category>
      <category>deployment</category>
    </item>
    <item>
      <title>Why manually registering component when Auto-Discovery exist?</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Thu, 18 Sep 2025 16:17:32 +0000</pubDate>
      <link>https://dev.to/majdizlitni/why-manually-registering-component-when-auto-discovery-exist-519d</link>
      <guid>https://dev.to/majdizlitni/why-manually-registering-component-when-auto-discovery-exist-519d</guid>
      <description>&lt;p&gt;For production grade applications SOLID are a must principles, but when adding a new feature open for extension close for modification principle could be easily violated.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hardcoding filters
&lt;/h2&gt;

&lt;p&gt;Let's take an example of an image processing application where we need an image filter plugin system.&lt;br&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%2F7frme5k1an60qk2yf1ug.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%2F7frme5k1an60qk2yf1ug.gif" alt="Image Taker" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core interface is simple, it must be implemented by classes as a best practice.&lt;br&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%2Fg76gircjvp93tm48iuaw.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%2Fg76gircjvp93tm48iuaw.png" alt="IFilter file" width="800" height="472"&gt;&lt;/a&gt; &lt;code&gt;Name&lt;/code&gt; represents the filter that we will apply to a given image.&lt;/p&gt;


&lt;h2&gt;
  
  
  The common approach
&lt;/h2&gt;

&lt;p&gt;The common way is to manually register every known filter&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;FilterManager&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;IFilter&lt;/span&gt; &lt;span class="nf"&gt;GetFilter&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;filterName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&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;filterName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"grayscale"&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;GrayscaleFilter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"sepia"&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;SepiaFilter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// PROBLEM: To add a new filter, we must come back here and modify this file.&lt;/span&gt;
            &lt;span class="cm"&gt;/*
            case "invert":
                return new InvertColorsFilter();
            */&lt;/span&gt;

            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Filter '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filterName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' is not recognized."&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;Main application logic: &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%2Ff79xutkqnezmjwoinksw.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%2Ff79xutkqnezmjwoinksw.png" alt="Mais.cs file" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this is a problem?
&lt;/h2&gt;

&lt;p&gt;This approach is technical debt and time consuming because it will introduce: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open/Close principle violation&lt;/strong&gt;: The &lt;code&gt;FilterManager&lt;/code&gt; is not 'closed for modification.' To add a new &lt;code&gt;InvertColorsFilter&lt;/code&gt;, we are forced to open and change the &lt;code&gt;FilterManager&lt;/code&gt; code which is time consuming, overwhelming and could be risky for a production grade level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error prone&lt;/strong&gt;: Whenever a new filter is added we should always add it to code to previous switch statement and this creates a tightly coupled application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Merge conflict&lt;/strong&gt;: For faster problems solving and project success, team play is needed but as the team grow a single file can become the hotspot where multiple developers edit it simultaneously, which introduces frustrating merge conflicts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Assembly scanning for discovery as a solution
&lt;/h2&gt;

&lt;p&gt;Refactoring the code for a production-grade level by adding a generic engine that builds classes automatically would be a better approach.&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;FilterManager&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;IReadOnlyDictionary&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;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_discoveredFilters&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;FilterManager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IReadOnlyDictionary&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;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;discoveredFilters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_discoveredFilters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;discoveredFilters&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;IFilter&lt;/span&gt; &lt;span class="nf"&gt;GetFilter&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;filterName&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;_discoveredFilters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filterName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;filterType&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotSupportedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Filter '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filterName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' is not recognized."&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;Activator&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;filterType&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;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IReadOnlyDictionary&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;,&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;BuildFilterCatalog&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;catalog&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;Dictionary&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;,&lt;/span&gt; &lt;span class="n"&gt;Type&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;pluginAssembly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Program&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&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;filterTypes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pluginAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTypes&lt;/span&gt;&lt;span class="p"&gt;()&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;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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsClass&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&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="n"&gt;IsAbstract&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFilter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;IsAssignableFrom&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;foreach&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;type&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filterTypes&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;tempFilter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFilter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;Activator&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;type&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;$"[Plugin Discovery] Found filter: '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tempFilter&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;'"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;catalog&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tempFilter&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="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;()]&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;catalog&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;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;discoveredFilters.TryGetValue(...)&lt;/code&gt;: Tries to find an entry in the dictionary using a key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pluginAssembly.GetTypes()&lt;/code&gt;: The pluginAssembly have references to .dll and .exe files.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GetTypes()&lt;/code&gt;: will return every single:&lt;/li&gt;
&lt;li&gt;class
&lt;/li&gt;
&lt;li&gt;interface
&lt;/li&gt;
&lt;li&gt;struct
&lt;/li&gt;
&lt;li&gt;enum
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;.Where(...)&lt;/code&gt;: Is a Language Integrated Query, used to keep data that satisfy given conditions.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;t.IsClass&lt;/code&gt;: checks if the current type is a class.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!t.IsAbstract&lt;/code&gt;: filters out abstract classes.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;typeof(IFilter).IsAssignableFrom(t)&lt;/code&gt;: determines if the type can be assigned to a variable of type IFilter.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;foreach&lt;/code&gt; loop takes a list of objects, each representing a filter class discovered by reflection and for each type in the list, an instance of the class is created using Activator.CreateInstance().&lt;/p&gt;




&lt;h2&gt;
  
  
  What is reflection?
&lt;/h2&gt;

&lt;p&gt;In .NET an Assembly is a compiled output of code that contains &lt;code&gt;.dll&lt;/code&gt; and &lt;code&gt;.exe&lt;/code&gt; files and by using &lt;code&gt;System.Reflection.Assembly&lt;/code&gt; we can load and inspect our solution files programmatically &lt;/p&gt;




&lt;p&gt;Combining &lt;strong&gt;dynamic discovery&lt;/strong&gt; via &lt;strong&gt;reflection&lt;/strong&gt; with &lt;strong&gt;builder pattern&lt;/strong&gt; we achieved not only flexible but also an extensible architecture.&lt;br&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%2Fmsse1bh6evgx1pw2p2m0.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%2Fmsse1bh6evgx1pw2p2m0.png" alt="Main file" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have used &lt;strong&gt;reflection&lt;/strong&gt; and &lt;strong&gt;dependency injection&lt;/strong&gt; to load filters  dynamically without hard coding.&lt;/p&gt;




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

&lt;p&gt;Using this shifting mindset we can create robust and scalable system but scanning every assembly can lead to slowness therefore we should be specific for best practices.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>A Comprehensive Guide To Exception Handling in C# .NET</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 18 May 2024 11:14:23 +0000</pubDate>
      <link>https://dev.to/majdizlitni/a-comprehensive-guide-to-exception-handling-in-c-net-1k4</link>
      <guid>https://dev.to/majdizlitni/a-comprehensive-guide-to-exception-handling-in-c-net-1k4</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What is an exception?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An exception is an occurrence during the execution of a program that disrupts it normal flow.&lt;/p&gt;

&lt;p&gt;In the world of computers, when you tell a program to do something, sometimes it runs into a problem. An &lt;code&gt;exception&lt;/code&gt; is the way the program says, "Oops! I can't do what you asked because there's a problem."&lt;/p&gt;

&lt;p&gt;As you can see in the picture bellow the debugger which is a powerful tool that allows developers to inspect the behavior of their code during execution, making it easier to identify and fix issues such as bugs and exceptions.&lt;br&gt;
In debug mode, when an exception occurs and is not caught by a &lt;strong&gt;&lt;code&gt;catch&lt;/code&gt;&lt;/strong&gt; block within the same method, the debugger typically interrupts the program execution and highlights the line of code where the exception occurred.&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%2Fwkzjns9uh1ydygrezg0p.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%2Fwkzjns9uh1ydygrezg0p.png" alt="VS2022 Debugger" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Why handling exception?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let's think about riding your bike. When you're on your bike, you wear a helmet, right? That helmet is there just in case you fall, it's there to protect your head from getting hurt.&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%2Fljy6glyg2wec96oi54in.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%2Fljy6glyg2wec96oi54in.gif" alt="bike helmet" width="472" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Now, in the world of computers, sometimes things go wrong when a program is trying to do its job, just like there might be a pothole or a branch that could make you fall off your bike.&lt;/p&gt;

&lt;p&gt;Handling exceptions is like wearing your helmet when riding your bike. It is a way for the program to say, "Whoops, something went wrong here, but don't worry buddy, I know what to do!"&lt;br&gt;
Just like your helmet keeps you safe, handling exceptions keeps the program safe so it doesn't crash and lose all the work it was doing. &lt;/p&gt;

&lt;p&gt;So by handling exceptions, we can provide meaningful error messages to the user and &lt;strong&gt;prevent our&lt;/strong&gt; programs from terminating unexpectedly. It also allows us to implement recovery scenarios and ensures that the code following the faulty one does not get affected by an error.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;How exception are handled&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In C# .NET, exceptions are handled using a combination of the &lt;code&gt;try&lt;/code&gt;, &lt;code&gt;catch&lt;/code&gt;, and &lt;code&gt;finally&lt;/code&gt; keywords. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;try&lt;/code&gt; contains the section of code that might potentially throw an exception. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;catch&lt;/code&gt; blocks are used to handle any exceptions that occur within the corresponding &lt;code&gt;try&lt;/code&gt; block. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;finally&lt;/code&gt; block, if present, is executed regardless of whether an exception is thrown or not. This is usually used for cleanup code that must be run regardless of whether an operation succeeds or fails.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this example &lt;strong&gt;&lt;code&gt;MethodToHandleException&lt;/code&gt;&lt;/strong&gt; attempts to divide 10 by 0 using the &lt;strong&gt;&lt;code&gt;Divide&lt;/code&gt;&lt;/strong&gt; method. If a &lt;strong&gt;&lt;code&gt;DivideByZeroException&lt;/code&gt;&lt;/strong&gt; occurs, it prints an error message, otherwise, it catches any other exceptions and prints a generic error message.&lt;/p&gt;

&lt;p&gt;The method ensures cleanup by printing "Cleaning up..." regardless of whether an exception occurs.&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;void&lt;/span&gt; &lt;span class="nf"&gt;HandleDivideByZeroException&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Code that might throw an exception&lt;/span&gt;
            &lt;span class="nf"&gt;Divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Attempting to divide by zero&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DivideByZeroException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Handle divide by zero exception&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;"Error: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// Rethrow the exception without losing the original stack trace&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&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;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Handle other exceptions&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;"An unexpected error occurred: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;finally&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Cleanup code, regardless of whether an exception occurred&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;"Cleaning up..."&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;There are 3 ways to re-throw an exception:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;`throw&lt;/strong&gt;` — rethrows the current exception and preserves the stack trace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;throw ex&lt;/code&gt;&lt;/strong&gt; — throws an existing exception but resets the stack trace from the point of rethrow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;`throw new Exception&lt;/strong&gt;` — creates a new exception, which completely rewrites the stack trace.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Handling Exceptions With Filtering in C#&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;when&lt;/code&gt; clause in C# catch blocks allows as to specify a condition that if true it will be handled in the catch block. &lt;/p&gt;

&lt;p&gt;This functionality, termed &lt;strong&gt;exception filtering&lt;/strong&gt;, proves beneficial in situations where exceptions should only be caught under specific circumstances.&lt;/p&gt;

&lt;p&gt;We can employ a &lt;strong&gt;&lt;code&gt;when&lt;/code&gt;&lt;/strong&gt; clause to handle various instances of &lt;strong&gt;&lt;code&gt;FormatException&lt;/code&gt;&lt;/strong&gt; differently:&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;try&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;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ConvertToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"123abc"&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 result: &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="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;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FormatException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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="s"&gt;"invalid format"&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;"Data has an invalid format. Please check your inputs."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FormatException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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="s"&gt;"empty string"&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;"No data provided. Please enter some numeric data."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OverflowException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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="s"&gt;"too large"&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;"Data is too large. Please enter a smaller number."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&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;ex&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;$"An unexpected error occurred: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best practices for exception handling in C
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoid throwing generic exceptions&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Throwing generic exceptions like &lt;strong&gt;&lt;code&gt;System.Exception&lt;/code&gt;&lt;/strong&gt; can make it difficult to determine the root cause of an issue. Instead, use specific exception types to provide more context and make debugging easier.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoid swallowing exceptions&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Swallowing exceptions by catching them and not doing anything with them can hide problems in your code and make debugging challenging. At the very least, log exceptions so you have a record of what went wrong.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Handle exceptions at the appropriate level&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Handle exceptions at the appropriate level of abstraction in your code. For example, catch exceptions at the UI layer for user-facing errors and catch them closer to the source for technical errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Provide meaningful error messages&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;When throwing exceptions, provide meaningful error messages that explain what went wrong and how to resolve the issue. This makes it easier for developers to understand and address problems.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of handling a specific scenario using these best practices:&lt;/p&gt;

&lt;p&gt;We have a method that loads data from a file. &lt;/p&gt;

&lt;p&gt;We catch specific exceptions like &lt;strong&gt;&lt;code&gt;FileNotFoundException&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;IOException&lt;/code&gt;&lt;/strong&gt; to handle file-related errors and inform the user appropriately. &lt;/p&gt;

&lt;p&gt;For any other unexpected errors, we log the exception and inform the user to contact support for assistance. &lt;/p&gt;

&lt;p&gt;Finally, we rethrow the exception to ensure it's not swallowed and can be handled elsewhere if necessary.&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;void&lt;/span&gt; &lt;span class="nf"&gt;LoadDataFromFile&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;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Attempt to load data from the file&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;ProcessData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FileNotFoundException&lt;/span&gt; &lt;span class="n"&gt;ex&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 the exception and inform the user that the file does not exist&lt;/span&gt;
        &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"File not found: {FilePath}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;MessageBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"The file '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' does not exist."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxButtons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;ex&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 the exception and inform the user that there was an error reading the file&lt;/span&gt;
        &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error reading file: {FilePath}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;MessageBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"An error occurred while reading the file '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'. Please try again later."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxButtons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch&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;ex&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 the exception and inform the user that an unexpected error occurred&lt;/span&gt;
        &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"An unexpected error occurred while loading data from file: {FilePath}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;MessageBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"An unexpected error occurred. Please contact support for assistance."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxButtons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MessageBoxIcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Rethrow the exception to ensure it's not swallowed&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;



</description>
    </item>
  </channel>
</rss>
