Replace enums by inheritance I have a class Call and 3 types of calls. Each type of call has a specific rate. So I have created an CallType enum and I will apply the right rate when making a call.

Here is my code so far:

public partial class Devices : Form
{
    public Devices()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var call = new Call(CallType.Regular);
        call.MakeCall();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        var call = new Call(CallType.Important);
        call.MakeCall();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        var call = new Call(CallType.Critical);
        call.MakeCall();
    }
}

public enum CallType
{
    None,
    Regular,
    Important,
    Critical
};

public class Call
{
    private CallType callType;
    const decimal regularRate = 0.25M;
    private decimal ratePerMinute;

    public Call(CallType callType)
    {
        this.callType = callType;
    }

    public void MakeCall()
    {
        switch (callType)
        {
            case CallType.Regular:
                ratePerMinute = regularRate;
                break;
            case CallType.Important:
                ratePerMinute = regularRate * 1.5M;
                break;
            case CallType.Critical:
                ratePerMinute = regularRate * 2.5M;
                break;
        }
    }
}


One of my colleague said that this code is bad: not loosely coupling and not scalable. He suggested to use inheritance instead.

How can I transform this code to respect loose coupling and scalabilty?
public void MakeCall()
{
    switch (callType)
    {
        case CallType.Regular:
            ratePerMinute = regularRate;
            break;
        case CallType.Important:
            ratePerMinute = regularRate * 1.5M;
            break;
        case CallType.Critical:
            ratePerMinute = regularRate * 2.5M;
            break;
    }
}



Seeing this method I would say the same. You cannot easily add new call-types and you cannot easily change their rate because they are all in the same switch. You have to open it every time. The Open-Closed-Priciple is violated. Even worse, the rate is not a part of the call-type but some magic number inside the switch.

What you can do is to create a class for each call-type. This means forget about the enum. Remove everything but the basic stuff from the Call and give it a protected constructor:

public abstract class Call
{
    protected Call(decimal rate) =&gt; Rate = rate;

    public decimal Rate { get;}

    public void MakeCall()
    {
        // do something...
    }
}


Use it to derive other calls (I did it for one of them);

public class RegularCall : Call
{
    private const decimal DeafultRate = 0.25m;

    public RegularCall() : base(DeafultRate ) {}
}


Alternatively you can make the property abstract and return the value here instead of passing it via the constructor:

public class RegularCall : Call
{
    public override decimal Rate =&gt; 0.25m;
}


And use some other service to create an instance of a call and do some other stuff:

public class Caller
{
    public static void MakeCall&lt;TCall&gt;() where TCall : Call, new
    {
        var call = new TCall();
        call.MakeCall();
    }
}


Each button would the just do this:

private void button1_Click(object sender, EventArgs e)
{
    Caller.MakeCall&lt;RegularCall&gt;();
}


Now you can add as many calls as you like without modifying anything.