<?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>Forem: Ashraf Mehdaly</title>
    <description>The latest articles on Forem by Ashraf Mehdaly (@amehdaly).</description>
    <link>https://forem.com/amehdaly</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%2F35992%2Fdb31b35c-a19a-4a46-9b39-a5de76642745.png</url>
      <title>Forem: Ashraf Mehdaly</title>
      <link>https://forem.com/amehdaly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/amehdaly"/>
    <language>en</language>
    <item>
      <title>Designing a Restore-First Desktop Backup Tool Around Restic (From Bash Script to Qt/C++)</title>
      <dc:creator>Ashraf Mehdaly</dc:creator>
      <pubDate>Sun, 22 Feb 2026 20:56:21 +0000</pubDate>
      <link>https://forem.com/amehdaly/designing-a-restore-first-desktop-backup-tool-around-restic-from-bash-script-to-qtc-17cd</link>
      <guid>https://forem.com/amehdaly/designing-a-restore-first-desktop-backup-tool-around-restic-from-bash-script-to-qtc-17cd</guid>
      <description>&lt;h3&gt;
  
  
  Reflections on trust, restore safety, threading, and building a desktop orchestration layer around a CLI engine.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Backups Are Easy. Restores Are Not.
&lt;/h3&gt;

&lt;p&gt;Taking backups is usually simple.&lt;/p&gt;

&lt;p&gt;Restoring them — confidently, correctly, and without hesitation — is where anxiety begins.&lt;/p&gt;

&lt;p&gt;Over time, I realized that most tools are designed around &lt;em&gt;creating backups&lt;/em&gt;. Very few are designed around &lt;em&gt;restoring safely&lt;/em&gt;. And psychologically, restore confidence is what really matters.&lt;/p&gt;

&lt;p&gt;This realization is what led me from a small Bash script wrapped in &lt;a href="https://develop.kde.org/docs/administration/kdialog/" rel="noopener noreferrer"&gt;KDialog&lt;/a&gt; to a full multithreaded Qt/C++ desktop application built around &lt;a href="https://restic.net/" rel="noopener noreferrer"&gt;restic&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 1: The Script That Solved One Problem
&lt;/h3&gt;

&lt;p&gt;The first version of this project was nothing more than:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Bash script&lt;/li&gt;
&lt;li&gt;Hardcoded include paths&lt;/li&gt;
&lt;li&gt;restic CLI calls&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://develop.kde.org/docs/administration/kdialog/" rel="noopener noreferrer"&gt;KDialog&lt;/a&gt; progress dialogs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It removed repetitive typing. That was enough — for a while.&lt;/p&gt;

&lt;p&gt;But as I started using restic to manage configuration state (Docker stacks, system configs, reverse proxies, etc.), new requirements emerged:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple structured backup definitions&lt;/li&gt;
&lt;li&gt;Clean separation between “what to back up” and “how to execute”&lt;/li&gt;
&lt;li&gt;Safer restore workflows&lt;/li&gt;
&lt;li&gt;Snapshot comparison&lt;/li&gt;
&lt;li&gt;Elevated execution handling&lt;/li&gt;
&lt;li&gt;Persistence beyond flat config files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The script had reached its natural limits.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Philosophy: Orchestrator, Not Engine
&lt;/h3&gt;

&lt;p&gt;One rule shaped everything that followed:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://restic.net/" rel="noopener noreferrer"&gt;Restic&lt;/a&gt; remains the engine. The application must remain an orchestrator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I did not want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A custom backup format&lt;/li&gt;
&lt;li&gt;A metadata layer that breaks CLI compatibility&lt;/li&gt;
&lt;li&gt;Tight coupling to restic internals&lt;/li&gt;
&lt;li&gt;A forked engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repositories remain 100% standard restic repositories.&lt;br&gt;&lt;br&gt;
You can always use the CLI directly.&lt;/p&gt;

&lt;p&gt;This separation is intentional. It preserves transparency and trust.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why &lt;a href="https://www.qt.io/" rel="noopener noreferrer"&gt;Qt&lt;/a&gt;/C++?
&lt;/h3&gt;

