برچسب: Avoid

  • define Using Aliases to avoid ambiguity | Code4IT

    define Using Aliases to avoid ambiguity | Code4IT


    Sometimes we need to use objects with the same name but from different namespaces. How to remove that ambiguity? By Using Aliases!

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    You may have to reference classes or services that come from different namespaces or packages, but that have the same name. It may become tricky to understand which reference refers to a specific type.

    Yes, you could use the fully qualified name of the class. Or, you could use namespace aliases to write cleaner and easier-to-understand code.

    It’s just a matter of modifying your using statements. Let’s see how!

    The general approach

    Say that you are working on an application that receives info about football matches from different sources using NuGet packages, and then manipulates the data to follow some business rules.

    Both services, ShinyData and JuanStatistics (totally random names!), provide an object called Match. Of course, those objects live in their specific namespaces.

    Since you are using the native implementation you cannot rename the classes to avoid ambiguity. So you’ll end up with code like this:

    void Main()
    {
        var shinyMatch = new ShinyData.Football.Statistics.Match();
        var juanMatch = new JuanStatistics.Stats.Football.Objects.Match();
    }
    

    Writing the fully qualified namespace every time can easily become boring. The code becomes less readable too!

    Luckily we have 2 solutions. Or, better, a solution that we can apply in two different ways.

    Namespace aliases – a cleaner solution

    The following solution will not work:

    using ShinyData.Football.Statistics;
    using JuanStatistics.Stats.Football.Objects;
    
    void Main()
    {
        var shinyMatch = new Match();
        var juanMatch = new Match();
    }
    

    because, of course, the compiler is not able to understand the exact type of shinyMatch and juanMatch.

    But we can use a nice functionality of C#: namespace aliases. It simply means that we can name an imported namespace and use the alias to reference the related classes.

    Using alias for the whole namespace

    using Shiny = ShinyData.Football.Statistics;
    using Juan = JuanStatistics.Stats.Football.Objects;
    
    void Main()
    {
        var shinyMatch = new Shiny.Match();
        var juanMatch = new Juan.Match();
    }
    

    This simple trick boosts the readability of your code.

    Using alias for a specific class

    Can we go another step further? Yes! We can even specify aliases for a specific class!

    using ShinyMatch = ShinyData.Football.Statistics.Match;
    using JuanMatch = JuanStatistics.Stats.Football.Objects.Match;
    
    void Main()
    {
        var shinyMatch = new ShinyMatch();
        var juanMatch = new JuanMatch();
    }
    

    Now we can create an instance of ShinyMatch which, since it is an alias listed among the using statements, is of type ShinyData.Football.Statistics.Match.

    Define alias for generics

    Not only you can use it to specify a simple class, but only for generics.

    Say that the ShinyData namespace defines a generic class, like CustomDictionary<T>. You can reference it just as you did before!

    using ShinyMatch = ShinyData.Football.Statistics.Match;
    using JuanMatch = JuanStatistics.Stats.Football.Objects.Match;
    using ShinyDictionary = ShinyData.Football.Statistics.CustomDictionary<int>;
    
    void Main()
    {
        var shinyMatch = new ShinyMatch();
        var juanMatch = new JuanMatch();
    
        var dictionary = new ShinyDictionary();
    }
    

    Unluckily we have some limitations:

    • we must always specify the inner type of the generic: CustomDictionary<int> is valid, but CustomDictionary<T> is not valid
    • we cannot use as inner type a class defined with an alias: CustomDictionary<ShinyMatch> is invalid, unless we use the fully qualified name

    Conclusion

    We’ve seen how we can define namespace aliases to simplify our C# code: just add a name to an imported namespace in the using statement, and reference it on your code.

    What would you reference, the namespace or the specific class?

    👉 Let’s discuss it on Twitter or on the comment section below.

    🐧





    Source link

  • Use a SortedSet to avoid duplicates and sort items &vert; Code4IT

    Use a SortedSet to avoid duplicates and sort items | Code4IT


    Using the right data structure is crucial to building robust and efficient applications. So, why use a List or a HashSet to sort items (and remove duplicates) when you have a SortedSet?

    Table of Contents

    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    As you probably know, you can create collections of items without duplicates by using a HashSet<T> object.

    It is quite useful to remove duplicates from a list of items of the same type.

    How can we ensure that we always have sorted items? The answer is simple: SortedSet<T>!

    HashSet: a collection without duplicates

    A simple HashSet creates a collection of unordered items without duplicates.

    This example

    var hashSet = new HashSet<string>();
    hashSet.Add("Turin");
    hashSet.Add("Naples");
    hashSet.Add("Rome");
    hashSet.Add("Bari");
    hashSet.Add("Rome");
    hashSet.Add("Turin");
    
    
    var resultHashSet = string.Join(',', hashSet);
    Console.WriteLine(resultHashSet);
    

    prints this string: Turin,Naples,Rome,Bari. The order of the inserted items is maintained.

    SortedSet: a sorted collection without duplicates

    To sort those items, we have two approaches.

    You can simply sort the collection once you’ve finished adding items:

    var hashSet = new HashSet<string>();
    hashSet.Add("Turin");
    hashSet.Add("Naples");
    hashSet.Add("Rome");
    hashSet.Add("Bari");
    hashSet.Add("Rome");
    hashSet.Add("Turin");
    
    var items = hashSet.ToList<string>().OrderBy(s => s);
    
    
    var resultHashSet = string.Join(',', items);
    Console.WriteLine(resultHashSet);
    

    Or, even better, use the right data structure: a SortedSet<T>

    var sortedSet = new SortedSet<string>();
    
    sortedSet.Add("Turin");
    sortedSet.Add("Naples");
    sortedSet.Add("Rome");
    sortedSet.Add("Bari");
    sortedSet.Add("Rome");
    sortedSet.Add("Turin");
    
    
    var resultSortedSet = string.Join(',', sortedSet);
    Console.WriteLine(resultSortedSet);
    

    Both results print Bari,Naples,Rome,Turin. But the second approach does not require you to sort a whole list: it is more efficient, both talking about time and memory.

    Use custom sorting rules

    What if we wanted to use a SortedSet with a custom object, like User?

    public class User {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        public User(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }
    

    Of course, we can do that:

    var set = new SortedSet<User>();
    
    set.Add(new User("Davide", "Bellone"));
    set.Add(new User("Scott", "Hanselman"));
    set.Add(new User("Safia", "Abdalla"));
    set.Add(new User("David", "Fowler"));
    set.Add(new User("Maria", "Naggaga"));
    set.Add(new User("Davide", "Bellone"));//DUPLICATE!
    
    foreach (var user in set)
    {
        Console.WriteLine($"{user.LastName} {user.FirstName}");
    }
    

    But, we will get an error: our class doesn’t know how to compare things!

    That’s why we must update our User class so that it implements the IComparable interface:

    public class User : IComparable
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
        public User(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    
        public int CompareTo(object obj)
        {
            var other = (User)obj;
            var lastNameComparison = LastName.CompareTo(other.LastName);
    
            return (lastNameComparison != 0)
                ? lastNameComparison :
                (FirstName.CompareTo(other.FirstName));
        }
    }
    

    In this way, everything works as expected:

    Abdalla Safia
    Bellone Davide
    Fowler David
    Hanselman Scott
    Naggaga Maria
    

    Notice that the second Davide Bellone has disappeared since it was a duplicate.

    This article first appeared on Code4IT

    Wrapping up

    Choosing the right data type is crucial for building robust and performant applications.

    In this article, we’ve used a SortedSet to insert items in a collection and expect them to be sorted and without duplicates.

    I’ve never used it in a project. So, how did I know that? I just explored the libraries I was using!

    From time to time, spend some minutes reading the documentation, have a glimpse of the most common libraries, and so on: you’ll find lots of stuff that you’ve never thought existed!

    Toy with your code! Explore it. Be curious.

    And have fun!

    🐧



    Source link

  • Avoid mental mappings &vert; Code4IT

    Avoid mental mappings | Code4IT


    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Every name must be meaningful and clear. If names are not obvious, other developers (or your future self) may misinterpret what you were meaning.

    Avoid using mental mapping to abbreviate names, unless the abbreviation is obvious or common.

    Names should not be based on mental mapping, even worse without context.

    Bad mental mappings

    Take this bad example:

    public void RenderWOSpace()
    

    What is a WOSpace? Without context, readers won’t understand its meaning. Ok, some people use WO as an abbreviation of without.

    So, a better name is, of course:

    public void RenderWithoutSpace()
    

    Acceptable mappings

    Some abbreviations are quite obvious and are totally fine to be used.

    For instance, standard abbreviations, like km for kilometer.

    public int DistanceInKm()
    

    or variables used, for instance, in a loop:

    for (int i = 0; i <; 100; i++){}
    

    or in lambdas:

    int[] collection = new int[] { 2, 3, 5, 8 };
    collection.Where(c => c < 5);
    

    It all depends on the scope: the narrower the scope, the meaningless (don’t get me wrong!) can be the variable.

    An edge case

    Sometimes, a common (almost obvious) abbreviation can have multiple meanings. What does DB mean? Database? Decibel? It all depends on the context!

    So, a _dbConnection obviously refers to the database. But a defaultDb, is the default decibel value or the default database?

    This article first appeared on Code4IT

    Conclusion

    As usual, clarity is the key for good code: a name, may it be for classes, modules, or variables, should be explicit and obvious to everyone.

    So, always use meaningful names!

    Happy coding!

    🐧



    Source link

  • Avoid using too many Imports in your classes &vert; Code4IT

    Avoid using too many Imports in your classes | Code4IT


    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Actually, this article is not about a tip to write cleaner code, but it is an article that aims at pointing out a code smell.

    Of course, once you find this code smell in your code, you can act in order to eliminate it, and, as a consequence, you will end up with cleaner code.

    The code smell is easy to identify: open your classes and have a look at the imports list (in C#, the using on top of the file).

    A real example of too many imports

    Here’s a real-life example (I censored the names, of course):

    using MyCompany.CMS.Data;
    using MyCompany.CMS.Modules;
    using MyCompany.CMS.Rendering;
    using MyCompany.Witch.Distribution;
    using MyCompany.Witch.Distribution.Elements;
    using MyCompany.Witch.Distribution.Entities;
    using Microsoft.Extensions.Logging;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;
    using MyProject.Controllers.VideoPlayer.v1.DataSource;
    using MyProject.Controllers.VideoPlayer.v1.Vod;
    using MyProject.Core;
    using MyProject.Helpers.Common;
    using MyProject.Helpers.DataExplorer;
    using MyProject.Helpers.Entities;
    using MyProject.Helpers.Extensions;
    using MyProject.Helpers.Metadata;
    using MyProject.Helpers.Roofline;
    using MyProject.ModelsEntities;
    using MyProject.Models.ViewEntities.Tags;
    using MyProject.Modules.EditorialDetail.Core;
    using MyProject.Modules.VideoPlayer.Models;
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    
    namespace MyProject.Modules.Video
    

    Sounds familiar?

    If we exclude the imports necessary to use some C# functionalities

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    

    We have lots of dependencies on external modules.

    This means that if something changes in one of the classes that are part of those namespaces, we may end up with code that is difficult to update.

    Class dependencies

    Also, guess what comes with all those imports? Constructor with too many parameters (and, in fact, in this class, I have 11 dependencies injected in the constructor) and code that is too long and difficult to understand (and, in fact, this class has 500+ lines).

    A solution? Refactor your project in order to minimize scattering those dependencies.

    Wrapping up

    Having all those imports (in C# we use the keyword using) is a good indicator that your code does too many things. You should focus on minimizing those imports without cheating (like using global imports).

    Happy coding!

    🐧



    Source link

  • Avoid subtle duplication of code and logic &vert; Code4IT

    Avoid subtle duplication of code and logic | Code4IT


    Just a second! 🫷
    If you are here, it means that you are a software developer.
    So, you know that storage, networking, and domain management have a cost .

    If you want to support this blog, please ensure that you have disabled the adblocker for this site.
    I configured Google AdSense to show as few ADS as possible – I don’t want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.

    Thank you for your understanding.
    Davide

    Duplication is not only about lines of code, but also about data usage and meaning.
    Reducing it will help us minimize the impact of every change.

    Take this class as an example:

    class BookShelf
    {
        private Book[] myBooks = new Book[]
        {
             new Book(1, "C# in depth"),
             new Book(2, "I promessi paperi")
        };
    
        public int Count() => myBooks.Length;
        public bool IsEmpty() => myBooks.Length == 0;
        public bool HasElements() => myBooks.Length > 0;
    }
    

    Here, both Count and IsEmpty use the same logical way to check the length of the collection: by calling myBooks.Length.

    What happens if you have to change the myBooks collection and replace the array of Books with a collection that does not expose the Length property? You will have to replace the logic everywhere!

    So, a better approach is to “centralize” the way to count the items in the collection in this way:

    class BookShelf
    {
        private Book[] myBooks = new Book[]
        {
             new Book(1, "C# in depth"),
             new Book(2, "I promessi paperi")
        };
    
        public int Count() => myBooks.Length;
        public bool IsEmpty() => Count() == 0;
        public bool HasElements() => Count() > 0;
    }
    

    If you will need to replace the myBooks data type, you will simply have to update the Count method – everything else will be the same.

    Also, HasElements and IsEmpty are a logical duplication. If they’re not necessary, you should remove one. Remove the one most used in its negative form: if you find lots of if(!HasElements()), you should consider replacing it with if(IsEmpty()): always prefer the positive form!

    Yes, I know, this is an extreme example: it’s too simple. But think of a more complex class or data flow in which you reuse the same logical flow, even if you’re not really using the exact same lines of code.

    By duplicating the logic, you will need to write more tests that do the same thing. Also, it may happen that if you found a flaw in your logic, and you fix it in some places and forget to fix it in other methods.

    Centralizing it will allow you to build safer code that is easier to test and update.

    A simple way to avoid “logical” duplication? Abstract classes!

    Well, there are many others… that I expect you to tell me in the comments section!

    Happy coding!

    🐧



    Source link