<?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: Mateus Cechetto</title>
    <description>The latest articles on DEV Community by Mateus Cechetto (@mateuscechetto).</description>
    <link>https://dev.to/mateuscechetto</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%2F1504099%2F69f74f0e-89a8-4eda-b0bc-4c7ebb5795af.png</url>
      <title>DEV Community: Mateus Cechetto</title>
      <link>https://dev.to/mateuscechetto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mateuscechetto"/>
    <language>en</language>
    <item>
      <title>How to Avoid Common Localization Pitfalls: Real-World Tips for Internationalizing Your Product</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 24 Aug 2025 17:25:06 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/how-to-avoid-common-localization-pitfalls-real-world-tips-for-internationalizing-your-product-8oe</link>
      <guid>https://dev.to/mateuscechetto/how-to-avoid-common-localization-pitfalls-real-world-tips-for-internationalizing-your-product-8oe</guid>
      <description>&lt;p&gt;When I first joined the team building a global product, I overlooked what it truly meant to support multiple languages and cultures. Little more than a year after, and building products localized to over 10 languages, I've learned a lot about internationalization (I18n), localization (L10n), and all the things that can go wrong when you don't plan for them from day one. In this article I'll share my learning, pain points, aha moments, so you don't have to learn the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should We Adapt Our Products?
&lt;/h2&gt;

&lt;p&gt;We spend huge amounts of time, money, and effort building products. So when we finally launch, we want to maximize the reach of what we've built. That's where internationalization and localization come into play.&lt;/p&gt;

&lt;p&gt;Let's quickly look at the business side of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TAM/SAM/SOM: If you're not familiar, these are market sizing terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TAM (Total Addressable Market): Everyone who could possibly use your product.&lt;/li&gt;
&lt;li&gt;SAM (Serviceable Available Market): Everyone your product can currently serve.&lt;/li&gt;
&lt;li&gt;SOM (Serviceable Obtainable Market): The segment you're realistically targeting right now.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Without localization, your SOM is probably just a fraction of your TAM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By localizing your product, you're instantly multiplying your potential userbase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is I18n (Internationalization)?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Internationalization (often abbreviated as I18n) is the process of designing and preparing your software to be adapted to different languages and regions without needing engineering changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Think of I18n as making your product "translation-ready."&lt;/p&gt;

&lt;h3&gt;
  
  
  What is L10n (Localization)?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Localization (L10n) is the actual adaptation of the product for a specific locale — translating strings, formatting dates, currencies, adjusting layouts, and more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I18n is the foundation; L10n is the finishing touch.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we do it at my team?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Translation Management: Crowdin&lt;br&gt;
We use &lt;a href="https://crowdin.com/" rel="noopener noreferrer"&gt;Crowdin&lt;/a&gt; to manage our translation workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports both free (community-driven) and paid (professional translators) options.&lt;/li&gt;
&lt;li&gt;Web interface to upload source files, manage translations, and download the results.&lt;/li&gt;
&lt;li&gt;Integrates well with GitHub and CI/CD pipelines.&lt;/li&gt;
&lt;li&gt;Workflow: &lt;code&gt;Upload source files → Translate → Download translations&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Web Frontend: React + i18next&lt;br&gt;
We use &lt;a href="https://www.i18next.com/" rel="noopener noreferrer"&gt;i18next&lt;/a&gt; for our React frontend.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for plurals, interpolation, and namespaces&lt;/li&gt;
&lt;li&gt;Integrates well with TypeScript&lt;/li&gt;
&lt;li&gt;Easy to use with context-aware translations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Desktop C#: System.Globalization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We rely on &lt;code&gt;System.Globalization.CultureInfo&lt;/code&gt; and &lt;code&gt;LocalizeDictionary&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Allows setting and parsing based on locale-specific rules&lt;/li&gt;
&lt;li&gt;Supports dynamic updates without recompilation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;CI/CD: GitHub Actions&lt;br&gt;
We've automated the translation process with GitHub Actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically upload new source strings to Crowdin on PR merge&lt;/li&gt;
&lt;li&gt;Download translated files before builds&lt;/li&gt;
&lt;li&gt;Ensures our product is always translation-ready&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Real-World Learnings
&lt;/h2&gt;

&lt;p&gt;Here are some practical examples of situations where localization was tricky and some learnings I took from them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Leave Space in the UI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We had a "Subscribe" button in the UI that looked great in English, but we decided to add a small indicator showing that a sale was live. In English, "Sale" was just a 4-character word. However, when we localized the button into Portuguese, the translation for "Sale" (Promoção) was 9 characters. This led to the text overflowing and the button becoming misaligned, leaving a poor user experience.&lt;/li&gt;
&lt;li&gt;In the mobile version of our website, one page has 4 tabs. In some languages the labels of the tabs are too long and, instead of dynamically resizing or wrapping into a new line, it pushed the layout and created a terrible vertical horizontal scroll.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: The key here is to &lt;strong&gt;leave space for the string to grow or shrink&lt;/strong&gt;, but also &lt;strong&gt;make sure there's a fallback system&lt;/strong&gt; for when the text is too long. You might want to set behaviors for text overflow, such as wrapping or truncating text, there is no silver bullet, the correct approach depends on the layout. This ensures your UI doesn't break under different languages, while also looking polished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One Word, Multiple Meanings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Take the word "Test". In English, we use the word "test" in different contexts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A product feature that allows the user to run a test.&lt;/li&gt;
&lt;li&gt;A message that says "Test completed successfully."&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, in German, the word "Test" might get confusing because it's often used in an academic or examination context (like "Prüfung" in German). Depending on the context, the translation can vary significantly. This requires us to make sure that translators have context, so we avoid using the same word in completely different places.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: When you're using crowdsourcing for translations, &lt;strong&gt;always provide context to avoid confusion&lt;/strong&gt;. This could be as simple as including a description of where the text appears or providing screenshots. Context helps translators pick the right word for the right situation, preventing misunderstandings that can result in awkward or incorrect translations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Never Concatenate Strings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Imagine an error message when a user fails to complete a form. In English, the sentence is structured like this:&lt;br&gt;
  &lt;code&gt;You forgot to enter your email.&lt;/code&gt;&lt;br&gt;
If you try to concatenate the message in code like:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You forgot to enter &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;userField&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;You may run into issues when translating this into languages where word order is different. For example, in German, the sentence structure might be reversed:&lt;br&gt;
   &lt;code&gt;Du hast vergessen, deine E-Mail einzugeben.&lt;/code&gt;&lt;br&gt;
In German, the phrase "forgot to enter" is split and the subject ("Du" meaning "You") is often placed before the verb in this context. Simply concatenating strings would lead to an unnatural or grammatically incorrect translation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: To avoid this, use a flexible template-based system where placeholders are separated from the text and translators can adjust word order appropriately. For example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You forgot to enter {0}.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;That, since it is just one string, can be easily translated to:&lt;br&gt;
&lt;code&gt;Du hast vergessen, {0} einzugeben.&lt;/code&gt;&lt;br&gt;
Here, {0} is a placeholder for the field name, and translators can change the word order as needed for proper grammar in each language.&lt;br&gt;
By using a template system, you're allowing each language's grammatical rules to be respected, without hardcoding any word order. This is key to maintaining natural, fluent translations that make sense in all supported languages.&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Always Parse Inputs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We had a bug where we had to parse a string from our API to a float. We were calling C#'s &lt;code&gt;float.TryParse()&lt;/code&gt; without specifying number style or culture info. That led the application to not handle correctly for user's where their machines locale were from places where the decimal separator is ',' instead of '.'.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: &lt;strong&gt;Always parse inputs, even if they're not directly coming from the user&lt;/strong&gt;. For example, when your backend receives a date from the system or when pulling data from the database, ensure that the formatting is locale-aware. This avoids errors that would break the application when users from different regions interact with your product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Lists, Plurals, Gendered Terms&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Beware about lists, plurals and gendered terms, as languages tend to vary a lot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: &lt;strong&gt;Templates&lt;/strong&gt; should account for plurals, gendered terms, and different sentence structures. Use libraries like i18next (for frontend) or built-in features in your framework for pluralization and gender handling, and avoid hardcoding singular/plural forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Don't Delay I18n&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This was a hard lesson, and the reason I wrote this. We had a feature that dynamically generated messages based on user behavior, pulling data directly from the database. The feature worked perfectly in English, but we realized too late that it was built without translation in mind. The system was generating strings with parameters that were non-translatable. By the time we realized this, it was one week before the planned product release, and we had to remove it from the initial feature set, even tho it was functionally working.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Tip&lt;/strong&gt;: &lt;strong&gt;Localization should never be an afterthought&lt;/strong&gt;. Ideally, I18n should be integrated into the very early stages of product development. If you wait until the final stages of a release, you might end up with functional features that can't be localized, forcing you to delay the release or ship an incomplete product. Always plan for localization from day one.&lt;/p&gt;

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

&lt;p&gt;If you're building a global product, localization is not optional, it's a core product concern. And like all core concerns, you should address it from day one.&lt;/p&gt;

&lt;p&gt;You're going to make mistakes. That's okay. What matters is that you treat localization as part of the development process, not an afterthought. With the right tools, workflows, and mindset, your product can speak to the world!&lt;/p&gt;

&lt;p&gt;I'd love to hear how your team handles internationalization and localization. What tools do you use? What hard lessons have you learned? Drop a comment below!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>i18n</category>
    </item>
    <item>
      <title>How Angular Schematics Help Developers Scale Architecture and Team Efficiency</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sat, 10 May 2025 20:45:03 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/how-angular-schematics-help-developers-scale-architecture-and-team-efficiency-3kck</link>
      <guid>https://dev.to/mateuscechetto/how-angular-schematics-help-developers-scale-architecture-and-team-efficiency-3kck</guid>
      <description>&lt;p&gt;As software engineers, our job isn't just writing features or fixing bugs. We're responsible for improving the processes around software and help teams move faster, safer, and more consistently. That means asking questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can we reduce repetitive tasks?&lt;/li&gt;
&lt;li&gt;Can we encode best practices so new team members don't guess?&lt;/li&gt;
&lt;li&gt;Can we lower the mental load of starting new features?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Angular projects, &lt;strong&gt;Schematics&lt;/strong&gt; is one of the best tools to operationalize these improvements. It lets you automate architecture, encode standards, and enforce patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an Angular Schematic?
&lt;/h2&gt;

&lt;p&gt;A schematic in Angular is a set of instructions that tells the Angular CLI how to generate or transform code. Think of it as a script that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create new files using templates.&lt;/li&gt;
&lt;li&gt;Update existing code (e.g. add a component to a module).&lt;/li&gt;
&lt;li&gt;Enforce consistent project structure and naming.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Schematics are part of the Angular DevKit, which powers the Angular CLI under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular CLI's Built-in Schematics
&lt;/h3&gt;

