[JAVA] Indique si le branchement conditionnel utilise un retour anticipé ou est écrit en toute sécurité dans la couverture conditionnelle-15 [exemple de refactoring C #]

Comment écrire une branche conditionnelle

Pour écrire des branchements conditionnels (if), vous pouvez trouver des techniques de retour précoce qui n'approfondissent pas l'imbrication à divers endroits. Personnellement, je ne pense pas que tout devrait être écrit avec des retours anticipés, et devrait être utilisé en fonction de la situation. De plus, c'est cet article qui m'a inspiré pour écrire un article. Surtout, la section des commentaires a été une expérience d'apprentissage.

J'ai une politique selon laquelle les retours anticipés ne doivent être utilisés que pour la gestion des erreurs et la logique métier doit être écrite en toute sécurité de manière conditionnelle. Ce point est expliqué dans l'exemple de code ci-dessous.

Exemple de code

À titre d'exemple simple, considérons la logique de calcul du prix de paiement en tenant compte de la taxe à la consommation et du taux d'actualisation. Si certaines conditions sont remplies, la taxe à la consommation sera le prix hors taxe à la consommation. Si le taux d'actualisation remplit également certaines conditions, il sera réduit de 1 par rapport au prix après prise en compte de la taxe à la consommation. Dans un souci de simplicité, nous n'entrerons pas dans le détail sur la présence ou l'absence de taxe à la consommation et les conditions d'application des remises, mais nous la mettrons en œuvre avec un drapeau indiquant si elle est applicable ou non.

        //Calculez le montant payé par le client
        public decimal CalculatePaymentPrice(decimal price, bool canRemoveTax, bool canDiscount)
        {
            if (price < 0)
            {
                throw new ArgumentOutOfRangeException("Veuillez saisir une valeur de 0 ou plus pour le prix du produit.");
            }
            else if (canRemoveTax)
            {
                //Remise appliquée sans taxe à la consommation
                if (canDiscount)
                {
                    return price * 0.9m;
                }
                else
                {
                    return price;
                }
            }
            else
            {
                //Remise appliquée avec taxe à la consommation
                if (canDiscount)
                {
                    return price * 1.08m * 0.9m;
                }
                else
                {
                    return price * 1.08m;
                }
            }
        }
java
    //Calculez le montant payé par le client
    public BigDecimal CalculatePaymentPrice(BigDecimal price, boolean canRemoveTax, boolean canDiscount) {
        if (price.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Veuillez saisir une valeur de 0 ou plus pour le prix du produit.");
        } else if (canRemoveTax) {
            //Remise appliquée sans taxe à la consommation
            if (canDiscount) {
                return price.multiply(new BigDecimal("0.9"));
            } else {
                return price;
            }
        } else {
            //Remise appliquée avec taxe à la consommation
            if (canDiscount) {
                return price.multiply(new BigDecimal("1.08")).multiply(new BigDecimal("0.9"));
            } else {
                return price.multiply(new BigDecimal("1.08"));
            }
        }
    }
# Politique de refactoring Dans cet exemple, le flux de traitement n'est pas bon avant le retour anticipé. Puisque j'essaie de tout écrire en un seul endroit, il est difficile de diviser le processus. Jugement d'erreur => Confirmation du taux de taxe à la consommation => Confirmation du taux d'actualisation => La dépendance de chaque traitement est réduite en divisant par le processus de calcul du prix de paiement. Puisque le jugement d'erreur est un processus avant d'entrer dans la logique de calcul, un retour anticipé est effectué.

2018/05/01 postscript Comme vous pouvez le voir dans la section des commentaires, une exception est levée même s'il s'agit d'une erreur commerciale. Normalement, vous ne devez pas lever d'exception pour les erreurs professionnelles. Il s'agit d'un effet néfaste en raison de la simplification de l'exemple de code et n'est pas soumis à la refactorisation. Ce que je voulais dire dans cet exemple, c'est que je ne veux pas mettre les erreurs commerciales dans la logique, il est donc normal de les éliminer tôt.

En réalité, un plan de refactoring consiste à effectuer le processus de vérification des prix à l'avance et à appeler la méthode CalculatePaymentPrice après avoir passé le contrôle.

Après refactoring


       public decimal CalculatePaymentPriceAfterRefactoring(decimal price, bool canRemoveTax, bool canDiscount)
        {
            //Évitement des erreurs
            if (price < 0)
            {
                throw new ArgumentOutOfRangeException("Veuillez saisir une valeur de 0 ou plus pour le prix du produit.");
            }

            //Taux de taxe à la consommation fixe
            decimal taxRate;
            if (canRemoveTax)
            {
                taxRate = 0m;
            }
            else
            {
                taxRate = 0.08m;
            }

            //Taux de remise confirmé
            decimal discountRate;
            if (canDiscount)
            {
                discountRate = 0.9m;
            }
            else
            {
                discountRate = 1.0m;
            }

            //Calculer le prix de paiement
            return price * (1m + taxRate) * discountRate;
        }
java
    public BigDecimal CalculatePaymentPriceAfterRefactoring(BigDecimal price, boolean canRemoveTax,
            boolean canDiscount) {
        //Évitement des erreurs
        if (price.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Veuillez saisir une valeur de 0 ou plus pour le prix du produit.");
        }

        //Acquisition du taux de la taxe à la consommation
        BigDecimal taxRate;
        if (canRemoveTax) {
            taxRate = BigDecimal.ZERO;
        } else {
            taxRate = new BigDecimal("0.08");
        }

        //Obtenez un taux de réduction
        BigDecimal discountRate;
        if (canDiscount) {
            discountRate = new BigDecimal("0.9");
        } else {
            discountRate = BigDecimal.ONE;
        }

        //Calculer le prix de paiement
        return price.multiply(taxRate.add(BigDecimal.ONE)).multiply(discountRate);
    }

Considération

En modifiant le flux de traitement de la partie de calcul du prix de paiement, chaque traitement peut être séparé. Si vous êtes préoccupé par les variables temporaires taxRate et discountRate, vous pouvez faire de la partie de la détermination du taux de taxe à la consommation et de la détermination du taux d'actualisation une méthode. Pour la gestion des erreurs, si vous appliquez un retour anticipé et écrivez une autre logique métier en toute sécurité avec des conditions complètes, n'y a-t-il pas de problème en tant que politique de mise en œuvre? Enfin, j'ai osé écrire sur la taxe à la consommation finalisée avec un retour anticipé.

Méthode de finalisation de la taxe à la consommation (déclaration anticipée)

Ce code est concis, mais si vous l'écrivez dans if-else, vous pouvez vérifier la couverture de la condition et vous sentir à l'aise. D'un autre côté, beaucoup de gens disent que le code est trop court et que l'un ou l'autre convient. .. ..


        private decimal GetTaxRate(bool canRemoveTax)
        {
            if (canRemoveTax)
            {
                return 0m;
            }

            return 0.08m;
        }

Article précédent (ignorer les exceptions)

Table des matières

Recommended Posts

Indique si le branchement conditionnel utilise un retour anticipé ou est écrit en toute sécurité dans la couverture conditionnelle-15 [exemple de refactoring C #]
Lorsque le traitement après le branchement conditionnel est redondant-12 [C # Refactoring Sample]