Есть ли способ минимизировать условие if и if-else - PullRequest
2 голосов
/ 02 мая 2019

Я написал код, который работает нормально, но я использую слишком много условий If и else-if. Есть ли способ минимизировать это? На основе целочисленных значений значения shippingStatus, invoiceStatus и paymentStatus должны измениться.

    int qtyOrdered = dynamic integer values;
    int qtyShipped = dynamic integer value;
    int qtyReturned = dynamic integer values;
    int qtyInvoiced = dynamic integer values;

        OrderShippingStatus shippingStatus = shippingStatus(qtyOrdered,qtyShipped,qtyReturned);
        OrderInvoicingStatus invoiceStatus = invoiceStatus(qtyOrdered,qtyInvoiced,qtyReturned);
        OrderPaymentStatus paymentStatus =paymentStatus(salesOrder.getAmountPaid(),totalAmountAfterEvent);

private OrderPaymentStatus paymentStatus(BigDecimal amountPaid, BigDecimal totalAmountAfterEvent) {
        if (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, amountPaid)) {
            return OrderPaymentStatus.FULLY_PAID;
        } else if (MathUtils.areEqual(totalAmountAfterEvent, BigDecimal.ZERO)) {
            return OrderPaymentStatus.NOT_APPLICABLE;
        } else if (MathUtils.isFirstLessThanSecond(amountPaid, totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(amountPaid, totalAmountAfterEvent))) {
            return OrderPaymentStatus.PARTIALLY_PAID;
        } else if (MathUtils.isFirstLessThanSecond(amountPaid, totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, amountPaid) || (MathUtils.areEqual(totalAmountAfterEvent, amountPaid)))) {
            return OrderPaymentStatus.PARTIALLY_PAID;
        } else {
            return salesOrder.getPaymentStatus();
        }
    }

    private OrderInvoicingStatus invoiceStatus(int qtyOrdered, int qtyInvoiced, int qtyReturned) {
        if (qtyOrdered == qtyInvoiced && qtyInvoiced > qtyReturned) {
            return OrderInvoicingStatus.FULLY_INVOICED;
        } else if (qtyOrdered == qtyInvoiced && qtyInvoiced == qtyReturned) {
            return OrderInvoicingStatus.NOT_APPLICABLE;
        } else if (qtyOrdered > qtyInvoiced && qtyInvoiced > qtyReturned) {
            return OrderInvoicingStatus.PARTIALLY_INVOICED;
        } else if (qtyOrdered > qtyInvoiced && qtyInvoiced == qtyReturned) {
            return OrderInvoicingStatus.NOT_INVOICED;
        } else {
            return salesOrder.getInvoiceStatus();
        }
    }

    private OrderShippingStatus shippingStatus(int qtyOrdered, int qtyShipped, int qtyReturned) {
        if (qtyOrdered == qtyShipped && qtyShipped >= qtyReturned) {
            return OrderShippingStatus.FULLY_SHIPPED;
        } else if (qtyOrdered > qtyShipped && qtyShipped > qtyReturned) {
            return OrderShippingStatus.PARTIALLY_SHIPPED;
        } else if (qtyOrdered > qtyShipped && qtyShipped == qtyReturned) {
            return OrderShippingStatus.NOT_SHIPPED;
        } else {
            return salesOrder.getShippingStatus();
        }
    }

Ответы [ 2 ]

2 голосов
/ 02 мая 2019

Если вы любите java 8 и лямбда-выражения, вы можете сделать:

1.Использовать существующий Functional Interface или определить новый, соответствующий вашим требованиям

@FunctionalInterface
public interface TriPredicate<A, B, C> {

    boolean test(A a, B b, C c);

}

2. Создайте перечисление, содержащее условие.Реализуйте метод, который возвращает элемент, который соответствует предикату enum

import java.util.Arrays;
import java.util.Optional;

public enum ShiStatus {
    FULLY_SHIPPED((qtyOrdered, qtyShipped, qtyReturned) -> qtyOrdered.equals(qtyShipped) && qtyShipped >= qtyReturned),
    PARTIALLY_SHIPPED((qtyOrdered, qtyShipped, qtyReturned) -> qtyOrdered > qtyShipped && qtyShipped > qtyReturned),
    NOT_SHIPPED((qtyOrdered, qtyShipped, qtyReturned) -> qtyShipped != 0.0 && qtyShipped.equals(qtyReturned));

    private TriPredicate<Double, Double, Double> predicate;

    ShiStatus(TriPredicate<Double, Double, Double> predicate) {
        this.predicate = predicate;
    }

    public TriPredicate<Double, Double, Double> getPredicate() {
        return predicate;
    }

    public static Optional<ShiStatus> getStatus(Double qtyOrdered, Double qtyShipped, Double qtyReturned) {
        return Arrays.stream(ShiStatus.values())
                .filter(shiStatus -> shiStatus.getPredicate().test(qtyOrdered, qtyShipped, qtyReturned))
                .findFirst();
    }

}

3. Используйте метод enum для получения базы состояния на условии enum

    @Test
    public void testEnum() {
        ShiStatus shippingStatus = ShiStatus.NOT_SHIPPED; // salesOrder.getShippingStatus()

        Assert.assertEquals(ShiStatus.PARTIALLY_SHIPPED, ShiStatus.getStatus(3D, 2D, 1D).orElse(shippingStatus));
        Assert.assertEquals(ShiStatus.NOT_SHIPPED, ShiStatus.getStatus(1D, 2D, 3D).orElse(shippingStatus));
    }
1 голос
/ 02 мая 2019