&lt;p&gt;The move to Qt Widgets + C++ was pragmatic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-platform (Linux + Windows)&lt;/li&gt;
&lt;li&gt;Strong threading primitives&lt;/li&gt;
&lt;li&gt;Clean process management (QProcess)&lt;/li&gt;
&lt;li&gt;Mature event system&lt;/li&gt;
&lt;li&gt;Deterministic memory ownership&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was not about building something flashy.&lt;br&gt;&lt;br&gt;
It was about building something predictable.&lt;/p&gt;

&lt;p&gt;Backup software should feel boring — in the best possible way.&lt;/p&gt;




&lt;h3&gt;
  
  
  Threading and Process Isolation
&lt;/h3&gt;

&lt;p&gt;One non-negotiable requirement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The UI must never block during backup or restore operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Architecture:&lt;/p&gt;

&lt;p&gt;UI Thread&lt;br&gt;&lt;br&gt;
→ Operation Controller&lt;br&gt;&lt;br&gt;
→ Worker Object (QObject-based)&lt;br&gt;&lt;br&gt;
→ QThread&lt;br&gt;&lt;br&gt;
→ QProcess (restic invocation)&lt;/p&gt;

&lt;p&gt;Key principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restic runs as an external process.&lt;/li&gt;
&lt;li&gt;Output streams are parsed asynchronously.&lt;/li&gt;
&lt;li&gt;No nested event loops.&lt;/li&gt;
&lt;li&gt;No UI updates from worker threads.&lt;/li&gt;
&lt;li&gt;Strict signal-slot boundaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This preserves responsiveness and reduces risk of undefined state during long operations.&lt;/p&gt;

&lt;p&gt;The application does not embed restic. It orchestrates it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Profiles as “State Definitions”
&lt;/h3&gt;

&lt;p&gt;The biggest conceptual shift from the Bash prototype was introducing structured profiles.&lt;/p&gt;

&lt;p&gt;A profile defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository path&lt;/li&gt;
&lt;li&gt;Multiple include directories&lt;/li&gt;
&lt;li&gt;Selective file includes&lt;/li&gt;
&lt;li&gt;Glob-based exclude patterns&lt;/li&gt;
&lt;li&gt;Pre/Post scripts&lt;/li&gt;
&lt;li&gt;Elevation requirements&lt;/li&gt;
&lt;li&gt;Default restore behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of thinking in terms of “run backup command”, I started thinking in terms of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Define the state of a machine.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Profile: docker-host-01&lt;br&gt;&lt;br&gt;
Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/etc/docker&lt;/li&gt;
&lt;li&gt;/srv/docker-compose&lt;/li&gt;
&lt;li&gt;/etc/nginx&lt;/li&gt;
&lt;li&gt;specific .env files
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Excludes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/logs/&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/cache/&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;transient runtime directories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows treating configuration as versioned infrastructure.&lt;/p&gt;




&lt;h3&gt;
  
  
  Restore Is a First-Class Citizen
&lt;/h3&gt;

&lt;p&gt;Most CLI usage patterns focus on &lt;code&gt;restic backup&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I chose to design the UI around restore semantics.&lt;/p&gt;

&lt;p&gt;Two restore modes emerged:&lt;/p&gt;

&lt;h4&gt;
  
  
  Mirror Mode
&lt;/h4&gt;

&lt;p&gt;The target directory becomes identical to the snapshot.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rebuilding a machine&lt;/li&gt;
&lt;li&gt;Migrating to a clean VM&lt;/li&gt;
&lt;li&gt;Rehydrating configuration state&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Update Mode
&lt;/h4&gt;

&lt;p&gt;Only overwrite files that exist in the snapshot.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Partial correction&lt;/li&gt;
&lt;li&gt;Non-destructive repair&lt;/li&gt;
&lt;li&gt;Controlled restoration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Internally, restore operations are staged and validated before final application.&lt;/p&gt;

&lt;p&gt;Restore must feel deliberate — not destructive.&lt;/p&gt;




&lt;h3&gt;
  
  
  Snapshot Diff and File-Level Diff
&lt;/h3&gt;

&lt;p&gt;Restic already tracks content efficiently.&lt;br&gt;&lt;br&gt;
But understanding &lt;em&gt;what changed&lt;/em&gt; is equally important.&lt;/p&gt;

