Skip to content Skip to sidebar Skip to footer

Pisanie wydajnych pętli w Ferrycie z wykorzystaniem edytora zaawansowanego

Pętle są fundamentem wielu algorytmów i operacji w programowaniu, umożliwiając wielokrotne wykonywanie określonych instrukcji. Tworząc aplikacje na platformie Ferryt mamy do dyspozycji różne rodzaje pętli, takie jak for, while, do-while oraz foreach. Korzystanie z pętli możliwe jest zarówno z poziomu kontrolki przepływu „pętla” BPM jak i z poziomu reguły, gdzie pętle można napisać z wykorzystaniem składni C# w edytorze zaawansowanym.

Wydajność tych pętli może mieć znaczący wpływ na ogólną szybkość i efektywność działania aplikacji. W tym artykule omówimy, jak pisać pętle w regułach używając edytora zaawansowanego oraz jak sprawić aby taka pętla była wydajna, przedstawiając przykłady i najlepsze praktyki.

Pętla for

Pętla for jest jedną z najczęściej używanych pętli w programowaniu. Umożliwia precyzyjne kontrolowanie liczby iteracji dzięki określeniu warunku początkowego, końcowego oraz kroku iteracji (modyfikacji).

Przykład podstawowej pętli for

for (int i = 0; i < PF.WplatyKlienta.Length; i++)
{
    PF.SumaWplat += PF.WplatyKlienta[i];
}

Ten przykład ilustruje podstawową pętlę for, która iteruje po wpłatach klienta i sumuje jego wszystkie wpłaty w polu PF.SumaWplat. Przyjrzyjmy się teraz szczegółowo każdemu elementowi tej pętli:

  1. Inicjalizacja (int i = 0;): W tej części deklarujemy i inicjalizujemy zmienną i, która będzie używana jako licznik pętli. Pętla rozpoczyna się od wartości 0, co oznacza, że w pierwszej iteracji indeks pierwszej wpłaty będzie wynosił 0.
  2. Warunek (i < PF.WplatyKlienta.Length;): Jest to kluczowy element, który kontroluje, jak długo pętla będzie się wykonywać. Pętla będzie się kontynuowała, dopóki zmienna i jest mniejsza niż długość tablicy WplatyKlienta. Gdy i osiągnie wartość równą długości tej tablicy, pętla zakończy swoje działanie.
  3. Modyfikacja (krok iteracji) (i++): Ta część kodu jest wykonywana po każdej iteracji pętli. i++ oznacza, że wartość i jest zwiększana o 1 po każdej iteracji. Dzięki temu pętla przetwarza każdą wpłatę z tablicy WplatyKlienta.
Możliwości konfiguracji elementów Pętli for
  • Inicjalizacja: Możesz zainicjalizować wiele zmiennych lub użyć zmiennych już istniejących:
int indexSymulacji = 0;
for (int i = PF.IlosSplaconychRat, j = PF.IloscPozostalychRat; i < j; i++, j--)
{
    PF.Symalacja(indexSymulacji)($"ilość spłaconych rat: {i}, Ilość pozostałych rat: {j}");
    indexSymulacji ++
}

W tym przypadku i rośnie, a j maleje z każdą iteracją.

  • Warunki: Możesz użyć bardziej złożonych warunków logicznych:
for (int i = 0; i < PF.WplatyKlienta.Length && PF.WplatyKlienta[i] >= 0; i++)
{
    PF.SumaWplat += PF.WplatyKlienta[i];
}

Pętla kończy się, gdy napotkamy pierwszą ujemną wpłatę.

  • Modyfikacja (krok iteracji): Możesz zastosować różne operacje modyfikacji, niekoniecznie inkrementację:
for (int i = 0; i < PF.WplatyKlienta.Length; i += 2)
{
    PF.SumaWplat += PF.WplatyKlienta[i];
}

W tym przykładzie przetwarzamy co drugą wpłatę, co może być użyteczne w specyficznych przypadkach.

Dobre praktyki dla pętli for

  • Optymalizacja warunku końcowego: Sprawdzenie warunku końcowego powinno być jak najmniej kosztowne, np. poprzez przechowywanie długości tablicy w zmiennej lokalnej.
  • Minimalizowanie operacji wewnątrz pętli: Unikaj skomplikowanych operacji w ciele pętli, przenieś je na zewnątrz, jeśli to możliwe. Najprościej rzecz ujmując jeżeli jakaś logika może dziać się poza pętlą, nie jest wymagana powtarzania jej wykonania, powinna ona się znaleźć poza pętlą.
