Buchempfehlung
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie
Umfassend, aber leicht verständlich führt dieses Buch in die Programmierung von ATMEL AVR Mikrocontrollern ein. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

Tutorial

Optimierungen

von MitgliedThePuppetMasterSeite 8 von 9

Vorzeitiger Exit

Manchmal ist es von Vorteil, das Programm, die Funktion oder Sub einfach Vorzeitig zu beenden / zu verlassen.

Sub CMD_ExecuteCMD(V_CID as UInteger, V_TSNEID as UInteger, V_CMD as UInteger, ByRef V_Data as String)
MutexLock(ClientMutex)
Dim UProfil as User_Profil_Type = ClientD(V_CID).V_Profil
MutexUnLock(ClientMutex)
Select Case V_CMD
    Case RP2P_CMD_DataStreamError
    Case RP2P_CMD_Unknow
    Case RP2P_CMD_Lang:                                     CMD_User_Lang               (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_Login:                               CMD_User_Login              (V_CID, V_TSNEID, V_Data, UProfil)
End Select
If UProfil.V_UserSSID = "" Then TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
Select Case V_CMD
    Case RP2P_CMD_NOOP
    Case RP2P_CMD_User_Info:                                CMD_User_Info               (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_List:                                CMD_User_List               (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_User_Connect:                             CMD_User_Connect            (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_AcceptConnect:                       CMD_User_ConnectAccept      (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_Disconnect:                          CMD_User_Disconnect         (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_Control:                             CMD_User_Control            (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_ImServer:                            CMD_User_ImServer           (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_Chat:                                CMD_User_Chat               (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_User_PayCoins:                            CMD_User_PayCoins           (V_CID, V_TSNEID, V_Data, UProfil)
End Select
If (UProfil.V_Admin <> 1) and (UProfil.V_Mod <> 1) Then TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
Select Case V_CMD
    Case RP2P_CMD_Admin_User_List:                          CMD_Admin_User_List         (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_User_Add:                           CMD_Admin_User_Add          (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_User_Del:                           CMD_Admin_User_Del          (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_User_Edit:                          CMD_Admin_User_Edit         (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_Admin_User_Pass:                          CMD_Admin_User_Pass         (V_CID, V_TSNEID, V_Data, UProfil)
    Case RP2P_CMD_Admin_User_Stats:                         CMD_Admin_User_Stats        (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Com_Kick:                                 CMD_Admin_Com_Kick          (V_CID, V_TSNEID, V_Data)
End Select
If (UProfil.V_Admin <> 1) Then TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
Select Case V_CMD
    Case RP2P_CMD_Admin_Log:                                CMD_Admin_Log               (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_Timeout:                     CMD_Admin_Config_TimeOut    (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_PingTime:                    CMD_Admin_Config_PingTime   (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_MinTarif:                    CMD_Admin_Config_MinCost    (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_News:                        CMD_Admin_Config_News       (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_AKSWVersion:                 CMD_Admin_Config_VersionSW  (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_AKHWVersion:                 CMD_Admin_Config_VersionHW  (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_MaxClient:                   CMD_Admin_Config_MaxClient  (V_CID, V_TSNEID, V_Data)
    Case RP2P_CMD_Admin_Config_Active:                      CMD_Admin_Config_Active     (V_CID, V_TSNEID, V_Data)
End Select
TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD)))
End Sub

Dieser Quellcode nutzt einige der zuvor beschriebenen Techniken um Optik, Geschwindigkeit und den damit verbundenen Speicherverbrauch zu reduzieren.
Zum einen Findet hier die optische TAB-Nutzung Anwendung. Die Parameter sind sauber untereinander geordnet.
Man erkennt die Strukturierung von Funktionen, deren Parameter und die zugehörigen Konstanten.

Des weiteren wird hier (was auch zur Sicherheit beiträgt) ein "Vorzeitiges Exit" genutzt. Man braucht eine Funktion nicht komplett zu durchlaufen, wenn ab einem bestimmten Zeitpunkt die Durchführung nicht mehr gestattet wird.
Zwischen den einzelnen "Select Case" findet sich ein Einzeiler.
Er besteht aus 3 Elementen. Eine Prüfung und eine doppelteilige Exit Anweisung.

If (UProfil.V_Admin <> 1) Then TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub

Diese Zeile könnte man auch folgendermaßen darstellen:

If (UProfil.V_Admin <> 1) Then
    TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD)))
    Exit Sub
End If

Da diese Zeilen grundlegend Identisch sind, abgesehen von dem zu Prüfendem Teil, habe ich die Exit-Angabe in einen Einzeiler umgewandelt.
Dies spart etwas Code, und lässt den Fokus des Quelltextes auf die elementaren Dinge legen. (der Select Case)

Man erkennt die Einzeiler auf einen Blick und deren Funktion. -> Antwort senden + Sub Verlassen.
Zusätzlich dient hier dieser Codeblock einer Art optischen Trennlinie. Man kann im Code die Einzelnen Abschnitte erkennen, ohne nach bestimmten Merkmalen zu suchen. (Code optisch stückeln)

Der vorzeitige Exit hat des weiteren den Vorteil der Geschwindigkeitsoptimierung.
Angenommen der Aufbau wäre wie folgt:

Sub CMD_ExecuteCMD(V_CID as UInteger, V_TSNEID as UInteger, V_CMD as UInteger, ByRef V_Data as String)
MutexLock(ClientMutex)
Dim UProfil as User_Profil_Type = ClientD(V_CID).V_Profil
MutexUnLock(ClientMutex)
Select Case V_CMD
    '...
    Case RP2P_CMD_User_Login:                                   CMD_User_Login              (V_CID, V_TSNEID, V_Data, UProfil)
End Select
If UProfil.V_UserSSID <> "" Then
    Select Case V_CMD
        '...
        Case RP2P_CMD_User_PayCoins:                            CMD_User_PayCoins           (V_CID, V_TSNEID, V_Data, UProfil)
    End Select
    If (UProfil.V_Admin = 1) or (UProfil.V_Mod = 1) Then
        Select Case V_CMD
            '...
            Case RP2P_CMD_Com_Kick:                             CMD_Admin_Com_Kick          (V_CID, V_TSNEID, V_Data)
        End Select
        If (UProfil.V_Admin = 1) Then
            Select Case V_CMD
                    '...
                Case RP2P_CMD_Admin_Config_Active:              CMD_Admin_Config_Active     (V_CID, V_TSNEID, V_Data)
            End Select
            TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD)))
        Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
        End If
    Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
    End If
Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
End If
End Sub

Hierbei würde eine stückweise Verschachtelung des Codes erfolgen. Zum einen erhöht es den Speicherplatz Verbrauch im Sourcecode (Else Zeile + EndIf) und zum anderen Würde Der Code länger ausgeführt werden, als wenn er vorzeitig verlassen würde.
Des weiteren erhöht diese Arbeitsweise auch den Speicherplatzverbrauch. Für jeden Namespace Block muss der Stack erweitert werden. Dies erhöht nicht nur die Laufzeit dieses Abschnitts, sondern verbraucht auch mehr Speicher als nötig wäre.

Ein weiterer Makel ist (vielleicht) noch die anwachsende Unübersichtlichkeit.

Wie würde man denn jetzt die Codeblöcke anordnen? Immer noch Untereinander?

'...
If UProfil.V_UserSSID <> "" Then
    Select Case V_CMD
        Case RP2P_CMD_NOOP
        Case RP2P_CMD_User_Info:                                CMD_User_Info               (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_List:                                CMD_User_List               (V_CID, V_TSNEID, V_Data)
        Case RP2P_CMD_User_Connect:                             CMD_User_Connect            (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_AcceptConnect:                       CMD_User_ConnectAccept      (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Disconnect:                          CMD_User_Disconnect         (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Control:                             CMD_User_Control            (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_ImServer:                            CMD_User_ImServer           (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Chat:                                CMD_User_Chat               (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_PayCoins:                            CMD_User_PayCoins           (V_CID, V_TSNEID, V_Data, UProfil)
    End Select
    If (UProfil.V_Admin = 1) or (UProfil.V_Mod = 1) Then
        Select Case V_CMD
            Case RP2P_CMD_Admin_User_List:                      CMD_Admin_User_List         (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Add:                       CMD_Admin_User_Add          (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Del:                       CMD_Admin_User_Del          (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Edit:                      CMD_Admin_User_Edit         (V_CID, V_TSNEID, V_Data, UProfil)
            Case RP2P_CMD_Admin_User_Pass:                      CMD_Admin_User_Pass         (V_CID, V_TSNEID, V_Data, UProfil)
            Case RP2P_CMD_Admin_User_Stats:                     CMD_Admin_User_Stats        (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Com_Kick:                             CMD_Admin_Com_Kick          (V_CID, V_TSNEID, V_Data)
        End Select
        If (UProfil.V_Admin = 1) Then
            Select Case V_CMD
                    '...
                Case RP2P_CMD_Admin_Config_Active:              CMD_Admin_Config_Active     (V_CID, V_TSNEID, V_Data)
            End Select
            TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD)))
        Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
        End If
    Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
    End If
Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
End If
'...

oder wäre es sinnvoll diese Blöcke jetzt in eigene Unterblöcke optisch zu separieren?

'...
If UProfil.V_UserSSID <> "" Then
    Select Case V_CMD
        Case RP2P_CMD_NOOP
        Case RP2P_CMD_User_Info:                            CMD_User_Info               (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_List:                            CMD_User_List               (V_CID, V_TSNEID, V_Data)
        Case RP2P_CMD_User_Connect:                         CMD_User_Connect            (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_AcceptConnect:                   CMD_User_ConnectAccept      (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Disconnect:                      CMD_User_Disconnect         (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Control:                         CMD_User_Control            (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_ImServer:                        CMD_User_ImServer           (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_Chat:                            CMD_User_Chat               (V_CID, V_TSNEID, V_Data, UProfil)
        Case RP2P_CMD_User_PayCoins:                        CMD_User_PayCoins           (V_CID, V_TSNEID, V_Data, UProfil)
    End Select
    If (UProfil.V_Admin = 1) or (UProfil.V_Mod = 1) Then
        Select Case V_CMD
            Case RP2P_CMD_Admin_User_List:                      CMD_Admin_User_List         (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Add:                       CMD_Admin_User_Add          (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Del:                       CMD_Admin_User_Del          (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Admin_User_Edit:                      CMD_Admin_User_Edit         (V_CID, V_TSNEID, V_Data, UProfil)
            Case RP2P_CMD_Admin_User_Pass:                      CMD_Admin_User_Pass         (V_CID, V_TSNEID, V_Data, UProfil)
            Case RP2P_CMD_Admin_User_Stats:                     CMD_Admin_User_Stats        (V_CID, V_TSNEID, V_Data)
            Case RP2P_CMD_Com_Kick:                             CMD_Admin_Com_Kick          (V_CID, V_TSNEID, V_Data)
        End Select
        If (UProfil.V_Admin = 1) Then
            Select Case V_CMD
                    '...
                Case RP2P_CMD_Admin_Config_Active:                  CMD_Admin_Config_Active     (V_CID, V_TSNEID, V_Data)
            End Select
            TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD)))
        Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
        End If
    Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
    End If
Else: TSNE_Data_Send(V_TSNEID, CMD_CreateString(RP2P_CMD_UnknowCommand, Str(V_CMD))): Exit Sub
End If
'...

Abgesehen von der Tatsache, dass die Ausführung auf dieser Art langsamer wäre, ist es natürlich Geschmackssache, wie man en Quellcode jetzt anordnet.
Persönlich würde ich jedoch dazu raten, den Code auf letztere Art zu sortieren.
Es ist Optisch zwar nicht mehr ganz so schön symmetrisch, allerdings hilft es beim Ersetzen von größeren Abschnitten, oder beim debuggen etwas, wenn man die Optische Trennung als Block darstellt.
Ob ich dies in einem Realem Fall auch so machen würde, kann ich jedoch nicht mit sagen. ... Wohl eher nicht. :)



 

Gehe zu Seite Gehe zu Seite  1  2  3  4  5  6  7  8  9  
Zusätzliche Informationen und Funktionen
  • Das Tutorial wurde am 03.12.2011 von MitgliedThePuppetMaster angelegt.
  • Die aktuellste Version wurde am 17.05.2012 von Mitgliedtheta gespeichert.
  Bearbeiten Bearbeiten  

  Versionen Versionen