&lt;p&gt;The application can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare two snapshots&lt;/li&gt;
&lt;li&gt;Identify added/modified/deleted files&lt;/li&gt;
&lt;li&gt;Extract specific file versions&lt;/li&gt;
&lt;li&gt;Perform file-level diff analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This turns backups into something closer to version history.&lt;/p&gt;

&lt;p&gt;For configuration-heavy environments, this visibility matters.&lt;/p&gt;




&lt;h3&gt;
  
  
  Elevated Execution and Hooks
&lt;/h3&gt;

&lt;p&gt;System paths often require root/admin access.&lt;/p&gt;

&lt;p&gt;The application supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicit elevated execution&lt;/li&gt;
&lt;li&gt;Controlled privilege escalation&lt;/li&gt;
&lt;li&gt;Pre/Post scripts per profile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stop Docker before backup&lt;/li&gt;
&lt;li&gt;Dump a database before snapshot&lt;/li&gt;
&lt;li&gt;Restart services after restore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not advanced features — they are practical realities in homelab and system environments.&lt;/p&gt;

&lt;p&gt;Automation without context can be dangerous.&lt;br&gt;&lt;br&gt;
Controlled hooks provide flexibility without losing structure.&lt;/p&gt;




&lt;h3&gt;
  
  
  Persistence and Portability
&lt;/h3&gt;

&lt;p&gt;SQLite is used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Profile definitions&lt;/li&gt;
&lt;li&gt;Operation history&lt;/li&gt;
&lt;li&gt;Application settings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Import/Export allows moving profile definitions between machines.&lt;/p&gt;

&lt;p&gt;The repository remains external and portable.&lt;/p&gt;

&lt;p&gt;The application’s state is separate from backup data.&lt;/p&gt;

&lt;p&gt;Again — boundaries matter.&lt;/p&gt;




&lt;h3&gt;
  
  
  Build System and Determinism
&lt;/h3&gt;

&lt;p&gt;The project uses CMake with clear target separation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core execution module&lt;/li&gt;
&lt;li&gt;Worker module&lt;/li&gt;
&lt;li&gt;UI module&lt;/li&gt;
&lt;li&gt;Database layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shared library outputs are controlled explicitly.&lt;br&gt;
No versioned SONAME chains where unnecessary.&lt;br&gt;
Deployment artifacts are predictable.&lt;/p&gt;

&lt;p&gt;Backup tooling should not surprise the user — including at build time.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Calm Conclusion
&lt;/h2&gt;

&lt;p&gt;This project evolved gradually:&lt;/p&gt;

&lt;p&gt;Bash script → structured orchestration → multi-threaded Qt desktop application.&lt;/p&gt;

&lt;p&gt;The most important insight was not about threading or CMake.&lt;/p&gt;

&lt;p&gt;It was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Backup software is about confidence.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Confidence comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictable behavior&lt;/li&gt;
&lt;li&gt;Clear boundaries&lt;/li&gt;
&lt;li&gt;Restore safety&lt;/li&gt;
&lt;li&gt;Transparency&lt;/li&gt;
&lt;li&gt;Compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Restic remains the engine.&lt;br&gt;&lt;br&gt;
The desktop layer exists to improve workflow — not to obscure it.&lt;/p&gt;

&lt;p&gt;If there is one architectural lesson here, it is this:&lt;/p&gt;

&lt;p&gt;When wrapping a CLI tool with a GUI, preserve the engine’s integrity — and design around the human moment of restore.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Reference
&lt;/h2&gt;

&lt;p&gt;I packaged this into a desktop application called EasyBackupManager (EBM).&lt;/p&gt;

&lt;p&gt;If you're curious to explore it, see screenshots, or try the Windows/Linux builds which is completely free, you can find it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://easybackupmanager.com" rel="noopener noreferrer"&gt;https://easybackupmanager.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repositories remain fully standard &lt;a href="https://restic.net/" rel="noopener noreferrer"&gt;restic&lt;/a&gt; repositories and are always accessible via the CLI.&lt;/p&gt;