Przykład mało wydajny:
for (int i = 0; i < (PF.WplatyKlienta.Length - 2); i++)
{
    PF.ImieNazwiskoKlienta = "Adam Kowal";
    PF.SumaWplat += PF.WplatyKlienta[i];
}
Przykład bardziej wydajny:
int SkorygowanaLiczbaWplat = PF.WplatyKlienta.Length - 2;
for (int i = 0; i < SkorygowanaLiczbaWplat (); i++)
{
    PF.SumaWplat += PF.WplatyKlienta[i];
}
PF.ImieNazwiskoKlienta = "Adam Kowal";

W powyższym przykładzie zapisaliśmy skorygowaną długość tablicy WplatyKlienta - 2 do zmiennej SkorygowanaLiczbaWplat, co pozwala na unikanie wielokrotnego wywoływania operacji PF.WplatyKlienta.Length - 2 w każdej iteracji. Dodatkowo operacje przypisania imienia i nazwiska klienta do pola PF.ImieNazwiskoKlienta , która nie jest zależna od pętli przenieśliśmy poza pętle, aby nie wykonała się wielokrotnie.

Pętla while

Pętla while kontynuuje wykonywanie swojego ciała, dopóki warunek jest prawdziwy. Jest używana, gdy nie wiemy dokładnie, ile iteracji będzie potrzebnych z góry.

Przykład podstawowej pętli while

Rozważmy ten sam przykład sumowania wpłat klienta:

int i = 0;
while (i < PF.WplatyKlienta.Length)
{
    PF.SumaWplat += PF.WplatyKlienta[i];
    i++;
}

Ta pętla while działa podobnie do pętli for, ale różni się nieco strukturą. Oto szczegółowa analiza:

  1. Inicjalizacja (int i = 0;): Zmienna i jest inicjalizowana przed rozpoczęciem pętli.
  2. Warunek (i < PF.WplatyKlienta.Length): Pętla będzie się wykonywać tak długo, jak długo i będzie mniejsze niż liczba wpłat klienta.
  3. Modyfikacja (i++): W przeciwieństwie do pętli for, tutaj musimy ręcznie zwiększać wartość i wewnątrz ciała pętli, aby uniknąć nieskończonej pętli.

Dobre praktyki dla pętli while

  • Upewnienie się, że warunek zakończenia jest osiągalny: Aby uniknąć nieskończonych pętli, warunek zakończenia musi być osiągalny.
  • Unikanie nieskończonych pętli: Zawsze sprawdzaj, czy pętla może się zakończyć, by nie blokować programu.
  • Minimalizowanie operacji wewnątrz pętli: Unikaj skomplikowanych operacji w ciele pętli, przenieś je na zewnątrz, jeśli to możliwe. Najprościej rzecz ujmując jeżeli jakaś logika może dziać się poza pętlą, nie jest wymagana powtarzania jej wykonania, powinna ona się znaleźć poza pętlą.

Pętla do-while

Pętla do-while jest podobna do pętli while, z tą różnicą, że sprawdzenie warunku następuje po wykonaniu ciała pętli. Dzięki temu pętla do-while jest gwarantowana do wykonania co najmniej raz.

Przykład podstawowej pętli do-while

Rozważmy scenariusz, w którym musimy przynajmniej raz przetworzyć wpłaty klienta:

int i = 0;
do
{
    PF.SumaWplat += PF.WplatyKlienta[i];
    i++;
} while (i < PF.WplatyKlienta.Length);

Pętla ta sumuje wpłaty, przynajmniej raz wykonując swoje ciało. Szczegóły:

  1. Inicjalizacja (int i = 0;): Zmienna i jest inicjalizowana przed rozpoczęciem pętli.
  2. Warunek (i < PF.WplatyKlienta.Length): Warunek sprawdzany jest po wykonaniu ciała pętli, co gwarantuje przynajmniej jedno wykonanie.
  3. Modyfikacja (i++): Zmienna i jest zwiększana po każdej iteracji, co zapewnia przejście do kolejnej wpłaty.

Pętla do-while jest użyteczna, gdy chcemy, aby pętla wykonała się przynajmniej raz, niezależnie od początkowego warunku. W opisanym przypadku mamy pewność, że przynajmniej jedna wpłata klienta zostanie przetworzona i dodana do sumy, nawet jeśli tablica WplatyKlienta zawiera tylko jeden element.

Pętla foreach

Pętla foreach jest doskonałym narzędziem do iterowania przez kolekcje, takie jak tablice, listy czy inne zbiory danych. Jest szczególnie przydatna, gdy chcemy przechodzić przez wszystkie elementy kolekcji bez potrzeby manipulowania indeksem, co upraszcza kod i zmniejsza ryzyko błędów.

