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 2 von 9

Optische Optimierung

Zuerst einmal befassen wir uns mit der optischen Optimierung. Vor allem da ich diese vermutlich häufiger in diesem Tutorial anwenden werden.

Um sich die optische Optimierung mal vor Augen zu führen, werde ich gleich mit einem Beispiel beginnen.

Function TranslateRegisterNameToAddress(V_MCU as String, V_Registername as String, ByRef R_Address as UInteger) as Integer Export
Dim TOffSet as UInteger = 0
Select Case LCase(V_MCU)
    Case "atmega8", "atmega32"
        TOffSet = &H20
        Select Case UCase(V_Registername)
            Case "R0"               : R_Address = 0                 : Return 1
            Case "R1"               : R_Address = 1                 : Return 1
            Case "R2"               : R_Address = 2                 : Return 1
            '...
            Case "R12"              : R_Address = 12                : Return 1
            Case "R13"              : R_Address = 13                : Return 1
            Case "R14"              : R_Address = 14                : Return 1
            '...
            Case "AX"               : R_Address = REG_AX            : Return 1
            Case "AL"               : R_Address = REG_AL            : Return 1
            Case "AH"               : R_Address = REG_AH            : Return 1
            Case "BX"               : R_Address = REG_BX            : Return 1
            '...
            Case "OCR1BH"           : R_Address = TOffSet + &H29    : Return 1
            Case "OCR1AL"           : R_Address = TOffSet + &H2A    : Return 1
            Case "OCR1AH"           : R_Address = TOffSet + &H2B    : Return 1
            '...
        End Select
'...
End Select
'...
End Function

Dies ist ein kleiner Ausschnitt aus einem meiner Projekte (ein flexibler Compiler). Ich habe hier bestimmte Bereiche im Code durch TABs in optische Spalten unterteilt.
Durch die Verwendung von TABs kann die Übersichtlichkeit im Code massiv gesteigert werden, wie man im nächsten Abschnitt erkennen kann.
Die Verwendung von TABs oder Leerzeichen ist hierbei egal, da sie vom Compiler nicht in das Binärprogramm einkompiliert werden.
Jedoch hat die Verwendung von TABs den Vorteil, dass die "Gruppierung" von Textelementen deutlich schneller und einfacher zu handhaben ist, als größere Mengen von Leerzeichen.
Außerdem reduziert dies die Größe des Sourcecodes.

Nachteilig ist jedoch zu erwähnen, das bei Verwendung von unterschiedlichen TAB-Breiten Einstellungen bei (typischerweise) Monospace Fonttypen es zur Verschiebung von Textelementen kommen kann.
Wird z.B. ein TAB im Editor mit einer Schrittweite von 4 angegeben, bedeutet dies, dass für einen TAB 4 Leerzeichen dargestellt werden.

Schreibt man nun Beispielsweise einen Text der 7 Zeichen lang ist, bei einer TAB-Breite von 4, und fügt danach ein TAB ein, wird das nächste Zeichen automatisch an der "virtuellen" Position 9 platziert. (TABs sind immer modulo Produkte aus ihrer Länge zur aktuellen Position)
Stellt man diesen Text nun auf einem Editor dar, der nur eine Schrittweite von 5 anstatt von 4 hat, dann erfolgt nach 7 Zeichen und dem Modulo die nächste Position bei 10.
Genau dies kann zu einem Problem bei der Darstellung führen, wenn Quelltexte mit TABs dargestellt werden.

Im Gegensatz hierzu ist eine Statische, und überall gleich aussehende Variante mit Leerzeichen zu realisieren.
Nachteilig hier, wie schon zuvor erwähnt, ist die auf Dauer enorm anwachsende und langwieriger zu ändernde Leerzeichen Variante, bei der die TAB's durch simple Leerzeichen realisiert werden.

