Panowanie na nadmiarowością kodu

Wstęp

Dzisiaj chciałem pokazać trochę teorii na temat tworzenia rozwiazań w MsAccess. Chodzi o aspekt generowania niepotrzebnej ilości kodu, zamiast starać się zamykać wszystko we wspólnych kawałkach. Częściowo wynika to z tego, że rozwiązania sa pisane przez osoby dopiero zaczynające przygodę z programowaniem, częściowo wynikają z braku znajomości samego Access’a.

Problem

Część osób generuje nadmiarowy kod VBA, który służy do robienia czegoś w taki sam sposób, albo podobny nie wyodrębniając funkcji, modułów czy klas. Każdy doświadczony programista wie, że redundancja to nie jest nic dobrego i taki kod staje się koszmarny w utrzymaniu i rozbudowie. Posłużymy się tu przykładem, prostego formularza, na którym będzie prostokąt i trzy przyciski opcji do zmiany jego tła:

a kod wygląda tak:

Private Sub toggCzarny_Click()
    Me.prostokat.BackColor = vbBlack
End Sub

Private Sub toggCzerwony_Click()
    Me.prostokat.BackColor = vbRed
End Sub

Private Sub toggZielony_Click()
    Me.prostokat.BackColor = vbGreen
End Sub

Zmiany

Efekt pracy już mamy, teraz rozpoczynamy testy i zauważamy, że każdy z przycisków po naciśnięciu pozostaje naciśnięty lub nie, zależnie od stanu początkowego.
To wymusza na nas wprowadzenie zmian w kodzie. Chleb powszedni każdego developera, no to nie pozostaje nam nic innego jak zmodyfikować kod dla przycisków, aby odznaczały inne przyciski.
Efektem tego będzie taki o to kod

Private Sub toggCzarny_Click()
    Me.prostokat.BackColor = vbBlack
    Me.toggCzarny = True
    Me.toggCzerwony = False
    Me.toggZielony = False
End Sub

Private Sub toggCzerwony_Click()
    Me.prostokat.BackColor = vbRed
    Me.toggCzarny = False
    Me.toggCzerwony = True
    Me.toggZielony = False
End Sub

Private Sub toggZielony_Click()
    Me.prostokat.BackColor = vbGreen
    Me.toggCzarny = False
    Me.toggCzerwony = False
    Me.toggZielony = True
End Sub

Zmiany, zmiany

Zbiegiem czasu pojawiła się potrzeba dodania zmiany na kolor biały, więc dodajemy kolejny przycisk i modyfikujemy kod:

Private Sub toggBialy_Click()
    Me.prostokat.BackColor = vbWhite
    Me.toggCzarny = False
    Me.toggCzerwony = False
    Me.toggZielony = False
    Me.toggBialy = True
End Sub

Private Sub toggCzarny_Click()
    Me.prostokat.BackColor = vbBlack
    Me.toggCzarny = True
    Me.toggCzerwony = False
    Me.toggZielony = False
    Me.toggBialy = False
End Sub

Private Sub toggCzerwony_Click()
    Me.prostokat.BackColor = vbRed
    Me.toggCzarny = False
    Me.toggCzerwony = True
    Me.toggZielony = False
    Me.toggBialy = False
End Sub

Private Sub toggZielony_Click()
    Me.prostokat.BackColor = vbGreen
    Me.toggCzarny = False
    Me.toggCzerwony = False
    Me.toggZielony = True
    Me.toggBialy = False
End Sub

Czyli ręcznie musieliśmy wprowadzić zmiany w trzech procedurach zdarzenia. I dopisać kolejną. I tak w ramach zmian to będzie rosło.
Powielamy strasznie dużo kodu, oczywiście przykład zawiera tylko 4 kontrolki, ale w razie ich większej ilości mamy naprawdę coś takiego, że jak usłyszymy o dodaniu kolejnego koloru to będziemy się bronić przed tym nogami i rękami.

Rozwiązanie

Tutaj trochę uproszczę i nie będę pokazywał etapów pośrednich, ale możemy wychwycić jedno: każdy z tych przycisków zmienia kolor i wyłącza zaznaczenie pozostałych.
To ubierzmy to w jedną funkcję, która będziemy wywoływać z kodu każdego przycisku. W końcu potrzebujemy tylko dwóch rzeczy aby to zrobić:
1. Kolor do zmiany
2. Nazwa kontrolki którą zostawiamy zaznaczoną

Więc scalmy to do takiej postaci:

Private Sub toggBialy_Click()
    ZmienKolor vbWhite, "toggBialy"
End Sub

Private Sub toggCzarny_Click()
    ZmienKolor vbBlack, "toggCzarny"
End Sub

Private Sub toggCzerwony_Click()
    ZmienKolor vbRed, "toggCzerwony"
End Sub

Private Sub toggZielony_Click()
    ZmienKolor vbGreen, "toggZielony"
End Sub
Function ZmienKolor(kolor As Long, kontrolka As String)
    Dim c           As Control

    Me.prostokat.BackColor = kolor
    For Each c In Me.Controls
        If c.ControlType = acToggleButton Then
            c.Value = (c.ControlName = kontrolka)
        End If
    Next
End Function

Tutaj ujawnia się mój skrót, oczywiście mógłbym wypisać literalnie przyciski w funkcji i przypisywać im wartość włączony/wyłączony, ale wtedy przy dodaniu nowego koloru, musiałbym także zmieniać jej kod, a tak wystarczy dodać odpowiednie wywołanie i pętla sama wyłączy odpowiednie buttony.

Podsumowanie

Dążenie do wyodrębniania wspólnych fragmentów kodu ma naprawdę sporo zalet i wspomina o tym chyba każda książka programistyczna.
Wbrew pozorom to nie wszystko co możemy uprościć.
Access ma jeszcze jedną fajną zaletę, ze we właściwościach zdarzeń możemy odwołać sie bezpośrednio do funkcji w module formularza w taki o to sposób:

=ZmienKolor(65280;"toggZielony")

Wtedy dodanie nowego koloru nie będzie od nas wymagało nawet wchodzenia w edytor VBA.

Odwołanie się poprzez właściwość do funkcji w module nie pozwala użyć stałych języka VBA, stąd zmiana vbGreen na 65280 itd. Doatkowo argumeny funkcji rozdzielamy średnikiem (;).

Dla zainteresowanych przykładowa baza z opisywanymi formularzami

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

WordPress SEO fine-tune by Meta SEO Pack from Poradnik Webmastera
Skip to toolbar