locked
Best practice when designing a class RRS feed

  • Question

  • User372430298 posted

    Hi,

    I am just trying to understand the best practice when designing a C# class.

    Let's say I have been told by my manager to design a reusable class to calculate discount of an item. Currently the discount rate is 15%.

    Below I have shown three ways the class could be designed and all three are working as expected. So which class is the best in terms of best design perspective?

        class CalculateDicount
        {
            private const decimal discountRate = 0.15M;
    
            public decimal Calculate(decimal valueOFTheItem)
            {
                valueOFTheItem = valueOFTheItem - (valueOFTheItem * discountRate);
                return valueOFTheItem;
            }
        }
    
        class CalculateDicount2
        {
            private const decimal discountRate = 0.15M;
            private decimal itemValue;
    
            public decimal Calculate(decimal valueOFTheItem)
            {
                itemValue = valueOFTheItem - (valueOFTheItem * discountRate);
                return itemValue;
            }
        }
    
        class CalculateDicount3
        {
            private const decimal discountRate = 0.15M;
            public decimal ItemValue { get; set; }
    
            public decimal Calculate()
            {
                ItemValue = ItemValue - (ItemValue * discountRate);
                return ItemValue;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                CalculateDicount c = new CalculateDicount();
                CalculateDicount2 c2 = new CalculateDicount2();
                CalculateDicount3 c3 = new CalculateDicount3();
                decimal price = c.Calculate(10);
                decimal price2 = c2.Calculate(100);
                c3.ItemValue = 50;
                decimal price3 = c3.Calculate();
                Console.WriteLine("Value of the Item after discount - " + price);
                Console.WriteLine("Value of the 2ndItem after discount - " + price2);
                Console.WriteLine("Value of the 3rdItem after discount - " + price3);
                Console.ReadLine();
            }
        }
    
    //Output
    //Value of the Item after discount - 8.50
    //Value of the 2ndItem after discount - 85.00
    //Value of the 3rdItem after discount - 42.50



    Friday, August 4, 2017 4:48 PM

Answers

  • User475983607 posted

    Avoid using hardcoded values in a class.  It is better to pass values into a class or store values in configuration as shown below.  This makes the class more versatile. 

    using System;
    using System.Configuration;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Globalization;
    
    namespace ConsoleDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                decimal value = 10.00m;
                CalculateDicount4 c1 = new CalculateDicount4();
                CalculateDicount4 c2 = new CalculateDicount4(-0.15m);
                CalculateDicount4 c3 = new CalculateDicount4(0.50m);
    
                Console.WriteLine(c1.Calculate(value));
                Console.WriteLine(c2.Calculate(value));
                Console.WriteLine(c3.Calculate(value));
    
            }
    
        }
    
        class CalculateDicount4
        {
            private decimal discountRate;
    
            //Get the discount from the config
            public CalculateDicount4()
            {
                decimal temp = 0.0m;
                if (decimal.TryParse(ConfigurationManager.AppSettings["discountRate"], out temp))
                {
                    discountRate = temp;
                }
                else
                {
                    throw new ArgumentException("Oops, the appConfig's discountRate is missing or it is not a decimal.");
                }
            }
    
            //Let the user set the rate
            public CalculateDicount4(decimal rate)
            {
                discountRate = rate;
            }
    
            public decimal Calculate(decimal valueOFTheItem)
            {
                valueOFTheItem = valueOFTheItem + (valueOFTheItem * discountRate);
                return valueOFTheItem;
            }
        }
    
    }
    
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
        </startup>
      <appSettings>
        <add key="discountRate" value="-0.25"/>
      </appSettings>
    </configuration>
    



    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, August 4, 2017 5:28 PM

All replies

  • User475983607 posted

    Avoid using hardcoded values in a class.  It is better to pass values into a class or store values in configuration as shown below.  This makes the class more versatile. 

    using System;
    using System.Configuration;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Globalization;
    
    namespace ConsoleDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                decimal value = 10.00m;
                CalculateDicount4 c1 = new CalculateDicount4();
                CalculateDicount4 c2 = new CalculateDicount4(-0.15m);
                CalculateDicount4 c3 = new CalculateDicount4(0.50m);
    
                Console.WriteLine(c1.Calculate(value));
                Console.WriteLine(c2.Calculate(value));
                Console.WriteLine(c3.Calculate(value));
    
            }
    
        }
    
        class CalculateDicount4
        {
            private decimal discountRate;
    
            //Get the discount from the config
            public CalculateDicount4()
            {
                decimal temp = 0.0m;
                if (decimal.TryParse(ConfigurationManager.AppSettings["discountRate"], out temp))
                {
                    discountRate = temp;
                }
                else
                {
                    throw new ArgumentException("Oops, the appConfig's discountRate is missing or it is not a decimal.");
                }
            }
    
            //Let the user set the rate
            public CalculateDicount4(decimal rate)
            {
                discountRate = rate;
            }
    
            public decimal Calculate(decimal valueOFTheItem)
            {
                valueOFTheItem = valueOFTheItem + (valueOFTheItem * discountRate);
                return valueOFTheItem;
            }
        }
    
    }
    
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
        </startup>
      <appSettings>
        <add key="discountRate" value="-0.25"/>
      </appSettings>
    </configuration>
    



    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, August 4, 2017 5:28 PM
  • User372430298 posted

    Thanks

    Friday, August 4, 2017 11:39 PM
  • User1771544211 posted

    Hi Akbar123,

    I prefer to set the class as a static class.

        static class CalculateDicount
        {
            ...        
        }
    

    Here is a link which talks about static class, please take it as reference.

    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members

    Best Regards,

    Jean

    Monday, August 7, 2017 2:09 AM