Des Weiteren erhöht die Nutzung von Leerzeichen die Sourcecode Größe und damit auch die Compiler-Execute-Time (Braucht länger zum kompilieren)

In diesem Tutorial wird eine generelle TAB-Breite von 4 verwendet.

Aber nun zu den optischen Auswirkungen des TAB Gebrauchs (egal ob Leerzeichen oder TAB genutzt wird).

Ohne TABs

Function TranslateRegisterNameToAddress(V_MCU as String, V_Registername as String, ByRef R_Address as UInteger) as Integer Export
Dim TOffSet as UInteger = 0
Select Case LCase(V_MCU)
    Case "atmega8", "atmega32"
        TOffSet = &H20
        Select Case UCase(V_Registername)
            Case "R0" : R_Address = 0 : Return 1
            Case "R1" : R_Address = 1 : Return 1
            Case "R2" : R_Address = 2 : Return 1
            '...
            Case "R12" : R_Address = 12 : Return 1
            Case "R13" : R_Address = 13 : Return 1
            Case "R14" : R_Address = 14 : Return 1
            '...
            Case "AX" : R_Address = REG_AX : Return 1
            Case "AL" : R_Address = REG_AL : Return 1
            Case "AH" : R_Address = REG_AH : Return 1
            Case "BX" : R_Address = REG_BX : Return 1
            '...
            Case "OCR1BH" : R_Address = TOffSet + &H29 : Return 1
            Case "OCR1AL" : R_Address = TOffSet + &H2A : Return 1
            Case "OCR1AH" : R_Address = TOffSet + &H2B : Return 1
            '...
        End Select
'...
End Select
'...
End Function

Die Übersichtlichkeit ist hier zwar im großem und ganzen noch gegeben, aber es sieht doch deutlich besser aus, wenn man die einzelnen Elemente sauber untereinander (in Spalten) anordnet.

Eine weitere Möglichkeit der De-Optimierung sieht folgendermaßen aus:

Function TranslateRegisterNameToAddress(V_MCU as String, V_Registername as String, ByRef R_Address as UInteger) as Integer Export
Dim TOffSet as UInteger = 0
Select Case LCase(V_MCU)
    Case "atmega8", "atmega32"
        TOffSet = &H20
        Select Case UCase(V_Registername)
            Case "R0"
                R_Address = 0
                Return 1

            Case "R1"
                R_Address = 1
                Return 1

            Case "R2"
                R_Address = 2
                Return 1
            '...
            Case "R12"
                R_Address = 12
                Return 1

            Case "R13"
                R_Address = 13
                Return 1

            '...
        End Select
'...
End Select
'...
End Function

Hier habe ich den Code noch weiter abgeschnitten, um das Tutorial nicht ganz so aufzublähen. Was gleich einen weiteren Punkt auf der Liste der Vorteile einer sauberen Strukturierung eröffnet: Quellcode kann ohne viele Zeilen zu "verschwenden" geschrieben werden.
Der Text geht zwar in die Breite, jedoch ist es für das Mausrad schonender wenn man nicht so lange Texte herunter scrollen muss.
Natürlich sollte man den Code nicht explizit unnötig in die Breite ziehen. Allerdings sind heutige Monitorauflösugnen von 640x480 unheimlich selten. Daher kann man ruhig davon ausgehen, das Breiten von 1024x768 schon Standard sind.
Man kann also durchaus etwas in die Breite wandern.

Optische Code-Optimierung ist zwar grundlegend Geschmackssache, hilft einem allerdings auch selbst, den Überblick zu behalten sowie schneller Informationen zu finden.

Unheimlich sinnvoll und hilfreich beim Debugging ist die Verwendung von TABs in einem Einzeiler. Die Anordnung von Quellcode in "virtuelle" Spalten erleichtert bei funktionsübergreifende Parameterübergabe die "Übersicht" der einzelnen Parameter.
Wie bereits in den letzten 3 Beispielen zu sehen war, musste die Anzahl Zeilen reduziert werden, da es einfach zu viel Code werden würde, der in die Höhe wächst. Es hat also auch den Vorteil, in kürzeren Abschnitten mehr Quellcode (geordnet) unterbringen zu können.