Przykład podstawowej pętli foreach

Rozważmy przykład, w którym mamy listę wpłat klienta i chcemy obliczyć ich sumę. Używając pętli foreach, możemy przechodzić przez każdą wpłatę w tej kolekcji i sumować je bez potrzeby martwienia się o indeksowanie.

foreach (decimal wplata in PF.WplatyKlienta)
{
    PF.sumaWplat += wplata;
}

Analiza Przykładu:

  1. Struktura pętli foreach:
    • foreach (decimal wplata in PF.WplatyKlienta) – Dla każdej wpłaty (wplata) w kolekcji PF.WplatyKlienta pętla wykonuje swoje ciało. wplata to zmienna, która przechowuje aktualnie przetwarzany element kolekcji podczas każdej iteracji.
  2. Dodawanie każdej wpłaty do sumy:
    • sumaWplat += wplata; – Każda wpłata jest dodawana do zmiennej sumaWplat, co pozwala na obliczenie łącznej sumy wszystkich wpłat.

Dobre Praktyki dla Pętli foreach

  • Ochrona przed modyfikacją kolekcji: W pętli foreach nie można modyfikować kolekcji, przez którą iterujemy (np. dodawać lub usuwać elementów), co zapobiega potencjalnym błędom.
  • Efektywność w przetwarzaniu dużych kolekcji: Pętla foreach jest zoptymalizowana pod kątem efektywnego iterowania przez kolekcje, co czyni ją dobrym wyborem do przetwarzania dużych zbiorów danych, zwłaszcza jeśli nie musimy manipulować kolejnością lub pozycją elementów.

Zagnieżdżanie pętli

Zagnieżdżanie pętli to technika, która pozwala na wykonywanie iteracji wielowymiarowych, czyli przetwarzanie danych na wielu poziomach jednocześnie. Dzięki temu podejściu system wykonuję „pętle w pętli”, dzięki czemu możemy skupić się na przetwarzaniu tylko tych danych, które są istotne, co zwiększa wydajność i przejrzystość kodu.

Załóżmy, że mamy listę rachunków klienta, z której każda pozycja zawiera informacje o statusie konta i jego wpłatach. Pierwsza pętla for iteruje po rachunkach, sprawdzając, czy są otwarte, a druga pętla for, zagnieżdżona wewnątrz pierwszej, sumuje wpłaty na danym koncie, jeśli jest ono otwarte. W kontekście tego przykładu możemy zagnieździć pętle, aby iterować po rachunkach klienta i przetwarzać wpłaty tylko na otwartych kontach.

for (int i = 0; i < PF.klient.Rachunki.Length; i++)
{
    if (PF.klient.Rachunki[i].CzyOtwarte)
    {
        for (int j = 0; j < PF.klient.Rachunki[i].Wplaty.Length; j++)
        {
            PF.sumaWplatWszystkichKont += PF.klient.Rachunki[i].Wplaty[j];
        }
    }
}

Analiza Przykładu:

  1. Pętla zewnętrzna (for):
    • for (int i = 0; i < PF.klient.Rachunki.Length; i++) – Przechodzimy przez wszystkie rachunki klienta.
  2. Warunek sprawdzający otwartość rachunku:
    • if (PF.klient.Rachunki[i].CzyOtwarte) – Sprawdzamy, czy dany rachunek jest otwarty. Jeśli tak, przechodzimy do sumowania wpłat.
  3. Pętla wewnętrzna (for):
    • for (int j = 0; j < PF.klient.Rachunki[i].Wplaty.Length; j++) – Przechodzimy przez wszystkie wpłaty na danym rachunku, jeśli jest otwarty.
  4. Sumowanie wpłat:
    • PF.sumaWplatWszystkichKont += PF.klient.Rachunki[i].Wplaty[j]; – Dodajemy każdą wpłatę z otwartego rachunku do łącznej sumy wpłat wszystkich kont.

Podsumowanie

Umiejętność odpowiedniego wyboru i efektywnego wykorzystania pętli jest kluczowa dla każdego Ferryt Developera. Dobór odpowiedniej pętli oraz dbanie o dobre praktyki wpływa nie tylko na wydajność aplikacji, ale także na jej czytelność i łatwość utrzymania. Dzięki zrozumieniu różnych typów pętli oraz przestrzeganiu dobrych praktyk, można tworzyć bardziej niezawodny i zoptymalizowany kod, co jest szczególnie istotne w zaawansowanych aplikacjach, które przetwarzają duże ilości danych.

2 Comments

Leave a comment