&lt;p&gt;When you run commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng generate component my-button
ng generate module user
ng generate service auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're using the default schematics that come with the Angular CLI. These generate standardized Angular code based on best practices and update related files (e.g. module declarations).&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Schematics
&lt;/h3&gt;

&lt;p&gt;The built-in schematics are great out of the box, but for larger projects, they're often not enough. That's why Angular also has support for custom schematics, that let you define your own scaffolding rules and project structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example #1 - Automating Test Setup
&lt;/h2&gt;

&lt;p&gt;In a project, we used an in-house testing framework that wrapped Angular's TestBed with custom setup logic (mocks, utilities, providers). But Angular CLI always generated test files using default Jasmine boilerplate.&lt;/p&gt;

&lt;p&gt;To avoid always copy-pasting the test setup, I built a schematic that created a &lt;code&gt;spec.ts&lt;/code&gt; file with our custom setup: injecting the right testing providers, imports and assert functions.&lt;/p&gt;

&lt;p&gt;Result: every component came with a ready to use test setup according to our project. It saved us time from rewriting the same test setup in every component, and enforced good practices, making new devs aware of our testing framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example #2 - Feature Architecture
&lt;/h2&gt;

&lt;p&gt;In my personal projects, I follow a &lt;strong&gt;feature-first architecture&lt;/strong&gt;, breaking my app into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;features&lt;/code&gt;: which contain the features of the app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shared&lt;/code&gt;: utility code shared across many features.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;layout&lt;/code&gt;: header, sidebars, footer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each feature includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-access&lt;/code&gt;: services and state management.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;feature&lt;/code&gt;: smart component.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ui&lt;/code&gt;: dumb components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To support that structure, I created &lt;a href="https://github.com/mateuscechetto/angular-feature-schematics" rel="noopener noreferrer"&gt;this schematic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a new feature folder with subfolders and base files.&lt;/li&gt;
&lt;li&gt;Adds a service (with HttpClient injection).&lt;/li&gt;
&lt;li&gt;Creates a smart component with routing set up.&lt;/li&gt;
&lt;li&gt;Updates &lt;code&gt;tsconfig&lt;/code&gt; to support path aliases (e.g., &lt;code&gt;@my-feature&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;Adds the new route to the central route config, intelligently placing it before the wildcard &lt;code&gt;**&lt;/code&gt; route.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It isn't just about saving time, it is about &lt;strong&gt;making good architecture easy&lt;/strong&gt; and &lt;strong&gt;hard to deviate from&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Schematics are one of the rare tools that let you automate both boilerplate and best practices. Codegen isn't just for saving keystrokes. It's about scaling your team's ability to build the right thing the right way. Angular Schematics are a powerful, underused tool that engineers can leverage to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Codify architecture.&lt;/li&gt;
&lt;li&gt;Reduce onboarding time.&lt;/li&gt;
&lt;li&gt;Lower error rates.&lt;/li&gt;
&lt;li&gt;Improve development velocity without chaos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're writing architecture docs or review checklists, consider: could this be a schematic instead?&lt;/p&gt;

&lt;h3&gt;
  
  
  Links - How to create a Schematic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://angular.dev/tools/cli/schematics" rel="noopener noreferrer"&gt;Angular Schematics Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.telerik.com/blogs/the-what-and-how-of-angular-schematics-the-super-simple-version" rel="noopener noreferrer"&gt;The What and How of Angular Schematics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nado261.medium.com/schematics-angular-5110c008f0f" rel="noopener noreferrer"&gt;Playing with Schematics — Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://angular.dev/tools/cli/schematics-authoring" rel="noopener noreferrer"&gt;Schematics authoring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>C# Functional Programming with Delegates and Higher-order functions</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Wed, 07 May 2025 23:45:05 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/c-functional-programming-with-delegates-and-higher-order-functions-2le1</link>
      <guid>https://dev.to/mateuscechetto/c-functional-programming-with-delegates-and-higher-order-functions-2le1</guid>
      <description>&lt;p&gt;C# is often known for its object-oriented roots, but it also has a very strong functional programming capability. At the heart of this functionality are &lt;strong&gt;delegates&lt;/strong&gt;, which enable higher-order functions (HOFs). If you've ever used LINQ in C#, you've already used HOFs without realizing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Higher-Order Functions?
&lt;/h2&gt;

&lt;p&gt;In functional programming, a higher-order function is a function that &lt;strong&gt;takes one or more functions as arguments&lt;/strong&gt;, &lt;strong&gt;returns a function&lt;/strong&gt;, &lt;strong&gt;or both&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This concept allows for more abstract, reusable, and declarative code. In C#, HOFs are implemented using &lt;strong&gt;delegates&lt;/strong&gt;, &lt;strong&gt;lambda expressions&lt;/strong&gt;, and &lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/" rel="noopener noreferrer"&gt;expression trees&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delegates
&lt;/h2&gt;

&lt;p&gt;A delegate in C# is a type that represents a reference to a method with a particular parameter list and return a particular type. Delegates are used to pass methods as arguments to other methods, enabling the creation of flexible and reusable code.&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;delegate&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;MathOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&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="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&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="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&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;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;PerformOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MathOperation&lt;/span&gt; &lt;span class="n"&gt;operation&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="nf"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MathOperation&lt;/span&gt; &lt;span class="n"&gt;addOperation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;MathOperation&lt;/span&gt; &lt;span class="n"&gt;multiplyOperation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;PerformOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;addOperation&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;PerformOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;multiplyOperation&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;$"Sum: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Product: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&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;p&gt;In this example, &lt;code&gt;PerformOperation&lt;/code&gt; is a HOF that takes &lt;code&gt;MathOperation&lt;/code&gt; delegate as an argument, allowing different operations to be passed and executed.&lt;/p&gt;

&lt;p&gt;In C#, there are three primary ways to define and use delegates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom delegate types&lt;/strong&gt; using the &lt;code&gt;delegate&lt;/code&gt; keyword (like the example above)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in delegates:&lt;/strong&gt; &lt;code&gt;Func&amp;lt;&amp;gt;&lt;/code&gt;, &lt;code&gt;Action&amp;lt;&amp;gt;&lt;/code&gt;, and &lt;code&gt;Predicate&amp;lt;&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anonymous methods/Lambda expressions&lt;/strong&gt; for inline definitions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using built-in delegates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Func&amp;lt;T, TResult&amp;gt;&lt;/code&gt; is used when the delegate returns a value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Action&amp;lt;T&amp;gt;&lt;/code&gt; is used when the delegate returns void&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Predicate&amp;lt;T&amp;gt;&lt;/code&gt; is used when the delegate returns a boolean. We usually use it for semantic, when we have a set of criteria and want to determine whether the parameters meet those criteria. In practice, it is the same as &lt;code&gt;Func&amp;lt;T, bool&amp;gt;&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiply&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;log&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;=&amp;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;message&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="s"&gt;"Hello from Action!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lambda Expressions
&lt;/h2&gt;

&lt;p&gt;Lambda expressions provide a concise way to represent anonymous methods (functions without a name). They are particularly useful when working with LINQ queries and functional constructs.&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&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="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// using with LINQ&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numbers&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;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="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9&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;evenNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="m"&gt;2&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Under the Hood of LINQ: Higher-Order Functions in Action
&lt;/h2&gt;

&lt;p&gt;Language Integrated Query (LINQ) is a powerful feature in C# that allows us to query and manipulate data in a declarative manner. When you use LINQ methods like &lt;code&gt;.Where()&lt;/code&gt;, &lt;code&gt;.Select()&lt;/code&gt;, or &lt;code&gt;.Any()&lt;/code&gt;, you are passing delegates into higher-order functions.&lt;/p&gt;

&lt;p&gt;In the previous example, we used &lt;code&gt;.Where()&lt;/code&gt;, this is what its signature looks like under the hood:&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;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Func&amp;lt;TSource, bool&amp;gt;&lt;/code&gt; is the delegate type.&lt;/li&gt;
&lt;li&gt;The lambda &lt;code&gt;x =&amp;gt; x % 2 == 0&lt;/code&gt; matches the signature and is passed as the predicate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World example
&lt;/h2&gt;

&lt;p&gt;In our case, we are building a system based on a card game. We want to make it so when a user hovers a card in hand, it highlights the cards in the deck that have synergy with the hovered card.&lt;/p&gt;

&lt;p&gt;We added a delegate in our cardlist class, that receives a card, the decklist and returns the color that we will highlight the cards:&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="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Hearthstone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Hearthstone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;ShouldHighlightCard&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gave us the flexibility to implement the function to decide if we will highlight a card in each card:&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;Thunderbringer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Neutral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Thunderbringer&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsElemental&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsBeast&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsElemental&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsBeast&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;Birdwatching&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hunter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Birdwatching&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&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="s"&gt;"Minion"&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 &lt;code&gt;Thunderbringer&lt;/code&gt; card highlights cards that are both &lt;code&gt;Elemental&lt;/code&gt; and &lt;code&gt;Beast&lt;/code&gt; in one color, only &lt;code&gt;Elemental&lt;/code&gt; in another, only &lt;code&gt;Beast&lt;/code&gt; in a third color, and leaves the rest unhighlighted. The &lt;code&gt;Birdwatching&lt;/code&gt; card highlights any card of type &lt;code&gt;Minion&lt;/code&gt;. If you're curious, here's the implementation of the &lt;code&gt;HighlightColorHelper&lt;/code&gt; class:&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighlightColorHelper&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="k"&gt;readonly&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;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_colorMapping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Teal&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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orange&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&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;static&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;conditions&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;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;for&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;i&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="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&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;conditions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;continue&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;_colorMapping&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;i&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;color&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;color&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;return&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;C#'s support for delegates and higher-order functions opens up a world of possibilities for developers looking to write more functional and expressive code. By embracing these concepts, you can write code that is not only more powerful but also more elegant and maintainable. Understanding these delegate forms helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read and write more expressive LINQ queries&lt;/li&gt;
&lt;li&gt;Pass behavior around in your applications like data&lt;/li&gt;
&lt;li&gt;Create APIs that are extensible and composable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So next time you use &lt;code&gt;.Where()&lt;/code&gt; or &lt;code&gt;.Select()&lt;/code&gt;, you'll know that you're already writing functional code in C#.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Why Naming Is Hard in Programming (and Why LLMs Struggle Write Real Code)</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sat, 03 May 2025 01:58:02 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/why-naming-is-hard-in-programming-and-why-llms-struggle-write-real-code-3bee</link>
      <guid>https://dev.to/mateuscechetto/why-naming-is-hard-in-programming-and-why-llms-struggle-write-real-code-3bee</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Naming in code isn't just a syntax concern, it's a design decision. Good names reduce cognitive load, but every name is a cost. In this article, we'll look at why naming is hard, why natural language can't replace code, and when it's better to duplicate than abstract.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Naming in software is famously difficult, and for a good reason. While we tend to seek to write clean and elegant code, we often forget that names themselves are a source of complexity. Names are not just labels, they are &lt;strong&gt;abstractions&lt;/strong&gt;, and each one comes with a &lt;strong&gt;cognitive and maintenance cost&lt;/strong&gt;. In this post we are going to explore why naming is hard, why code duplication isn't always bad and why we should seek for simplicity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Programming Languages Exist?
&lt;/h2&gt;

&lt;p&gt;We didn't invent programming languages because they are cool, we created them because natural languages like English are fundamentally bad at describing technical ideas. Take the Pythagorean theorem as an example, the English version is clunky, long and not easy to understand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the sum of the squares on the legs of a right triangle is equal to the square on the hypotenuse&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The algebraic notation, &lt;code&gt;a² + b² = c²&lt;/code&gt;, is far more compact and unambiguous. That's the power of a specialized language, and the same applies to programming languages.&lt;/p&gt;

&lt;p&gt;When we write code, we are always using (at least) 2 languages: the programming language, like Python or Java, and a natural language, usually English, for naming variables, functions and files. The programming language is precise, the natural language is not. That's where the trouble begins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why LLMs Can't Replace Programmers
&lt;/h3&gt;

&lt;p&gt;There is a growing trend to treat large language models (LLMs) as code generators. And there are some people who fear that they can replace programmers. But here is the issue: they rely on natural language to interpret intent, and that is inherently fuzzy. Prompting in a natural language to write code is like asking a poet to draft legal policy, the precision just isn't there. Programming languages exist because English can't express what we need in software clearly. They are purpose-built for clarity and logic. English isn't. LLMs are a great tool to increase productivity, accelerate learning and produce boilerplates, but they cannot replace coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every Name Is a Cost
&lt;/h2&gt;

&lt;p&gt;A new name in your code, where it's a variable, function or class, isn't free, it comes with &lt;strong&gt;cognitive load&lt;/strong&gt;. It has to be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understood by the team&lt;/li&gt;
&lt;li&gt;Maintained&lt;/li&gt;
&lt;li&gt;Aligned with future code changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even small indirections can add up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;shouldSendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way you need to check what &lt;code&gt;shouldSendNotification()&lt;/code&gt; does. Sometimes it's better to &lt;strong&gt;inline simple logic&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;optedOut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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;Inline logic keeps the behavior visible at the call site, which is often more readable than a name wrapping simple conditions that adds extra indirection.&lt;/p&gt;

&lt;p&gt;In one project, I had to debug a nested flow where every condition had its own well-named function—but I still couldn't understand the logic without jumping up and down on the code. Inlining the conditions made the bug obvious in seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Names Are Bad Comments
&lt;/h2&gt;

&lt;p&gt;Variable and functions names are made for humans, as the compilers don't care about them. But different than comments, you cannot use punctuations, spaces, and usually want to keep names short and identifiable. That makes it hard to find good names for many things. &lt;strong&gt;Like comments, names can go stale&lt;/strong&gt;. And &lt;strong&gt;having a bad name can mislead the developer&lt;/strong&gt; that will face that code in the future, making it harder to maintain and potentially generating bugs. For example, instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;handleUserData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// actually just filters inactive users&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;filterInactiveUsers&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;And if it's simple logic? Skip the name entirely:&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;filteredUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastLogin&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Have Naming Conventions
&lt;/h2&gt;

&lt;p&gt;As we are seeing, naming is hard, but having consistent naming makes it easier to read and understand, reducing the cognitive load. That's why having a clear and enforced naming convention across your codebase is critical.&lt;/p&gt;

&lt;p&gt;Think of it this way: when you see a function named &lt;code&gt;getUser()&lt;/code&gt; in one file, and &lt;code&gt;loadCustomerData()&lt;/code&gt; in another, and &lt;code&gt;fetchPerson()&lt;/code&gt; elsewhere, your brain has to stop and ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are these the same concept?&lt;/li&gt;
&lt;li&gt;Do they behave the same way?&lt;/li&gt;
&lt;li&gt;Do they return the same type of object?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This mental overhead adds up especially in large teams or mature codebases. A consistent convention eliminates that ambiguity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the naming scheme is predictable. You don't have to guess whether "fetch" or "load" means something different. You can scan the code faster and understand relationships between functions more easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Familiar Patterns Make Code Easier to Navigate
&lt;/h3&gt;

&lt;p&gt;When teams follow a naming convention (e.g., verbs for functions, nouns for models, isX for booleans), it becomes easier to guess what something does—even if you've never seen that part of the code before. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;isActiveUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// boolean&lt;/span&gt;
&lt;span class="nf"&gt;calculateTotal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// function&lt;/span&gt;
&lt;span class="nx"&gt;UserOrder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// model or class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This predictability allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search faster&lt;/li&gt;
&lt;li&gt;Spot mistakes quickly&lt;/li&gt;
&lt;li&gt;Understand new code without diving into every implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naming conventions are not just about syntax, they are about &lt;strong&gt;shared understanding&lt;/strong&gt;. When your whole team adheres to the same patterns, you reduce misunderstandings and speed up onboarding for new engineers. They also allow tools (linters, code formatters, type checkers) to help you more effectively. The more structured your code is, the more tooling can automate quality enforcement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the Real Business Language and Terms
&lt;/h2&gt;

&lt;p&gt;If you're building software for a non-English-speaking domain (Brazilian finance or Japanese logistics), &lt;strong&gt;don't change key business terms to awkward English translations&lt;/strong&gt;. It's better to use the language your stakeholders use, even inside the codebase. Terms like &lt;code&gt;boleto&lt;/code&gt;, &lt;code&gt;kanban&lt;/code&gt;, or &lt;code&gt;kakeibo&lt;/code&gt; might not have clean English equivalents. Translating them poorly makes the code harder to understand, not easier.&lt;/p&gt;

&lt;p&gt;I worked at a Brazilian project in the Education field where we had individual classes, group of classes defined by the platform, and group of classes defined by the user. Internally, we used Portuguese names to describe each one of them. But in code, the teams decided to use English translations, but the backend and the frontend team didn't communicate with each other, so they ended up having different names for the same things, and even worse, we had a common name meaning two different things for the backend and the frontend. So the frontend &lt;code&gt;/studyPlan&lt;/code&gt; page was calling &lt;code&gt;/api/classes&lt;/code&gt; and the &lt;code&gt;/classes&lt;/code&gt; was calling&lt;code&gt;/api/courses&lt;/code&gt;. This misalignment wasn't just annoying, it caused real bugs and friction across the teams. Using the domain's native terms in code would have avoided the confusion entirely.&lt;/p&gt;

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

&lt;p&gt;Writing good code isn't about abstracting everything into elegant patterns. It's about being clear, honest, and readable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't name what doesn't need naming&lt;/li&gt;
&lt;li&gt;Don't abstract every repeated line&lt;/li&gt;
&lt;li&gt;Do name things based on what they are now&lt;/li&gt;
&lt;li&gt;Do prefer clear duplication over vague generalization&lt;/li&gt;
&lt;li&gt;Do use business terms exactly as your users say them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fewer names means less mental overhead, fewer misunderstandings, and cleaner maintenance.&lt;/p&gt;

&lt;p&gt;Sometimes, the best code looks boring.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cleancode</category>
      <category>ai</category>
    </item>
    <item>
      <title>Handling Evolving Requirements: Leveraging C# Params for Variable Number of Parameters</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 02 Mar 2025 23:00:20 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/handling-evolving-requirements-leveraging-c-params-for-variable-number-of-parameters-2f93</link>
      <guid>https://dev.to/mateuscechetto/handling-evolving-requirements-leveraging-c-params-for-variable-number-of-parameters-2f93</guid>
      <description>&lt;p&gt;When building software, we need to be aware that the requirements &lt;strong&gt;will&lt;/strong&gt; change over time. Knowing that, we need to write code that is easy to maintain and to modify. Recently, in my project we had code that looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICardWithHighlight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&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;Pretty simple and straightforward code. The cards that implemented that interface would have to set a condition if they should highlight or not other cards. Then a new requirement arrived: cards could now be highlighted in Green or Yellow, depending on different conditions. This forced us to change the interface, because only telling if they should highlight was not enough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICardWithHighlight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&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;enum&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Yellow&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighlightColorHelper&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;static&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;condition&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;condition&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;static&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;secondCondition&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;condition&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;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&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;secondCondition&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;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yellow&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;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our code can highlight cards with one condition in green, and we use &lt;strong&gt;method overloading&lt;/strong&gt; to handle two conditions as well. However, it's evident that this solution isn't the best. What if we needed to highlight with another color for a third condition, and a fourth, fifth... With the current solution, we would have to create new methods for each color, and all of those methods would look very similar.&lt;/p&gt;

&lt;p&gt;This is where C# &lt;a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/method-parameters?redirectedfrom=MSDN#params-modifier" rel="noopener noreferrer"&gt;parameter arrays&lt;/a&gt; can help us. By using the &lt;code&gt;params&lt;/code&gt; keyword, we can make our &lt;code&gt;GetHighlightColor()&lt;/code&gt; method accept a variable number of parameters of the specified type. If you pass a multiple values, C# will automatically convert them into an array of that type.&lt;/p&gt;

&lt;p&gt;With it, we can update the &lt;code&gt;GetHighlightColor()&lt;/code&gt; without breaking compatibility with the existing code (when we changed &lt;code&gt;ICardWithHighlight&lt;/code&gt; to make &lt;code&gt;ShouldHighlight()&lt;/code&gt; return a color, we had to update our entire codebase). This approach improves flexibility and maintainability, making it easier to add new colors.&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;enum&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Pink&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighlightColorHelper&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="k"&gt;readonly&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;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_colorMapping&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yellow&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Red&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blue&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pink&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;static&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;conditions&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;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;for&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;i&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="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&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;conditions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;continue&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;_colorMapping&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;i&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;color&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;color&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;return&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;params bool[] conditions&lt;/code&gt;: The &lt;code&gt;params&lt;/code&gt; keyword allows the method to accept any number of boolean conditions. The conditions are passed as an array, which gives us the flexibility to pass as many conditions as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dictionary Mapping:&lt;/strong&gt; We use a dictionary &lt;code&gt;_colorMapping&lt;/code&gt; to map each condition index to a specific color. This approach avoids using hard-coded indices or a long &lt;code&gt;switch&lt;/code&gt; statement. Adding a new color simply requires adding a new entry to the dictionary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritized Matching:&lt;/strong&gt; The method processes each condition in the order in which it is passed, returning the color for the first condition that is &lt;code&gt;true&lt;/code&gt;. If no conditions are met, it returns &lt;code&gt;HighlightColor.None&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Highlights 1 cost minion&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;TrustyFishingRod&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hunter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrustyFishingRod&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="k"&gt;is&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;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MINION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cost&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Highlights elementals in one color and beasts in other&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;Thunderbringer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Neutral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Thunderbringer&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsElemental&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsBeast&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Highlights 1 cost spells in one color, 2 cost spells in other and 3 cost spells in another&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;BarakKodobane&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hunter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BarakKodobane&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="k"&gt;is&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;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SPELL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="k"&gt;is&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;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SPELL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="k"&gt;is&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;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SPELL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&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 the example above, the &lt;code&gt;params&lt;/code&gt; method allows for an arbitrary number of conditions to be passed. The caller doesn't need to worry about implementation details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At the call site:&lt;/strong&gt; The params keyword allows you to pass any number of arguments of the specified type. If you pass more than one argument, they are automatically packed into an array.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the method:&lt;/strong&gt; The method receives an array of the specified type, and you can access the arguments as you would with any other array in C#.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Array Creation:&lt;/strong&gt; When you use params, the compiler automatically creates an array to hold the passed arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Because the arguments are converted to an array, the overhead is similar to any array creation in C#.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; You can pass an array directly or provide a list of arguments, which makes it more flexible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Other Languages Solve the Same Problem
&lt;/h2&gt;

&lt;p&gt;This problem is not new; most languages have a way to deal with it, and most solutions are very similar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Java&lt;/strong&gt; has &lt;code&gt;varargs&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;getHighlightColor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At the call site:&lt;/strong&gt; Java allows you to pass a comma-separated list of arguments of the specified type. Java internally converts this list into an &lt;strong&gt;array&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the method:&lt;/strong&gt; The method receives the arguments as an array of the specified type.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Array Creation:&lt;/strong&gt; Similar to C#, &lt;code&gt;varargs&lt;/code&gt; in Java are converted into an array. The array is created at runtime, and each argument is added to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; The performance is largely similar to C# in that the arguments are stored in an array, which has a fixed overhead for array creation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overloading:&lt;/strong&gt; One important distinction is that Java requires you to overload methods when you want to use other arguments alongside varargs. This can introduce complexity if not handled carefully.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Typescript&lt;/strong&gt; has &lt;code&gt;rest parameters&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;HighlightColor&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At the call site:&lt;/strong&gt; The rest parameters syntax (&lt;code&gt;...args&lt;/code&gt;) collects all passed arguments into a single array-like object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the method:&lt;/strong&gt; Inside the method, you can treat the arguments as an array (or tuple, depending on the context).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Array Creation:&lt;/strong&gt; TypeScript (and JavaScript) creates an array-like object to hold the arguments passed to the function. This is essentially a readonly array that cannot be resized after the function call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internally:&lt;/strong&gt; The rest parameter syntax is a more declarative approach over the traditional arguments object, which allows for better type safety and readability.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Go&lt;/strong&gt; has &lt;code&gt;variadic functions&lt;/code&gt; using &lt;code&gt;slices&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;getHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conditions&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At the call site:&lt;/strong&gt; Go functions expect a slice (which can be created from an array or passed directly as an argument). You can use the ... operator to pass an array or slice to a function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the method:&lt;/strong&gt; The function accepts a slice, which is a reference to an underlying array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you call &lt;code&gt;func(1, 2, 3)&lt;/code&gt;, the compiler takes those arguments, wraps them in a slice, and passes that slice to the function. Internally, Go has to allocate memory for the slice on the heap, so be mindful of the overhead when passing large numbers of arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slice Internals:&lt;/strong&gt; Go's slices are reference types, so when you pass a slice to a function, you are passing a reference to the underlying array (not a copy). This is more memory efficient compared to passing an array by value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Slices in Go are much more efficient than arrays because they are dynamically sized and use a reference to the underlying array. The slice itself contains three fields: a pointer to the array, a length, and a capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility:&lt;/strong&gt; Go's slices are more flexible as they allow efficient manipulation of data without needing to recreate a new array every time.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt; has &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_highlight_color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At the call site:&lt;/strong&gt; Python allows you to pass a variable number of positional arguments using &lt;code&gt;*args&lt;/code&gt; (denoted by a star *). If you want to pass keyword arguments (key-value pairs), you use &lt;code&gt;**kwargs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At the method:&lt;/strong&gt; The method receives these arguments as a tuple (&lt;code&gt;*args&lt;/code&gt;) and a dictionary (&lt;code&gt;**kwargs&lt;/code&gt;), where &lt;code&gt;*args&lt;/code&gt; holds all positional arguments and &lt;code&gt;**kwargs&lt;/code&gt; holds all keyword arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Behind the Scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Argument Packing:&lt;/strong&gt; In Python, when &lt;code&gt;*args&lt;/code&gt; is used, the arguments are packed into a tuple. Similarly, &lt;code&gt;**kwargs&lt;/code&gt; collects the keyword arguments into a dictionary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; The performance overhead of &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; is relatively low compared to some other languages, as Python handles them with dynamic typing and doesn't involve the creation of strongly-typed arrays. However, there's still a small memory overhead because Python needs to create a tuple for &lt;code&gt;*args&lt;/code&gt; and a dictionary for &lt;code&gt;**kwargs&lt;/code&gt; to store the passed arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unpacking:&lt;/strong&gt; Python allows you to unpack arguments passed to &lt;code&gt;*args&lt;/code&gt; and &lt;code&gt;**kwargs&lt;/code&gt; into other function calls, making it a flexible way to work with variable numbers of arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cherry on top of our solution
&lt;/h2&gt;

&lt;p&gt;If you remember, our solution used &lt;strong&gt;Dictionary Mapping&lt;/strong&gt; to get the correct &lt;code&gt;HighlightColor&lt;/code&gt; depending on the conditions. Newer versions of C# allow us to use &lt;strong&gt;Pattern Matching&lt;/strong&gt; to return the color based on the "shape" of the conditions array.&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;static&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;conditions&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;conditions&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Matches when the first element is true&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;..]&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Matches when the first element is false, second is true&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Matches when the first two elements are false, third is true&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;..]&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Matches when the first three elements are false, fourth is true&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&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="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Matches when the first four elements are false, fifth is true&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;..]&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Fallback for when no specific pattern matches&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HighlightColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;..&lt;/code&gt; in the pattern matching syntax is called the "discard" or "rest" pattern, and it is used to match and ignore any remaining elements in the array. It allows you to match a specific subset of elements in a collection while ignoring the rest. For example, &lt;code&gt;[true, ..]&lt;/code&gt; matches when the first element is &lt;code&gt;true&lt;/code&gt;, but it doesn't care what the rest of the elements are, allowing you to match any sequence where the first boolean is &lt;code&gt;true&lt;/code&gt;, returning &lt;code&gt;HighlightColor.Green&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;_&lt;/code&gt; is a &lt;strong&gt;wildcard&lt;/strong&gt; that acts as a fallback when none of the patterns are met, returning &lt;code&gt;HighlightColor.None&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;In this article, we've explored how software requirements change over time and how C# solves the problem of handling a variable number of inputs to a method. We've also looked at how other languages approach the same problem. This approach not only makes your code more flexible and scalable but also keeps it clean, maintainable, and easy to extend as your requirements evolve. Whether we're adding more conditions or introducing new colors, this solution provides a simple and powerful way to handle dynamic, condition-based logic in our application.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>designpatterns</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Method Hiding and Overriding in C#: A Real-World Problem Solved</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Thu, 20 Feb 2025 21:15:14 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/understanding-method-hiding-and-overriding-in-c-a-real-world-problem-solved-587j</link>
      <guid>https://dev.to/mateuscechetto/understanding-method-hiding-and-overriding-in-c-a-real-world-problem-solved-587j</guid>
      <description>&lt;p&gt;I recently faced a problem at my work that revolved around populating dictionaries depending on interfaces, but one of the derived types wasn't showing up in the expected collection. After digging deeper, I came across a concept that was new to me: &lt;strong&gt;method hiding&lt;/strong&gt;. It was causing my derived class to be unsuitable for the interface. I was familiar with method overriding, but I had never encountered method hiding before.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk through the problem I faced, how I solved it, and explain the concepts and differences between method hiding and method overriding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I was working on a system where cards were represented by classes implementing &lt;code&gt;ICard&lt;/code&gt; interface. Cards typically implement &lt;code&gt;ICard&lt;/code&gt; indirectly through other interfaces, such as &lt;code&gt;ICardWithHighlight&lt;/code&gt; and &lt;code&gt;ICardWithRelatedCards&lt;/code&gt;, which extend &lt;code&gt;ICard&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetCardId&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;interface&lt;/span&gt; &lt;span class="nc"&gt;ICardWithHighlight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&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;interface&lt;/span&gt; &lt;span class="nc"&gt;ICardWithRelatedCards&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;ShouldShowForOpponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;opponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetRelatedCards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system uses &lt;strong&gt;reflection&lt;/strong&gt; to dynamically load all the card classes and check which interface they implement. The goal is to populate dictionaries with card instances, keyed by their unique &lt;code&gt;CardId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The card &lt;code&gt;Arcanologist&lt;/code&gt; has 2 different ids; therefore, it has 2 card classes: &lt;code&gt;Arcanologist&lt;/code&gt; and &lt;code&gt;ArcanologistCore&lt;/code&gt;, each implementing &lt;code&gt;GetCardId()&lt;/code&gt; with its respective value. Since they refer to the same card, I used inheritance so that their &lt;code&gt;ShouldHighlight()&lt;/code&gt; method remains consistent across both classes. However, I faced a problem: the derived class &lt;code&gt;ArcanologistCore&lt;/code&gt; wasn't been added to the &lt;code&gt;HighlightCards&lt;/code&gt; dictionary, even though it seemed to be a valid implementation of &lt;code&gt;ICardWithHighlight&lt;/code&gt;.&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;RelatedCardsManager&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;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;ICardWithRelatedCards&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;_relatedCards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;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;ICardWithHighlight&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;_highlightCards&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;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;ICardWithRelatedCards&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;RelatedCards&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_relatedCards&lt;/span&gt; &lt;span class="p"&gt;??=&lt;/span&gt; &lt;span class="nf"&gt;InitializeRelatedCards&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;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;ICardWithHighlight&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HighlightCards&lt;/span&gt;  &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_highlightCards&lt;/span&gt; &lt;span class="p"&gt;??=&lt;/span&gt; &lt;span class="nf"&gt;InitializeHighlightCards&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;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;ICardWithRelatedCards&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;InitializeRelatedCards&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relatedCardsDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlightCardsDict&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;InitializeCards&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;_highlightCards&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highlightCardsDict&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;relatedCardsDict&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="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;ICardWithHighlight&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;InitializeHighlightCards&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relatedCardsDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlightCardsDict&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;InitializeCards&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;_relatedCards&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relatedCardsDict&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;highlightCardsDict&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="p"&gt;(&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;ICardWithRelatedCards&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&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;ICardWithHighlight&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="nf"&gt;InitializeCards&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;cards&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="nf"&gt;GetAssembly&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;ICard&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;ICard&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;relatedCardsDict&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;ICardWithRelatedCards&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;highlightCardsDict&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;ICardWithHighlight&lt;/span&gt;&lt;span class="p"&gt;&amp;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;card&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cards&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;cardInstance&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;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ICard&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;cardInstance&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ICardWithRelatedCards&lt;/span&gt; &lt;span class="n"&gt;relatedCard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;relatedCardsDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;relatedCard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;relatedCard&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;cardInstance&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&lt;/span&gt; &lt;span class="n"&gt;highlightCard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;highlightCardsDict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;highlightCard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highlightCard&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;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;relatedCardsDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;highlightCardsDict&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 the code above: - &lt;strong&gt;Reflection&lt;/strong&gt; is used to load all types in the assembly that implements the &lt;code&gt;ICard&lt;/code&gt; interface. - We check if the type implement the &lt;code&gt;ICardWithHighlight&lt;/code&gt; or &lt;code&gt;ICardWithRelatedCards&lt;/code&gt; to add it to the appropriate dictionary. - Lazily initialize the Dictionaries, and when one is initialized, also initializes the other one.&lt;/p&gt;

&lt;p&gt;Now, let's take a look at the &lt;code&gt;Arcanologist&lt;/code&gt; and &lt;code&gt;ArcanologistCore&lt;/code&gt; classes:&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;Arcanologist&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arcanologist&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&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;ArcanologistCore&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arcanologist&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;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArcanologistCore&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;
  
  
  The Issue
&lt;/h2&gt;

&lt;p&gt;The problem occurred when &lt;code&gt;ArcanologistCore&lt;/code&gt; wasn't appearing in the &lt;code&gt;HighlightCards&lt;/code&gt; dictionary. Even though &lt;code&gt;ArcanologistCore&lt;/code&gt; correctly implemented &lt;code&gt;ICardWithHighlight&lt;/code&gt; and had its own &lt;code&gt;GetCardId()&lt;/code&gt; method, it was still being ignored when populating the dictionary.&lt;/p&gt;

&lt;p&gt;My first solution was to manually add &lt;code&gt;ICardWithHighlight&lt;/code&gt; to the &lt;code&gt;ArcanologistCore&lt;/code&gt; class. This worked, and the card started appearing in the dictionary.&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;ArcanologistCore&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arcanologist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArcanologistCore&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;But I was not satisfied with this solution. I have always knew that in OOP when a class extends other, it should be implementing all its interfaces, so why did I need to explicitly write that my derived class was implementing that interface? So I start looking into an answer for this, and I found it. It is called &lt;strong&gt;Method Hiding&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Method Hiding and Method Overriding?
&lt;/h2&gt;

&lt;p&gt;In C#, &lt;strong&gt;method hiding&lt;/strong&gt; occurs when a derived class defines a method with the same name as a method in the base class, but without using the &lt;code&gt;override&lt;/code&gt; keyword. This causes the derived class's method to hide the base class's method. When using method hiding, the base class method is not called — instead, the method in the derived class is used only if the reference is specifically of the derived type. This way, since &lt;code&gt;GetCardId()&lt;/code&gt; in the base class was hidden, &lt;code&gt;ArcanologistCore&lt;/code&gt; no longer fully implemented the &lt;code&gt;ICard&lt;/code&gt; interface, and as a result, it did not implement &lt;code&gt;ICardWithHighlight&lt;/code&gt; either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method overriding&lt;/strong&gt;, on the other hand, happens when a derived class uses the override keyword to provide its own implementation of a method from the base class. This ensures that the method in the derived class is called, even if the reference is of the base class type.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;The solution was straightforward: instead of using the &lt;code&gt;new&lt;/code&gt; keyword in the &lt;code&gt;GetCardId()&lt;/code&gt; method in &lt;code&gt;ArcanologistCore&lt;/code&gt;, I needed to use &lt;code&gt;override&lt;/code&gt; to properly override the method from the base class. This ensures that when an object of type &lt;code&gt;ArcanologistCore&lt;/code&gt; is referenced as an &lt;code&gt;ICardWithHighlight&lt;/code&gt;, the overridden method is called, allowing the card to be added to the dictionary. I also had to mark the base class method as &lt;code&gt;virtual&lt;/code&gt; to tell C# that the method can be overridden.&lt;/p&gt;

&lt;p&gt;Here is the corrected implementation:&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;Arcanologist&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithHighlight&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;virtual&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Arcanologist&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;HighlightColor&lt;/span&gt; &lt;span class="nf"&gt;ShouldHighlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;HighlightColorHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetHighlightColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&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;ArcanologistCore&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Arcanologist&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;string&lt;/span&gt; &lt;span class="nf"&gt;GetCardId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CardIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArcanologistCore&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;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;After changing the &lt;code&gt;new&lt;/code&gt; keyword to &lt;code&gt;override&lt;/code&gt; in the derived class, the card was properly added to &lt;code&gt;HighlightCards&lt;/code&gt; dictionary, and the issue was resolved. This experience helped me understand the distinction between &lt;strong&gt;method hiding&lt;/strong&gt; and &lt;strong&gt;method overriding&lt;/strong&gt; in C#.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>programming</category>
      <category>oop</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Lazy Loading Pattern: When and Why to Use It</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Wed, 22 Jan 2025 22:20:48 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/lazy-loading-pattern-when-and-why-to-use-it-34df</link>
      <guid>https://dev.to/mateuscechetto/lazy-loading-pattern-when-and-why-to-use-it-34df</guid>
      <description>&lt;h2&gt;
  
  
  What is Lazy Loading?
&lt;/h2&gt;

&lt;p&gt;Lazy Loading is a design pattern that defers the initialization of an object or resource until it is actually needed. Instead of creating the object at the start of the program or application, the system waits until the first time the object is accessed, at which point it is created and cached for future use. As &lt;a href="https://martinfowler.com/eaaCatalog/lazyLoad.html" rel="noopener noreferrer"&gt;Martin Fowler wrote&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An object that doesn't contain all of the data you need but knows how to get it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is particularly useful when dealing with expensive objects or resources that might not always be required. By delaying their creation until they are needed, Lazy Loading can help improve performance, save memory, and reduce unnecessary overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Lazy Loading in Action
&lt;/h2&gt;

&lt;p&gt;Let’s take a look at an example to see how Lazy Loading works in practice.&lt;/p&gt;

&lt;p&gt;In our case, we are building a system based on a card-based game, and one of the cards, the Mothership, has related cards that can be accessed. These related cards are minions with the Protoss tag. Here's how it could be implemented:&lt;/p&gt;

&lt;h3&gt;
  
  
  Computing on Every Call
&lt;/h3&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;Mothership&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithRelatedCards&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;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetRelatedCards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&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;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&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;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROTOSS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MINION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&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;&lt;strong&gt;Explanation:&lt;/strong&gt; the related cards are computed every time &lt;strong&gt;GetRelatedCards()&lt;/strong&gt; is called, regardless of whether they were computed before.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Initial Cost:&lt;/strong&gt; It is only calculated when the method is called.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Overhead:&lt;/strong&gt; This approach incurs a high performance cost since the list is recomputed every time it is requested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inefficient:&lt;/strong&gt; If the related cards don’t change often or are used repeatedly, recalculating them on every call is wasteful in terms of both CPU and memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Immediate Initialization
&lt;/h3&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;Mothership&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithRelatedCards&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&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;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROTOSS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MINION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&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;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetRelatedCards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_options&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;&lt;strong&gt;Explanation:&lt;/strong&gt; the related cards are computed immediately when the object is created, regardless of whether they will be used.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simpler Code:&lt;/strong&gt; The code is simpler because there’s no need to check for null or implement caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Delay on Access:&lt;/strong&gt; The list is always available, so there is no initial delay when accessing the related cards.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wasted Resources:&lt;/strong&gt; If the related cards are not always needed (as in our case, when the card isn’t played in a game), this approach can waste memory. All related cards are precomputed and stored in memory, even if they are never used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Initial Cost:&lt;/strong&gt; When an object is instantiated, the related cards are computed right away, which can slow down initialization when creating many card objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially, we used Immediate Initialization for the related cards, but the approach introduced problems when creating many card objects because of the high inital cost and memory usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy Loading Pattern
&lt;/h3&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;Mothership&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICardWithRelatedCards&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;?&lt;/span&gt; &lt;span class="n"&gt;_cache&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="k"&gt;public&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;Card&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetRelatedCards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&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;_cache&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;_cache&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HearthDb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cards&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collectible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&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;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROTOSS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;CardType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MINION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&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;_cache&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;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading:&lt;/strong&gt; The list of related cards (&lt;code&gt;_cache&lt;/code&gt;) is initially set to &lt;code&gt;null&lt;/code&gt;. Only when &lt;code&gt;GetRelatedCards()&lt;/code&gt; is called for the first time is the list populated with the minions that have the PROTOSS tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; After the list is created, it’s cached in the &lt;code&gt;_cache&lt;/code&gt; field, so subsequent calls to &lt;code&gt;GetRelatedCards()&lt;/code&gt; return the cached list without recalculating it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Lazy Loading Works Best
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory Efficiency:&lt;/strong&gt; The related cards are only computed when necessary, and the list is cached for future calls. If the related cards aren’t used, they are never computed, saving memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Initialization Cost:&lt;/strong&gt; The initial creation of the object is faster because the related cards are not precomputed upfront.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Repeated Computation:&lt;/strong&gt; Once the list of related cards is computed, it is cached, preventing repeated calculations and reducing CPU overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The primary trade-off of Lazy Loading is the &lt;strong&gt;initial delay&lt;/strong&gt; on the first access of the related cards, but this is usually a small price to pay for significant memory savings and improved performance over the long term.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cache Invalidation
&lt;/h2&gt;

&lt;p&gt;One of the key considerations when using Lazy Loading (or caching in general) is &lt;strong&gt;cache invalidation&lt;/strong&gt;. While caching can significantly improve performance by reducing the need for repeated calculations or data retrieval, it also introduces the challenge of ensuring that cached data remains &lt;strong&gt;accurate and up-to-date&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When data changes—whether because of user actions, external data updates, or any other factors—the cached version of the data can become &lt;strong&gt;stale&lt;/strong&gt;. This means that when you access the cache, you might be retrieving outdated or incorrect information. To prevent this, caches need to be invalidated or refreshed at appropriate times.&lt;/p&gt;

&lt;p&gt;In our case, we are working with a &lt;strong&gt;static&lt;/strong&gt; pool of cards. The related cards are based on predefined tags and type, and this data does not change dynamically during gameplay. The card pool is known and limited: the existent cards are fixed, and there are no external factors or events that would require frequent updates to the related cards. Because of that, cache invalidation is not a concern in our specific scenario. As a result, once the related cards are cached, they can be reused without worrying about data becoming stale.&lt;/p&gt;

&lt;p&gt;However, if our scenario involved &lt;strong&gt;dynamic data&lt;/strong&gt; (for example, if the tags or types of cards could change during gameplay, or if new cards were introduced or removed) then cache invalidation strategies would need to be implemented. To handle this, we would need to implement cache invalidation strategies, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time-based expiration:&lt;/strong&gt; Cache is invalidated after a certain amount of time has passed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual invalidation:&lt;/strong&gt; Cache is manually cleared when the system detects that a change has occurred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-based invalidation:&lt;/strong&gt; Cache is invalidated when specific events occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our hypothetical problem, event-based invalidation would be the better choice because it automatically handles changes and keeps your cache in sync without manual intervention. For example, in a game with real-time card updates, events like "card changed," "card removed," or "new card added" could trigger the invalidation of caches for related cards.&lt;/p&gt;

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

&lt;p&gt;Lazy Loading is a powerful design pattern that can help optimize performance by deferring the creation of expensive objects until they are needed.&lt;br&gt;
By comparing Lazy Loading with Immediate Initialization and Computing on Every Call, we can clearly see its benefits in scenarios where resources like memory and CPU time need to be managed carefully. When used correctly, Lazy Loading can greatly enhance the performance of your application, especially in resource-constrained environments.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
      <category>designpatterns</category>
      <category>performance</category>
    </item>
    <item>
      <title>Extension Methods</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 15 Dec 2024 19:16:04 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/extension-methods-57m1</link>
      <guid>https://dev.to/mateuscechetto/extension-methods-57m1</guid>
      <description>&lt;p&gt;Recently on my work, I had to add a new functionality to a class that I don't control. Subclassing was my first idea, but it didn't feel good because it had tightly coupled to the existing class and had limited flexibility. After looking for alternatives, I considered composition but then I discovered C# &lt;a href="https://en.wikipedia.org/wiki/Extension_method" rel="noopener noreferrer"&gt;Extension Methods&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Extension Methods let you "attach" methods to existing classes or objects. This approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enhances &lt;em&gt;readability&lt;/em&gt; by using object-oriented syntax. It allows the developers to call the added functionality as if it were part of the original class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoids &lt;em&gt;code duplication&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintains &lt;em&gt;separation of concerns&lt;/em&gt;, keeping extensions separate from the original class, which aligns with the &lt;em&gt;Open/Closed Principle&lt;/em&gt; of object-oriented design—software entities should be open to extension but closed for modification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduces &lt;em&gt;boilerplate&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enables the creation of &lt;a href="https://en.wikipedia.org/wiki/Fluent_interface" rel="noopener noreferrer"&gt;fluent interfaces&lt;/a&gt;, which allow for chaining method calls in a way that mimics natural language&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple, fluent syntax is far more intuitive than using standalone utility functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Different Languages Implement Extension-Like Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  C# and Kotlin: Native Extension Methods
&lt;/h3&gt;

&lt;p&gt;Both C# and Kotlin provide first-class support for extension methods or functions. These mechanisms are type-safe and validated at compile time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C#: Extension Methods:
C# defines extension methods as static methods in a separate class, using this to indicate the type being extended:
&lt;/li&gt;
&lt;/ul&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StringExtensions&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;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsUpperCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;str&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;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsUpper&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;string&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HELLO"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Kotlin: Extension Functions
Kotlin’s implementation is concise and integrated seamlessly:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;  &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Boolean&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&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="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;word&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HELLO"&lt;/span&gt;
  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JavaScript: Prototype Extension
&lt;/h3&gt;

&lt;p&gt;JavaScript allows extensions through its &lt;code&gt;prototype&lt;/code&gt; mechanism, enabling developers to add methods to built-in objects.&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="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isUpperCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HELLO&lt;/span&gt;&lt;span class="dl"&gt;"&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;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While powerful, modifying prototypes is not recommended and comes with risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pollution: Adding methods to native prototypes can conflict with future JavaScript features or third-party libraries.&lt;/li&gt;
&lt;li&gt;Global Effects: Changes apply globally, affecting all instances of the type.&lt;/li&gt;
&lt;li&gt;Debugging Challenges: Modifying core types makes issues harder to track.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Utility Functions in Java and TypeScript
&lt;/h3&gt;

&lt;p&gt;Languages without native support, like Java and TypeScript, rely on utility functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StringUtils&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toUpperCase&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Usage&lt;/span&gt;
  &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HELLO"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isUpperCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Typescript
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;str&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HELLO&lt;/span&gt;&lt;span class="dl"&gt;"&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;isUpperCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Utility functions are safe but lack the fluency of object-oriented extension methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Languages and Monkey Patching
&lt;/h3&gt;

&lt;p&gt;Dynamic languages like Python and Ruby allow direct modification of existing classes or objects, a technique known as &lt;strong&gt;monkey patching&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_upper_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;self&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_upper_case&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_upper_case&lt;/span&gt;

  &lt;span class="c1"&gt;# Usage
&lt;/span&gt;  &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HELLO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_upper_case&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ruby
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_upper_case&lt;/span&gt;
          &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Usage&lt;/span&gt;
  &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HELLO"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_upper_case&lt;/span&gt; &lt;span class="c1"&gt;# True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While monkey patching is flexible, it’s risky for similar reasons as js prototype.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rust: Traits
&lt;/h3&gt;

&lt;p&gt;Rust offers a unique alternative with traits and trait implementations. Instead of modifying a type directly, you implement a trait to add functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;IsUpperCase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_upper_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;IsUpperCase&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_upper_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="nf"&gt;.to_uppercase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HELLO"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&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;word&lt;/span&gt;&lt;span class="nf"&gt;.is_upper_case&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust’s traits ensure extensions are scoped and composable, offering safety without sacrificing flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World example
&lt;/h2&gt;

&lt;p&gt;One very useful case in C# is to filter out null values from &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;?&lt;/code&gt; transforming it into &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;:&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnumerableExtensions&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;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WhereNotNull&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Extension Mechanism&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;Extension Methods&lt;/td&gt;
&lt;td&gt;Type-safe, elegant syntax&lt;/td&gt;
&lt;td&gt;Requires static class&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;Extension Functions&lt;/td&gt;
&lt;td&gt;Concise, seamless integration&lt;/td&gt;
&lt;td&gt;Limited to scoped extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;Prototype Extension&lt;/td&gt;
&lt;td&gt;Powerful, dynamic&lt;/td&gt;
&lt;td&gt;Risk of conflicts, global effects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java, Typescript&lt;/td&gt;
&lt;td&gt;Utility Functions&lt;/td&gt;
&lt;td&gt;Safe, avoids modifying types&lt;/td&gt;
&lt;td&gt;Verbose, lacks fluency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python, Ruby&lt;/td&gt;
&lt;td&gt;Monkey Patching&lt;/td&gt;
&lt;td&gt;Flexible, easy to implement&lt;/td&gt;
&lt;td&gt;Debugging challenges, risky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Traits&lt;/td&gt;
&lt;td&gt;Type-safe, scoped, composable&lt;/td&gt;
&lt;td&gt;Slightly verbose&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Balancing Power and Safety
&lt;/h2&gt;

&lt;p&gt;Extension methods offer a clean and flexible way to enhance existing types without modifying their source code, improving readability and maintainability.&lt;br&gt;
Each language’s approach to extending functionality reflects its core philosophy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic languages prioritize flexibility but risk stability.&lt;/li&gt;
&lt;li&gt;Statically typed languages favor safety and maintainability.&lt;/li&gt;
&lt;li&gt;Rust’s traits stand out as a hybrid, balancing flexibility with compile-time guarantees.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>csharp</category>
      <category>python</category>
      <category>rust</category>
    </item>
    <item>
      <title>Allowlist vs Denylist: When to use them</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 03 Nov 2024 00:27:43 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/allowlist-vs-denylist-when-to-use-them-5d6c</link>
      <guid>https://dev.to/mateuscechetto/allowlist-vs-denylist-when-to-use-them-5d6c</guid>
      <description>&lt;p&gt;In software development, managing access to resources and features is a common challenge. Two common approaches to regulate access are the use of allow and deny lists. These strategies determine whether certain users, inputs, or systems are allowed or denied access, but they do so in opposite ways.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's worth noting the recent shift in terminology within the software industry. Terms like 'allowlist' and 'denylist' are being adopted over the older 'whitelist' and 'blacklist' to promote more inclusive language. This shift reflects a broader industry trend toward fostering diversity and inclusivity in both coding practices and team dynamics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What is Allowlist?
&lt;/h3&gt;

&lt;p&gt;An &lt;em&gt;allowlist&lt;/em&gt; is a list of entities (such as users, inputs, or services) that are explicitly permitted to access a feature or resource. If something is not on the allowlist, it is &lt;strong&gt;automatically denied access by default&lt;/strong&gt;. They are often used to control access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feature Flags:&lt;/strong&gt; Granting early access to new features for specific users or testers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs:&lt;/strong&gt; Allowing only approved applications or users to interact with your API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inputs:&lt;/strong&gt; Ensuring only approved inputs or data formats are accepted by the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Advantages of Allowlisting
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tighter Control:&lt;/strong&gt; Allowlisting provides a high level of security, allowing only pre-approved entities to access the system. This is ideal when the number of trusted users or inputs is limited and well-defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Quality Assurance:&lt;/strong&gt; When deploying a feature to a select group of users (such as beta testers), a allowlist ensures that only trusted individuals access it, minimizing unexpected issues.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better Prevention of Abuse:&lt;/strong&gt; Allowlists can prevent unauthorized or malicious access by ensuring only verified entities are granted permission.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Disadvantages of Allowlisting
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Maintenance:&lt;/strong&gt; Managing an allowlist can be time-consuming, especially as the number of approved users, inputs, or services grows. Every new entity must be vetted and added manually.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Flexibility:&lt;/strong&gt; Legitimate users or inputs can be inadvertently excluded if not added to the list, which can cause delays or inconvenience during development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Slower Iteration:&lt;/strong&gt; For fast-moving projects, constantly updating the allowlist can slow down progress, especially when dealing with external partners or APIs that require regular changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is Denylist?
&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;denylist&lt;/em&gt; is a list of entities that are specifically denied access, while &lt;strong&gt;everything else is permitted by default&lt;/strong&gt;. In software development, denylisting is commonly used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Block Unwanted Users:&lt;/strong&gt; Preventing bad actors or known spammers from accessing an app or platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter Out Bad Inputs:&lt;/strong&gt; Rejecting harmful data, such as SQL injection attacks or cross-site scripting attempts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control Feature Access:&lt;/strong&gt; Disabling features for specific users who may have violated terms of service or encountered a known issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Advantages of Denylisting
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less Restrictive:&lt;/strong&gt; Denylists allow for more flexibility, as they only block specific entities, letting new users or inputs flow through without needing explicit permission.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easier to Implement:&lt;/strong&gt; In fast-paced development environments, denylists are easier to manage because they require action only when there is something to block, rather than vetting each new user or input in advance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broader Access:&lt;/strong&gt; Denylists are well-suited to systems with a wide range of users or inputs, where most entities are safe or acceptable, and only specific ones need to be blocked.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Disadvantages of Denylisting
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Gaps:&lt;/strong&gt; Denylists rely on identifying known issues or bad actors. If an attacker or harmful input isn't already on the list, it could slip through undetected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reactive Approach:&lt;/strong&gt; Denylists tend to be reactive rather than proactive, as they focus on blocking known threats. New or evolving issues may go unnoticed until damage is done.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  When to use Allowlists vs Denylists
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allowlists:&lt;/strong&gt; Use when you need tight control over access, such as rolling out features or managing critical resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Denylists:&lt;/strong&gt; Use when you have a broad user base or only need to block known threats and exceptions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Criteria&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Allowlist&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Denylist&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Default Behavior&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Denies all by default; only approved entities are allowed&lt;/td&gt;
&lt;td&gt;Allows all by default; only blocks specific entities&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Restricted access systems, e.g., admin panels&lt;/td&gt;
&lt;td&gt;Public-facing systems, e.g., user-generated content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security Approach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proactive; limits risk by approving only known entities&lt;/td&gt;
&lt;td&gt;Reactive; blocks known malicious entities after they act&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintenance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High; requires ongoing approval for new users/entities&lt;/td&gt;
&lt;td&gt;Lower; only requires updating to block malicious activity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Potential Pitfalls&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Risk of excluding legitimate entities accidentally&lt;/td&gt;
&lt;td&gt;Risk of letting unknown malicious entities slip through&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Real-world examples
&lt;/h3&gt;

&lt;p&gt;The inspiration for discussing this topic came from two scenarios my team faced last month, where we had to choose between using an allowlist or a denylist.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Game Modes Tracking:&lt;/strong&gt; In this situation, we needed to track specific features for different game modes. Each feature was tied to an allowlist of game modes where it made sense to exist. This way, if a new game mode was introduced, it wouldn’t automatically receive those features, preventing any potential information leaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Card Draw Source Tracking:&lt;/strong&gt; The second scenario involved tracking whether a card was drawn generically or via a tutored draw (where specific cards are targeted). For tutored draws, revealing the source of the draw is crucial, while showing the source of a generic draw adds noise. We opted for a denylist in this case. If we missed identifying a card, it would result in showing unnecessary information (just noise, but not critical). With an allowlist, missing a tutored card would result in missing valuable information, which would have been much worse.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Choosing between allowlists and denylists depends on the specific requirements. If you need strict control and limited access, an allowlist offers higher security. For larger, more dynamic systems where the majority of users or inputs are safe, a denylist offers more flexibility. Both approaches have their pros and cons, but understanding when and how to apply them will help you manage access effectively in your software projects.&lt;/p&gt;

</description>
      <category>programming</category>
    </item>
    <item>
      <title>Complicate Your Personal Projects</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Fri, 04 Oct 2024 00:56:24 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/complicate-your-personal-projects-lgi</link>
      <guid>https://dev.to/mateuscechetto/complicate-your-personal-projects-lgi</guid>
      <description>&lt;p&gt;Recently, personal projects have increasingly become a gold rush where people are focused on building the simplest "microsaas" possible in the hope of creating passive income. There's nothing wrong with profitable projects or launching a Minimum Viable Product (MVP) and iterating. In fact, that’s how most successful products are built, and its a practice I do myself. But in this article, I want to offer a different perspective: &lt;strong&gt;why you should deliberately complicate your personal projects as much as possible.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fun Factor
&lt;/h3&gt;

&lt;p&gt;When I start a personal project, I usually have two goals: solve a problem I face in real life and improve my skills. This is why I often choose technologies I’m still learning or apply patterns I’m not fully comfortable with yet. It challenges me to deepen my understanding of these technologies, and since it’s a personal project, I have the freedom to make mistakes and learn from them. The freedom to try new things without constraints is what makes personal projects fun. The fun itself is the motivation that keeps the personal project from being abandoned like so many unfinished ideas that every engineer has.&lt;/p&gt;

&lt;p&gt;In my professional life, I follow established patterns and maintain consistency within the codebase. In contrast, personal projects give me space to experiment. I try different approaches, play with patterns I’m unfamiliar with, and if I find them valuable, I start applying them in my professional work as well. This experimentation alongside the autonomy of making and learning from my own mistakes, makes the process more enjoyable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Custom Hearthstone Deck Validator
&lt;/h3&gt;

&lt;p&gt;Take one of my recent personal projects, a custom Hearthstone deck validator. The project’s purpose was to allow users to define custom deck-building rules for tournaments or casual play. Instead of taking the easy route and creating dropdowns for predefined options, I complicated things on purpose. I opted for a text input where users could write the rules they wanted, which meant I had to create a Domain-Specific Language (DSL) to process and validate these rules.&lt;/p&gt;

&lt;p&gt;To build the DSL, I revisited concepts I hadn’t touched since my compilers classes, such as tokenization. Rather than using regular expressions, I manually tokenized the input to have more control and flexibility. Manual tokenization allowed me to separate syntax and semantic validation, making error messages more helpful and detailed. This project was also the first time that using Test-Driven Development (TDD) genuinely enhanced my development experience.&lt;/p&gt;

&lt;p&gt;On top of that, I learned about &lt;a href="https://github.com/microsoft/monaco-editor" rel="noopener noreferrer"&gt;Monaco Editor&lt;/a&gt; (the same editor that powers Visual Studio Code) and decided to integrate it to provide real-time syntax highlighting for my DSL. I had to learn how to add a custom language to it, and it was &lt;strong&gt;incredibly satisfying&lt;/strong&gt; when the editor correctly highlighted valid input and flagged errors. Each new piece of complexity taught me something new, things I would not have learned if I had taken the "easy" route.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fb9k2hau236tubq14dx1f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fb9k2hau236tubq14dx1f.png" alt="Custom Hearthstone Deck Validator" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;
Custom Hearthstone Deck Validator



&lt;h3&gt;
  
  
  Example 2: Hearthstone Set Review Hub
&lt;/h3&gt;

&lt;p&gt;Another personal project that became more complex than necessary was the Hearthstone Set Review Hub. The core idea was simple: a central platform where players could rate new cards. That's something a basic spreadsheet could handle. But I decided to spice it up. I wanted to make it interactive for streamers by allowing their Twitch chat to submit ratings in real time directly to the hub.&lt;/p&gt;

&lt;p&gt;This led me to learn about IRC protocol and discover &lt;a href="https://github.com/tmijs/tmi.js" rel="noopener noreferrer"&gt;tmi.js&lt;/a&gt;. The complexity escalated when I realized that I had to handle multiple streamers using the system at the same time, requiring creating and managing multiple instances of TMI clients.&lt;/p&gt;

&lt;p&gt;Then, as the next Hearthstone expansion approached, I found myself on a tight deadline. I needed to release a working version before the expansion hype peaked (in approximately 20 days), which forced me to simplify my product. To make the most minimal viable product, I built a simple UI with just text fields and a button. Instead of using a database, I opted for Google Sheets to store the data, as streamers were already familiar with spreadsheets. My system would simply add a new page with chat ratings to their existing spreadsheet. I had to learn the Google Sheets API and handle its rate limits. To avoid exceeding the rate limit, I batched the ratings before writing them. But this introduced a new problem: how should the system handle multiple ratings for the same card? If a user sent more than one rating, how would I update the previous one if it was in a different batch?&lt;/p&gt;

&lt;p&gt;I solved this by storing all ratings in memory until the streamer finished rating the card. Only then would I send the data to the spreadsheet. These decisions, even though they seem obvious in hindsight, were challenging under time pressure. Each problem I faced required a new skill or a new way of thinking. As my operating systems professor once said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My exams are easy. It’s simple to spot a deadlock or a race condition when you've spent the past months studying them and you're analyzing a piece of code that &lt;em&gt;probably&lt;/em&gt; contains one. The real challenge is recognizing these issues when your production system is behaving unpredictably, and you're not even sure they could be the cause."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I released the project, and it was well-received by the community, leading to donations, contributor interest, and further development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffasj2letsltyt3ddoco3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffasj2letsltyt3ddoco3.png" alt="HS Set Review Bot MVP" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;
HS Set Review Bot MVP



&lt;p&gt;As development continued, I didn't stop challenging myself. This project significantly enhanced my skills in writing scripts to automate various tasks. It also deepened my understanding of observability, caching strategies, analytics, CI/CD, web scraping, and even Machine Learning. With the help of an old classmate, we trained a classification model to rate card after the expansion, using cards stats data to compare with the ratings users gave before the expansion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F84mopm1hxncmd2tnsg7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F84mopm1hxncmd2tnsg7z.png" alt="Current HS Set Review Homepage" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;
Current HS Set Review Homepage



&lt;p&gt;&lt;a href="https://media.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%2F8wg233lx10rsw15ohndi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8wg233lx10rsw15ohndi.png" alt="Current HS Set Review Review Page" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;
Current HS Set Review Review Page



&lt;h3&gt;
  
  
  Why Complicate Things?
&lt;/h3&gt;

&lt;p&gt;Both of these projects became much more complex than they needed to be. But this complexity forced me to learn at an accelerated pace. The things I learned in just a few months compares to what I could have gained over years in a typical work environment. The key difference was that I was the one making the decisions, dealing with the consequences, and reaping the rewards when things went well.&lt;/p&gt;

&lt;p&gt;At work, you typically have well-defined roles and responsibilities, and a lot of decisions are made by senior team members. You might specialize in one part of the stack, rarely touching others. But in a personal project, you're the architect, developer, tester, and product manager all in one. You control the technology choices, the design, and how deep you want to dive into different areas of the stack. This forces you to broaden your skills and become a more well-rounded developer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knowledge &amp;gt; Money
&lt;/h3&gt;

&lt;p&gt;While these projects never had the goal of making money, the knowledge and experience I gained were far more valuable in the long run. They directly contributed to my career growth. I landed my current position because one of those projects caught the attention of a company. Additionally, these projects give me plenty to talk about in interviews and meetups. People get excited when I share the lessons learned, the decisions I made, and the struggles I faced. &lt;/p&gt;

&lt;p&gt;Your career, like life, is a marathon, not a sprint. Focus on becoming valuable, and the rewards will follow, rather than fixating on getting money as quickly as possible.&lt;/p&gt;

&lt;p&gt;So, my advice: complicate your personal projects. Choose technologies you’re unfamiliar with. Push yourself into areas you haven’t explored before. Learn from your mistakes. You’ll walk away with a wealth of knowledge, confidence, and skills that will benefit you far more than trying to build the simplest microsaas for quick cash.&lt;/p&gt;

</description>
      <category>career</category>
      <category>sideprojects</category>
      <category>discuss</category>
    </item>
    <item>
      <title>When does TDD make sense?</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 22 Sep 2024 19:01:23 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/when-does-tdd-make-sense-5h16</link>
      <guid>https://dev.to/mateuscechetto/when-does-tdd-make-sense-5h16</guid>
      <description>&lt;p&gt;Throughout my career, I often heard that Test-Driven Development (TDD) is an effective approach for building software. However, I struggled to see the benefits for a long time. This changed recently when I was working on a project where TDD was an ideal fit. In that instance, it significantly improved my development process, making it faster and less prone to errors. In this article, I will explain when to use TDD and why it works best in certain scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  When TDD Falls Short
&lt;/h3&gt;

&lt;p&gt;While TDD is a powerful methodology, it's not always the right tool for the job. Here are a couple of scenarios where applying TDD can be more problematic than beneficial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unclear or Evolving Requirements&lt;/strong&gt;: When requirements are ambiguous or still evolving, writing tests upfront can feel like shooting in the dark. In these cases, we need to explore the problem space, experiment with different approaches, and iterate on the design as we learn more. Trying to lock in tests before understanding what the code should do wastes time and stifles creativity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Low Domain Logic&lt;/strong&gt;: In cases where the codebase is mostly concerned with handling input/output (I/O) operations or simple tasks, there’s little value in writing tests first. For example, building a "Hello World" program is a clear case where TDD is overkill. The code is too simple, too stable, and has little to no logic to test. If the code heavily interacts with external systems like databases, file systems, or APIs, writing unit tests upfront can be inconvenient and less effective. The high ratio of boundary code (e.g., I/O) versus actual domain logic means that the return on investment for TDD is low.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When to use TDD
&lt;/h3&gt;

&lt;p&gt;Now let’s look at when TDD shines. From my recent experience, I found that TDD works best in scenarios where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Requirements&lt;/strong&gt;: In the project I mentioned, the requirements were crystal clear. I knew exactly what the expected output of each function should be for every type of input. This allowed me to write the tests first with confidence that they reflected the desired behavior. Because of the clarity, the tests guided the development, ensuring that my implementation was correct and met the business needs from the get-go.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Domain Logic&lt;/strong&gt;: If you’re working on a system with a lot of complex business rules, TDD becomes incredibly valuable. In this case, each test verifies that a specific part of the logic behaves correctly. I experienced this firsthand: after adding each new piece of functionality, I ran my tests to see what was missing and iterated on the code until all tests passed. This made me confident that each new change didn’t break any existing behavior.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why to use TDD
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavior-Driven Focus&lt;/strong&gt;: Writing tests first helped me focus on the behavior, not the implementation. This is an essential distinction, as it prevents tests from being too tightly coupled to the internal workings of the code. Instead, the tests reflect what the code should do, making refactoring easier without breaking the tests unnecessarily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Long-Term Maintenance&lt;/strong&gt;: One of the biggest advantages of TDD is the long-term stability it brings. As I revisited the project later to add new features or improve existing functionality, my existing tests acted as a safety net. I could confidently make changes without fearing regressions because the tests ensured everything still worked as intended.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pratical Example: Building a Custom Deck Validation DSL with TDD
&lt;/h3&gt;

&lt;p&gt;In one of my recent projects, I applied TDD to build a &lt;strong&gt;custom Hearthstone deck validation Domain Specific Language (DSL)&lt;/strong&gt;. The goal was to create a system that allows users to define complex deck-building rules in a human-readable format. First, &lt;a href="https://hsdeckvalidator.vercel.app/about" rel="noopener noreferrer"&gt;I designed how the language would look like&lt;/a&gt;, and what scenarios it should cover. This clarity in requirements, coupled with the system's complex logic, made it an ideal use case for TDD.&lt;/p&gt;

&lt;p&gt;The project had two core components that benefited greatly from a TDD approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;RuleValidator&lt;/strong&gt;: This component is responsible for validating a user’s input to ensure it follows the DSL’s syntax and semantics. It tokenizes the input, checks for errors in structure, and returns a list of validation errors with clear messages for the user. If the list is empty, it means the input is valid. The TDD approach ensured that all possible validation scenarios, including edge cases, were tested during implementation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mateuscechetto/custom-hs-deck-validator/blob/main/src/DSL/RuleValidator.spec.ts" rel="noopener noreferrer"&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mateuscechetto/custom-hs-deck-validator/blob/main/src/DSL/RuleValidator.ts" rel="noopener noreferrer"&gt;Implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;RuleGenerator&lt;/strong&gt;: Once an input is validated, the RuleGenerator transforms it into TypeScript code that defines the deck-building rules. It first invokes the RuleValidator to confirm that the input is correct. For valid input, it generates a function representing the rule, based on attributes, operators, modifiers, and values. This generated code is then used by the &lt;code&gt;DeckValidator&lt;/code&gt; to verify whether the cards in the deck follow the defined rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mateuscechetto/custom-hs-deck-validator/blob/main/src/DSL/RuleGenerator.spec.ts" rel="noopener noreferrer"&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mateuscechetto/custom-hs-deck-validator/blob/main/src/DSL/RuleGenerator.ts" rel="noopener noreferrer"&gt;Implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By writing tests first, I ensured that all scenarios designed for the DSL were covered, which guided the development process from start to finish. The tests acted as a checklist, helping me verify that each feature was implemented correctly and completely. This process also made development smoother—rather than relying on memory to track what still needed to be done, I simply ran the test suite and worked through any failing tests.&lt;/p&gt;

&lt;p&gt;The benefits of TDD became even more apparent when I refactored the code. For instance, I broke down larger functions into smaller, reusable ones, improving the overall design. Additionally, when I decided to add new modifiers (&amp;gt; and &amp;lt; for comparing values), I was confident that the existing functionality would remain intact because the tests served as a safety net, catching potential regressions.&lt;/p&gt;

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

&lt;p&gt;TDD is a valuable methodology when used in the right context. It excels when you have clear requirements, a high level of domain logic, and need a reliable way to prevent regressions over time. However, it can slow you down in exploratory phases or for trivial, boundary-heavy code. Knowing when to apply TDD and when to hold off is the key to getting the most out of it.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to Test Functions That Return Functions in TypeScript with Jest</title>
      <dc:creator>Mateus Cechetto</dc:creator>
      <pubDate>Sun, 15 Sep 2024 23:03:16 +0000</pubDate>
      <link>https://dev.to/mateuscechetto/how-to-test-functions-that-return-functions-in-typescript-with-jest-14og</link>
      <guid>https://dev.to/mateuscechetto/how-to-test-functions-that-return-functions-in-typescript-with-jest-14og</guid>
      <description>&lt;p&gt;In one of my recent projects, I had a function that, given an input, generates and returns a new function. While this is not an everyday occurrence, it's crucial to understand how to test such patterns effectively. In this article, we'll explore techniques for testing functions that return functions in TypeScript using Jest.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge of Function Equality
&lt;/h3&gt;

&lt;p&gt;Initially, I approached testing by comparing the generated function to an expected function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shoud return the expected function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;expected&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    expect(received).toEqual(expected) // deep equality

    Expected: [Function expected]
    Received: [Function anonymous]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The failure occurs because JavaScript functions are objects with unique identities. Even if two functions are structurally identical, they are not considered equal unless they reference the same object. Moreover, generated functions often create closures, capturing variables from their surrounding scope. These closed-over variables, or "lexical environments" add another layer of complexity to testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  First-Class Functions and Closures
&lt;/h3&gt;

&lt;p&gt;Before we dive deeper, let's review some core concepts. In JavaScript (and by extension, TypeScript), functions are considered first-class objects, meaning they can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be stored in variables or properties&lt;/li&gt;
&lt;li&gt;Be passed as arguments to other functions&lt;/li&gt;
&lt;li&gt;Be returned as the result of another function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows for powerful patterns like higher-order functions (functions that return other functions). When a function is generated inside another function, it often forms a closure, meaning the inner function has access to variables defined in its parent scope, even after the parent function has finished executing.&lt;/p&gt;

&lt;p&gt;For instance, in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&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;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "hello, world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function greet closes over the message variable, keeping it alive even after generator has returned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Different Testing Strategy
&lt;/h3&gt;

&lt;p&gt;To effectively test functions that return other functions, we must focus on the &lt;em&gt;output&lt;/em&gt; of the generated function rather than comparing the functions themselves. This approach ensures we're validating behavior, which is the true goal of testing.&lt;/p&gt;

&lt;p&gt;When testing a sum function, for instance, you check if the result is as expected: &lt;code&gt;expect(sum(1, 2)).toBe(3)&lt;/code&gt;. Similarly, when testing a generator function, we must evaluate the returned function's behavior by calling it with various inputs.&lt;/p&gt;

&lt;p&gt;Here's how to properly test a function generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should handle different messages and names&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;resulting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;resulting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;resulting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mateus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello, Mateus&lt;/span&gt;&lt;span class="dl"&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;resulting2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;resulting2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bye, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;resulting2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mateus&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bye, Mateus&lt;/span&gt;&lt;span class="dl"&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;By testing the output, we can ensure that the generator function works correctly for different inputs, providing the desired behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing More Advanced Scenarios: Closures
&lt;/h3&gt;

&lt;p&gt;Now, let's dive into some more advanced scenarios. When testing generator functions that form closures, you may want to validate that the closed-over variables are handled properly, and that the function behaves as expected even in edge cases.&lt;/p&gt;

&lt;p&gt;Consider this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;counter&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;Here, the generated function closes over the counter variable. Testing this pattern ensures that each invocation of the returned function correctly updates the counter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should increment the counter on each call&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;counterGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// First call, counter is incremented to 11&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Second call, counter is incremented to 12&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Third call, counter is incremented to 13&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 case, you're not just testing the output of a single call but also ensuring that the closure works properly by keeping the internal counter variable alive and updating it between function calls.&lt;/p&gt;

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

&lt;p&gt;Testing functions that return functions in TypeScript can seem tricky at first due to the nature of JavaScript's function objects and closures. However, by focusing on testing the behavior of the generated functions—rather than comparing them directly—you can effectively validate their correctness.&lt;/p&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions in JavaScript are first-class objects with unique identities, which complicates direct comparison.&lt;/li&gt;
&lt;li&gt;The solution is to test the output of generated functions by calling them with different inputs.&lt;/li&gt;
&lt;li&gt;For more complex cases, like closures, ensure that your tests validate how closed-over variables are handled over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these strategies, you'll be well-equipped to test function generators effectively in your projects.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>jest</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