Nutzung von Separatoren

Als Separator kann vieles Verwendung finden, das einem beliebt.
Hat man eine intelligente IDE, welche einem Codeblöcke zusammen klappen lässt, oder durch eine Linie trennt, dann muss man sich selbst Linien schaffen.

Die einfachste Variante ist wohl das

Sub Bar()

End Sub

'--------------------------------------
Sub foo()

End Sub

Hiermit hat man einen Codeblock optisch von einem anderem Getrennt.

Persönlich verwende ich mehrere Arten von Separatoren für unterschiedliche Zwecke.

'######################################

'--------------------------------------

'- - - - - - - - - - - - - - - - - - -

Die Erste Variante ist sehr dick und breit. Die dient mir als Trennung zwischen Subs, Funktionen, Globalen Variablen, Typen, usw.
Die Zweite verwenden ich, bei der Gruppierung von Subs und Funktionen oder zusammengehöriger Teile von Code-Elementen.

Ein Beispiel:

'######################################
Sub Foo_Add()
End Sub

'--------------------------------------
Sub Foo_Del()
End Sub

'--------------------------------------
Sub Foo_Cls()
End Sub



'######################################
Sub Bar_Add()
End Sub

'--------------------------------------
Sub Bar_Del()
End Sub

'--------------------------------------
Sub Bar_Cls()
End Sub

Hier sind 2 Gruppen Von Funktionen vorhanden. Foo und Bar. Sie gehören irgendwie zusammen, da sie die selbe Funktionen auszuführen scheinen.
Allerdings sind sie auch getrennt voneinander zu betrachten. da sie z.B. auf unterschiedliche Speicherbereiche zugreifen oder auf andere Weise verschieden sind.

Daher trenne ich solche Gruppen mit der auffälligen ### Variante.
Die Untergruppierung realisiere ich mit einer dezenteren --- Linie, welche beim schnellem Scrollen gut unterschieden werden kann.


Die dritte Variante nutze ich persönlich zur weiteren Unterteilung von Spezialisierungen oder im Quellcode selbst

'######################################
Sub Bar_Add(Vari as UInteger) Overload
End Sub

'- - - - - - - - - - - - - - - - - - -
Sub Bar_Add(Vari as UShort) Overload
End Sub

'- - - - - - - - - - - - - - - - - - -
Sub Bar_Add(Vari as UByte) Overload
End Sub

'--------------------------------------
Sub Bar_Del()
End Sub

'--------------------------------------
Sub Bar_Cls()
End Sub

Damit lässt sich eine optische Trennung realisieren und gleichzeitig erkennen, dass sie noch näher zusammen gehören.

Gleiches Prinzip lässt sich z.B. auch bei einem komplexen Code anwenden (welcher später im Tutorial vollständig zu sehen sein wird)

'##################################################################################################################
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
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'...
Select Case V_CMD
    '...
    Case RP2P_CMD_User_PayCoins:                            CMD_User_PayCoins           (V_CID, V_TSNEID, V_Data, UProfil)
End Select
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'...
Select Case V_CMD
    '...
    Case RP2P_CMD_Com_Kick:                                 CMD_Admin_Com_Kick          (V_CID, V_TSNEID, V_Data)
End Select
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'...
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)))
End Sub

Das mag jetzt auf den ersten Blick etwas kurios aussehen, aber im Abschnitt "Vorzeitiger Exit" wird es eventuell etwas deutlicher.

Solche "Trennungen" sind auch hervorragend um "in-code" Dokumentationen in Abschnitte zu unterteilen (Siehe "API-Doku" vom Projekt "TSNE" oder das Beispiel "test_callback.bas" im Projekt "irc.bi")


 

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