</description>
      <category>qt</category>
      <category>cpp</category>
      <category>restic</category>
      <category>devops</category>
    </item>
    <item>
      <title>Adding Middleware to .NET Desktop Applications</title>
      <dc:creator>Ashraf Mehdaly</dc:creator>
      <pubDate>Sat, 22 Jun 2024 18:51:37 +0000</pubDate>
      <link>https://forem.com/amehdaly/adding-middleware-to-net-desktop-applications-4gh</link>
      <guid>https://forem.com/amehdaly/adding-middleware-to-net-desktop-applications-4gh</guid>
      <description>&lt;p&gt;&lt;strong&gt;Middleware&lt;/strong&gt; is a common pattern in web development for handling cross-cutting concerns like logging, authentication, and error handling. However, in desktop applications, the concept isn't as directly supported. This article explores how you can implement middleware-like behavior in .NET desktop applications using several design patterns and strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event Handling Middleware
&lt;/h3&gt;

&lt;p&gt;One approach to implementing middleware in a .NET desktop application is through event handling. By intercepting and handling events centrally, you can insert middleware logic before the main application logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&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;Middleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Middleware logic&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;"Middleware processing..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainApplication&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt; &lt;span class="n"&gt;SomeEvent&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;MainApplication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Middleware&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;SomeEvent&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;SomeEvent&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;MainLogic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MainLogic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Main application logic&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;"Main logic processing..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TriggerEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;SomeEvent&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&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;In this example, the Middleware class intercepts the SomeEvent event before the MainLogic method processes it. This allows you to insert any necessary preprocessing logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decorator Pattern Middleware
&lt;/h3&gt;

&lt;p&gt;The decorator pattern is another effective way to add middleware-like behavior. This pattern involves wrapping functionality around specific methods, which can be particularly useful for key operations in your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IComponent&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainComponent&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IComponent&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Main application logic&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;"Executing main component..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MiddlewareDecorator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IComponent&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;IComponent&lt;/span&gt; &lt;span class="n"&gt;_component&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;MiddlewareDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IComponent&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_component&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Middleware logic before&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;"Executing middleware before..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;_component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Middleware logic after&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;"Executing middleware after..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mainComponent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MainComponent&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;decoratedComponent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MiddlewareDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mainComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;decoratedComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this pattern, the MiddlewareDecorator wraps around the MainComponent, allowing you to insert logic before and after the main execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipeline Pattern Middleware
&lt;/h3&gt;

&lt;p&gt;For a more structured approach, you can implement a pipeline pattern. This involves creating a series of middleware components that each process a request and pass it to the next component in the pipeline.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Context properties&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Middleware1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Middleware logic&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;"Middleware 1 processing..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Middleware2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Middleware logic&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;"Middleware 2 processing..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pipeline&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_middlewares&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IMiddleware&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_currentMiddleware&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMiddleware&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_currentMiddleware&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_currentMiddleware&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;_currentMiddleware&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;_middlewares&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_middlewares&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_currentMiddleware&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Pipeline&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Middleware1&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Middleware2&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;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this pipeline pattern, each IMiddleware component processes the Context and then calls the next middleware in the sequence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;While .NET desktop applications don't natively support middleware in the same way that web frameworks like ASP.NET Core do, you can still implement middleware-like behavior using event handling, the decorator pattern, or a custom pipeline. These strategies allow you to modularize and manage cross-cutting concerns such as logging, exception handling, and more in a clean and maintainable way.&lt;/p&gt;

&lt;p&gt;By adopting these patterns, you can improve the structure and scalability of your desktop applications, making them easier to maintain and extend over time.&lt;/p&gt;

</description>
      <category>dotnetcore</category>
      <category>designpatterns</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Unraveling the Enigma: Exploring Object Equality in JavaScript and Beyond</title>
      <dc:creator>Ashraf Mehdaly</dc:creator>
      <pubDate>Sat, 22 Jul 2023 08:00:39 +0000</pubDate>
      <link>https://forem.com/amehdaly/unraveling-the-enigma-exploring-object-equality-in-javascript-and-beyond-1cf8</link>
      <guid>https://forem.com/amehdaly/unraveling-the-enigma-exploring-object-equality-in-javascript-and-beyond-1cf8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;br&gt;
