none
Using regions are evil !! Is it so ?? RRS feed

  • General discussion

  • I have used regions so far in my codes  wherever it is possible and i used to suggest my team during my reviews to use regions and i say which is clean and readable. But i got surprised when one of my senior advised to not use regions and shared this blog at me. 

    https://marcduerst.com/2016/10/03/c-regions-are-evil/

    Is it really a bad practice ?


    SomaSundaram R

    • Changed type CoolDadTxModerator Thursday, April 11, 2019 2:25 PM This is a discussion more than a technical question
    Thursday, April 11, 2019 6:12 AM

All replies

  • I can't go with what is in the link. I use regions all the time when needed to segregate code functionality within a class,  like in the class example.

    I don't use regions haphazardly, and I only use them when needed to give clarity 

    using System;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using Entities;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    namespace ProgMgmntCore2UserIdentity.WebApi
    {
        public class WebApi : IWebApi
        {
            #region ProjectApi
            
            public List<DtoProject> GetProjsByUserIdApi(string userid)
            {
                var dtoprojects = new List<DtoProject>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjsByUserId?userid=" + userid);
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic projects = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in projects)
                    {
                        DtoProject dto = obj.ToObject<DtoProject>();
    
                        dtoprojects.Add(dto);
                    }
                }
    
                return dtoprojects;
            }
    
            public DtoProject GetProjByIdApi(int id)
            {
                DtoProject dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/project/GetProjById?id=" + id);
                    HttpResponseMessage getResponseMessage = client.GetAsync(uri).Result;
    
                    if (!getResponseMessage.IsSuccessStatusCode)
                        throw new Exception(getResponseMessage.ToString());
    
                    var responsemessage = getResponseMessage.Content.ReadAsStringAsync().Result;
    
                    dynamic project = JsonConvert.DeserializeObject(responsemessage);
    
                    dto = project.ToObject<DtoProject>();
                }
    
                return dto;
            }
    
            public void CreateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/CreateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void UpdateProjectApi(DtoProject dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/UpdateProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void DeleteProjectApi(DtoId dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("api/project/DeleteProject", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            #endregion
    
            #region TaskApi
    
            public List<DtoTask> GetTasksByProjIdApi(int id)
            {
                var dtotasks = new List<DtoTask>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/task/GetTasksByProjId?id=" + id);
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic tasks = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in tasks)
                    {
                        DtoTask dto = obj.ToObject<DtoTask>();
    
                        dtotasks.Add(dto);
                    }
                }
    
                return dtotasks;
            }
    
            public DtoTask GetTaskByIdApi(int id)
            {
                DtoTask dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/task/GetTaskById?id=" + id);
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic task = JObject.Parse(responseString);
                    
                    dto = task.ToObject<DtoTask>();
                }
    
                return dto;
            }
    
            public void CreateTaskApi(DtoTask dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message = client.PostAsync("api/task/CreateTask", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void UpdateTaskApi(DtoTask dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message = client.PostAsync("api/task/UpdateTask", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void DeleteTaskApi(DtoId dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://progmgmntcore2api.com") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message = client.PostAsync("api/task/DeleteTask", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            #endregion
    
            #region CacheApi
    
            public DtoCache GetCacheApi()
            {
                var dtocache = new DtoCache();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://progmgmntcore2api.com/api/cache");
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    var deserialized = JsonConvert.DeserializeObject<DtoCacheRoot>(responseString);
    
                    dtocache.ProjectTypes = deserialized.DtoCache.ProjectTypes;
                    dtocache.Durations = deserialized.DtoCache.Durations;
                    dtocache.Statuses = deserialized.DtoCache.Statuses;
                    dtocache.Resources = deserialized.DtoCache.Resources;
                }
    
                return dtocache;
            }
    
            #endregion
        }
    }
    
    

      
    Thursday, April 11, 2019 6:46 AM
  • I think it is better not to use them but they are not evil.  It is better and easier unit test smaller classes that just do one thing.
    Thursday, April 11, 2019 10:01 AM
  • I think it is better not to use them but they are not evil.  It is better and easier unit test smaller classes that just do one thing.

    I have to disagree with the unit testing thing, particularly if one is using Domain Driven Design. There is nothing wrong in using small classes, but there is nothing wrong with  classes that have business behavior that is segregated in the class that uses Interface implementation where the class is unit testable via the implemented Interface. 

    The Inventory Domain object can have multiple functionality behavior concerning inventory. The same could be true for the PuruchaseOrder Domain object or the Sales Domain object, etc. and etc. These objects can also communicate with each other as well. 

    Thursday, April 11, 2019 11:54 AM
  • No matter the case one can always use the following shortcut keys to expand or collapse all regions at once. 

    Ctrl-M, Ctrl-O will collapse all of the code to its definitions.
    Ctrl-M, Ctrl-L will expand all of the code (actually, this one toggles it).
    Ctrl-M, Ctrl-M will expand or collapse a single region


    So if the project has regions that are collapsed hit CTRL-M, CTRL-L 

    Personally this will vary from team to team along with the complexity of a Visual Studio solution.

    Let's say a developer becomes part of a team where the Visual Studio solution is very large, is new to them and has regions. If the class names were named properly the first thing here is that you can now figure out which class they need to be in, expand the class in Solution Explorer to examine the class e.g.

    Then from there can determine were they need to be. On the other hand if names of classes, methods and properties are poorly named with regions this is not wise unless the region names are well named to be descriptive.



    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Thursday, April 11, 2019 1:33 PM
    Moderator
  • It is completely and utterly a style thing. The blogger is posting their opinion on why using regions is evil but you can apply this same logic to pretty much anything. For example "functions are evil".

    1) Creating many small functions that do one and only one thing (which is exactly how functions are supposed to work) means you will have lots of functions.

    2) The more functions you have the more a developer has to jump around to see what each does and therefore the harder it is to read the code since it doesn't flow nicely down the page.

    3) Since you can have lots of functions you cannot easily see that your code is too large for a single type (because each function is a couple lines of code but put together there are 1000s of lines).

    Honestly I thought coding style questions like this died out years ago. If your team is arguing about coding style (beyond the simple consistency stuff) then you are going about development all wrong.

    1) Modern IDEs do not require that you scroll through code to find anything. Click and jump is all you need.

    2) There are many code metrics tools that will (far more accurately) tell you whether your code is too complex and they are based upon actual complexity and not lines of code. LOC complexity is an old school concept. There is nothing fundamentally different between these 2 lines of code and the complexity is the same, unless you're counting lines of code.

    //1 line of code
    var result = employees.Where(x => x.Name == "Bob").Take(10);
    
    //3 lines of code
    var result = (from e in employees
                  where e.Name == "Bob"
                  select e).Take(10);
    3) If a developer cannot get past comment styles, tab vs whitespace, region usage, etc. then they are not yet at the point they should probably be writing production code. These things are pointless to argue over as they don't change anything meaningful in terms of behavior or performance. Again, excluding consistency in a file for ease of reading.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, April 11, 2019 2:06 PM
    Moderator