2010-03-26 8 views
1

Je suis tombé sur ce code aujourd'hui et je me demande quelles sont les façons de l'optimiser.Code Anecdote: optimiser le code pour plusieurs boucles imbriquées

De toute évidence, le modèle est difficile à changer car il est hérité, mais intéressé à obtenir des opinions.

Modifié certains noms et brouillé une certaine logique de base à protéger. En faire un wiki pour que les amateurs de code puissent répondre sans se soucier des points.

+0

Pouvez-vous utiliser LINQ? – SLaks

+0

Nope, ancienne version .net –

+0

Vous recherchez des optimisations de performances ou des optimisations de lisibilité? –

Répondre

1

Cela dépend beaucoup des données. Vous devez établir un profil avec un ensemble de données «typique», identifier les goulots d'étranglement, puis envisager des optimisations appropriées en fonction des données de votre profil.

+0

À la recherche de l'élégance du code, en supprimant l'imbrication .. –

+0

Je vois seulement une boucle (foreach) - peut-être que vous voulez dire quelque chose d'autre que "nesting"? –

+0

Il y a beaucoup de conditions imbriquées, qui pourraient être supprimées en profitant du fait que C# && et || Les opérateurs sont en réalité des raccourcis logiques, similaires à AndAlso et OrElse dans VB. Cela n'améliorerait pas les performances, mais rendrait le code plus facile à suivre. L'importance de la lisibilité du code est souvent sous-estimée ... –

2
if (testPayment.Customer.Name != customer.Name){continue;} 

Cela ne devrait pas être nécessaire pour commencer - il est certain que tous les paiements effectués pour une commande donnée concernent le même client?

Je n'aime pas du tout cette fonction, si je réussis à passer un payment_id, alors je ne m'attendrais qu'à recevoir soit ce paiement spécifique, soit null ... Rien de tout cela ne cherche ...

me semble que vous devez penser à redessiner beaucoup de code, et je pense qu'il va bien au-delà de cette fonction spécifique ...

+2

Dépend de la nature de l'application. J'ai vu des applications commerciales où une commande peut avoir plusieurs clients payants avec des pourcentages variables chacun doit. Bien que la comparaison par nom puisse causer des problèmes si le nom n'est pas un PK. –

+0

+1 pour cela, mais vu le code que nous avons déjà vu, je pense que c'est peu probable. Vous avez raison de le signaler si ... –

+0

Je suis juste en train de contourner l'application .. il ya beaucoup à faire .. Je pense que je vais avoir plusieurs occasions de poster des questions. –

1

Si vous pouvez ajouter des membres à la classe Payment, ajoutez un didRefund booléen qui est défini sur true chaque fois que la chaîne RefundPayment est définie sur "refund". Cela vous permet d'éviter la chaîne compare.

Avant la boucle si vous n'initialisez finalPayment comme ceci:

finalPayment = new Payment; 
finalPayment.Value = -1.0e12 

vous pouvez éviter le test nul dans la boucle. (En supposant qu'aucun des clients n'effectue de paiements négatifs d'un milliard de dollars)

1

Le premier test (if (payment.RefundPayment == null)) est redondant. Le deuxième test utilisant String.Compare fonctionne avec des chaînes null. Vous pouvez utiliser cette "optimisation" dans la deuxième place, vous utilisez cette comparaison dans la boucle foreach.

1

Vous pouvez déplacer l'une des conditions dans une fonction qui lui est propre car elle est répétée deux fois (test pour elle et son contraire). Vous pouvez également mettre les conditions ensemble et envelopper la boucle entière dans le premier conditionnel. De cette façon, vous n'avez qu'un point de sortie pour la fonction. Si cela ne semble pas gérable, vous pouvez envelopper le foreach-loop dans une fonction et l'appeler ainsi.

private static boolean IsRefundPayment(Payment payment) { 
    return payment.RefundPayment != null && String.Compare(payment.RefundPayment, "refund", true) == 0; 
} 

private static Payment FindPayment(Order order, Customer customer, int paymentId) { 
    Payment payment = Order.Payments.FindById(paymentId); 
    if (payment == null || IsRefundPayment(payment)) { 
     foreach (Payment testpayment in Order.payments) { 
      if (testPayment.Customer.Name == customer.Name && !testPayment.Cancelled && !IsRefundPayment(payment) 
       && (testPayment.Value > payment.Value)) { 
       payment = testPayment; 
      } 
     } 
    } 
    return payment; 
} 
+0

Omettre finalPayment, il suffit d'écrire directement au paiement. Ensuite, vous perdrez une déclaration, ainsi que la finale si. – Einar