JavaScript is a widely used programming language known for its flexibility and dynamic nature. However, when it comes to object comparison, JavaScript can behave in unexpected ways. One peculiar aspect is that two seemingly similar objects are not considered equal when using the equality operator (==) or strict equality operator (===). This essay explores the reasons behind this behavior and compares it with other programming languages like C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Reference Equality in JavaScript:&lt;/strong&gt;&lt;br&gt;
In JavaScript, objects are reference types, and when comparing objects using the equality operator (==) or the strict equality operator (===), the comparison is based on their references rather than their contents. Two objects with identical key-value pairs are considered different if they occupy different memory locations. Let's illustrate this with a code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;obj2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: false&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;obj2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, obj1 and obj2 have the same key-value pairs, but they are two distinct objects with different references. Hence, the comparison yields false.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Value Equality in JavaScript:&lt;/strong&gt;&lt;br&gt;
If you want to compare the contents of two objects rather than their references, you need to implement a custom comparison function. One way to achieve this is by converting the objects to JSON strings and then comparing those strings. However, this approach has limitations, especially when dealing with nested objects or functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;areObjectsEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;obj2&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;areObjectsEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;obj4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Object Comparison in C#:&lt;/strong&gt;&lt;br&gt;
C# is a statically typed language, and its object comparison behavior is different from JavaScript. By default, object comparisons in C# are reference-based, similar to JavaScript's strict equality (===). However, C# allows you to override the &lt;code&gt;Equals&lt;/code&gt; method to customize object comparison based on their contents.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;obj&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;obj&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;!(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Person&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;false&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;otherPerson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;obj&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;otherPerson&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;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;otherPerson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;person1&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;Person&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;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;person2&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;Person&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;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: False&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we override the &lt;code&gt;Equals&lt;/code&gt; method in the &lt;code&gt;Person&lt;/code&gt; class to compare the objects based on their &lt;code&gt;Name&lt;/code&gt; and &lt;code&gt;Age&lt;/code&gt; properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
In JavaScript, two similar objects are not considered equal when using the equality or strict equality operators because the comparison is based on their references, not their contents. To compare object contents in JavaScript, you need to implement a custom comparison function. On the other hand, C# allows developers to override the &lt;code&gt;Equals&lt;/code&gt; method to customize object comparisons based on their properties. Understanding these differences is crucial for writing robust code when dealing with objects in JavaScript and other programming languages like C#.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>learning</category>
      <category>csharp</category>
    </item>
    <item>
      <title>How to use Sudo in Windows 10 Powershell</title>
      <dc:creator>Ashraf Mehdaly</dc:creator>
      <pubDate>Tue, 10 Nov 2020 08:24:33 +0000</pubDate>
      <link>https://forem.com/amehdaly/sudo-for-windows-4dcb</link>
      <guid>https://forem.com/amehdaly/sudo-for-windows-4dcb</guid>
      <description>&lt;p&gt;Many of us may face a small problem with windows terminal (&lt;code&gt;command line&lt;/code&gt;) when going to execute some commands that require an admin privilege while the shell is opened in normal user privilege, so we have to restart the shell using &lt;code&gt;Run As Administrator&lt;/code&gt; in order to proceed, whilst  in Linux we simply use &lt;code&gt;sudo&lt;/code&gt; command to execute whatever we want as a root user.&lt;br&gt;
Here we have solution for this issue in Windows, just follow the following steps:&lt;br&gt;
1- Using &lt;code&gt;PowerShell&lt;/code&gt; terminal execute the following command line to install &lt;a href="https://scoop.sh/" rel="noopener noreferrer"&gt;scoop&lt;/a&gt; package installer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\&amp;gt;iwr -useb get.scoop.sh | iex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Then after installing "scoop" in your system install "sudo" package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\&amp;gt;scoop install sudo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will be able to use &lt;code&gt;sudo&lt;/code&gt; command same as in Linux, for example in order to install npm package globally we have to run &lt;code&gt;npm install&lt;/code&gt; in a privilege mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\&amp;gt;sudo npm install –g bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As well as having a &lt;code&gt;sudo&lt;/code&gt; option in Windows, we will have the ability to install packages in Windows using "scoop" similar to &lt;code&gt;apt&lt;/code&gt; &amp;amp; &lt;code&gt;apt-get&lt;/code&gt; in Linux.&lt;br&gt;
For more information how to use scoop visit :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://scoop.sh/" rel="noopener noreferrer"&gt;https://scoop.sh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/lukesampson/scoop/wiki" rel="noopener noreferrer"&gt;https://github.com/lukesampson/scoop/wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

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