Tutorial
Optimierungen
von ThePuppetMaster | Seite 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. :)
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|
|