jeudi 22 avril 2021

Avoid if and switch statement and more generic approach

I want to avoid the use of "if" and "switch" statements which deal with specific cases and instead taking a more generic approach.

Requirement: Based on a number of requirements which are detailed below, the status of an Order may be determined to be "Confirmed", "Closed" or "AuthorisationRequired".

Inputs:

IsRushOrder: bool
OrderType: Enum (Repair, Hire)
IsNewCustomer: bool
IsLargeOrder: bool

Outputs:

OrderStatus: Enum (Confirmed, Closed, AuthorisationRequired)

Requirements (Applied in priority order from top to bottom):

-Large repair orders for new customers should be closed
-Large rush hire orders should always be closed
-Large repair orders always require authorisation
-All rush orders for new customers always require authorisation
-All other orders should be confirmed

==========================================================================================

One way i could think of implementing withoud using IF is by populating OrderStatus in collection and querying using LINQ This implementaion will get complicated quickly as we add more statuses.

public class OrderStatusAnalyzer
{
    protected static List<OrderStatus> OrderStatuses;

    public OrderStatusAnalyzer()
    {
        OrderStatuses = OrderStatusCollection.Get();
    }

    public string GetOrderStatusTypeByOrderInput(OrderInput orderInput)
    {
        var orderStatusTypes = from orderStatus in OrderStatuses
                               where orderStatus.IsNewCustomer == orderInput.IsNewCustomer
                                     && orderStatus.IsLargeOrder == orderInput.IsLargeOrder
                                     && orderStatus.IsRushOrder == orderInput.IsRushOrder
                                     && orderStatus.OrderType == orderInput.OrderType
                               orderby orderStatus.Priority ascending
                               select orderStatus.OrderStatusType;

        var statusTypesList = orderStatusTypes.ToList();
        var orderStatusType = !statusTypesList.Any() ? "VehicleRepairOrder.Order.AllOtherOrders" : statusTypesList[0];

        return orderStatusType;
    }
}
public static class OrderStatusCollection
{
    public static List<OrderStatus> Get()
    {
        // Note:
        // 1) If we have to avoid referencing null, then we can populate the data with probabilities. Populating data with probabilities will become hard Maintain as we add more status   
        // 2) this is also violating O(Open for extension and closed for modification) of SOLID principle 
        // 3) instead of passing null, if you pass actual unit test will fail
        var orderStatuses = new List<OrderStatus>
        {
            new OrderStatus
            {
                IsLargeOrder = true, IsNewCustomer = true, OrderType = OrderTypeEnum.Repair,
                IsRushOrder = null,
                Priority = 1, OrderStatusType = "VehicleRepairOrder.Order.LargeRepairNewCustomerOrder"
            },

            new OrderStatus
            {
                IsLargeOrder = true, IsNewCustomer = null, OrderType = OrderTypeEnum.Hire, IsRushOrder = true,
                Priority = 2, OrderStatusType = "VehicleRepairOrder.Order.LargeRushHireOrder"
            },

            new OrderStatus
            {
                IsLargeOrder = true, IsNewCustomer = null, OrderType = OrderTypeEnum.Repair,
                IsRushOrder = null,
                Priority = 3, OrderStatusType = "VehicleRepairOrder.Order.LargeRepairOrder"
            },

            new OrderStatus
            {
                IsLargeOrder = null, IsNewCustomer = true, OrderType = OrderTypeEnum.Any, IsRushOrder = true,
                Priority = 4, OrderStatusType = "VehicleRepairOrder.Order.AllRushNewCustomerOrder"
            },

        };

        return orderStatuses;
    }
}

Aucun commentaire:

Enregistrer un commentaire