Как уже упоминалось в комментариях @Mark Jeronimus, вы можете использовать три отдельных метода, чтобы сделать его более читабельным.Поскольку вы сравниваете разные аспекты, функция switch () не имеет такого большого смысла.Также вы можете использовать больше пробелов ... Мое предложение:

Сделать эту функцию:

if (qtyOrdered == qtyShipped && qtyShipped >= qtyReturned) {
    shippingStatus = ShiStatus.FULLY_SHIPPED;
} 
else if (qtyOrdered > qtyShipped && qtyShipped > qtyReturned) {
    shippingStatus = ShiStatus.PARTIALLY_SHIPPED;
} 
else if (qtyOrdered > qtyShipped && qtyShipped == qtyReturned) {
    shippingStatus = ShiStatus.NOT_SHIPPED;
} 
else {
    shippingStatus = salesOrder.getShippingStatus();
}

Сделать эту функцию второй:

if (qtyOrdered == qtyInvoiced && qtyInvoiced > qtyReturned) {
    invoiceStatus = ShiStatus.FULLY_INVOICED;
} 
else if (qtyOrdered == qtyInvoiced && qtyInvoiced == qtyReturned) {
    invoiceStatus = InvStatus .NOT_APPLICABLE;
} 
else if (qtyOrdered > qtyInvoiced && qtyShipped > qtyReturned) {
    invoiceStatus = InvStatus .PARTIALLY_INVOICED;
} 
else if (qtyOrdered > qtyInvoiced && qtyShipped == qtyReturned) {
    invoiceStatus = ShiStatus.NOT_INVOICED;
} 
else {
    invoiceStatus = salesOrder.getInvoiceStatus();
}

Сделать этоваша третья функция:

if (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, salesOrder.getAmountPaid())) {
    paymentStatus = PayStatus .FULLY_PAID;
} 
else if (MathUtils.areEqual(totalAmountAfterEvent, BigDecimal.ZERO)) {
    paymentStatus = PayStatus .NOT_APPLICABLE;
} 
else if (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent))) {
    paymentStatus = PayStatus .PARTIALLY_PAID;
} 
else if (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, salesOrder.getAmountPaid()) || (MathUtils.areEqual(totalAmountAfterEvent, salesOrder.getAmountPaid())))) {
     paymentStatus = PayStatus .PARTIALLY_PAID;
} 
else {
     paymentStatus = salesOrder.getPaymentStatus();
}

____________________________________________________________

В качестве альтернативы вы можете сделать каждое значение if (?) целым:

private static int conditions() {
     if(your_first_statement) {
         return 0;
     }
     else if(your_second_statement) {
         return 1;
     } 
     // continue with all your if statements and put this method way down in your programm

ИтакВаша основная функция будет:

  private static void whatever_function_youre_in() {
      int condition = conditions();
      switch(condition) {
      case 0: {
          //your code from the first if statement
      }
      case 1: {
          // your code from the second if statement
      }
      } // continue with all your if conditions
   }    // your else conditions could be the default case from switch (maybe)

РЕДАКТИРОВАТЬ

Поскольку было неясно, что я имел в виду с 3 функциями:

В кодеСоздатель дал вам возможность упаковать их в пустоты и выполнить их следующим образом:

function1();
function2();
function3();

После этого продолжите работу с моим переключателем.

Однако имейте в виду, что вы должны выполнить условия ()сначала и объявите все ваши значения int для всего класса.Например:

 private static int your_int;
 private static int your_second_int;
 // and so on...

EDIT2

А для бедных парней (включая создателя) вот полный код:

public class your_class() {
private static int conditions() {
if (qtyOrdered == qtyShipped && qtyShipped >= qtyReturned) {
       return 0;
    } 
    else if (qtyOrdered > qtyShipped && qtyShipped > qtyReturned) {
        return 1;
    } 
    else if (qtyOrdered > qtyShipped && qtyShipped == qtyReturned) {
        return 2;
    } 
    else {
        return 3;
    }
    if (qtyOrdered == qtyInvoiced && qtyInvoiced > qtyReturned) {
        return 4;
    } 
    else if (qtyOrdered == qtyInvoiced && qtyInvoiced == qtyReturned) {
        return 5;
    } 
    else if (qtyOrdered > qtyInvoiced && qtyShipped > qtyReturned) {
        return 6;
    } 
    else if (qtyOrdered > qtyInvoiced && qtyShipped == qtyReturned) {
        return 7;
    } 
    else {
        return 8;
    }
    if (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, salesOrder.getAmountPaid())) {
        return 9;
    } 
    else if (MathUtils.areEqual(totalAmountAfterEvent, BigDecimal.ZERO)) {
        return 10;
    } 
    else if (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent))) {
        return 11;
    } 
    else if (MathUtils.isFirstLessThanSecond(salesOrder.getAmountPaid(), totalAmountAfterEvent) && (MathUtils.isFirstLessThanSecond(totalAmountAfterEvent, salesOrder.getAmountPaid()) || (MathUtils.areEqual(totalAmountAfterEvent, salesOrder.getAmountPaid())))) {
        return 12;
    } 
    else {
        return 13;
    }
}

private static void main(Strings[] args) {
int conditions = conditions();
switch(condition) {
case 0: {
    shippingStatus = ShiStatus.FULLY_SHIPPED;
}
case 1: {
    shippingStatus = ShiStatus.PARTIALLY_SHIPPED;
}
// all your other cases
}
}

Я думаю, что теперь вы можете лучше понять это и завершить остальную часть переключения.Примечание. Вы должны сделать доступными все статические int вашего динамического int в вашем классе.

...