Einzelnen Beitrag anzeigen

Scurra

Registriert seit: 19. Jan 2015
81 Beiträge
 
Delphi 10.3 Rio
 
#1

Vermeiden von globalen Variablen

  Alt 13. Feb 2015, 21:23
Hallo zusammen,

da ich noch ein Neuling in Delphi bin, habe ich die letzten Tage zum Üben ein Programm geschrieben, das in gewisser Hinsicht den Explorer von Windows nachahmt. Die grafische Oberfläche habe ich als Bild angehängt.
Genauer gesagt soll mein Programm folgendes machen: Ich habe einen Button ("Verzeichnis wählen"). Klickt man ihn an, kann man ein Verzeichnis wählen. In der ScrollBox, werden dann alle Bilder mit bestimmten Dateiformaten angezeigt, die sich in diesem Verzeichnis befinden. Angefangen habe ich damit, um mit dem Resize-Event zu "spielen", wenn ich nämlich die Breite des Formulars und damit die Breite der ScrollBox ändere, dann sollen die Elemente darin (anfangs waren das einfach nur Panels ohne einen Inhalt. Die Panels erkennt man, wenn man - wie im Bild im Anhang - die Bilder mit gedrückter Maustaste selektiert, die Panels sind dann blau) entsprechend neu angeordnet werden, so dass man auf keinen Fall horizontal scrollen muss. Um das zu erreichen, habe ich erst einmal ein paar globale Variablen definiert (obwohl ich globale Variablen nicht mag, da sie ein Programm fehleranfällig machen). In diesen Variablen ist dann z. B. gespeichert, wie weit die linke Spalte der Panels vom linken Rand der Scrollbox entfernt ist, wie groß die Panels überhaupt sind, wie groß die horizontalen und vertikalen der Abstände der Panels zueinander sind etc. Das kann man so machen, wenn man für jedes Panel gleiche Werte verwenden möchte wie ich in meinem Programm.

In einem weiteren Schritt habe ich Objekte der Klasse TImage auf die Panels gesetzt, worin die Bilder angezeigt werden. Auch hierfür habe ich wieder globale Variablen verwendet, um die Abstände des Bildes zu den Rändern des Panels festzulegen. Im nächsten Schritt habe ich unten noch Labels auf die Panels gelegt, um den Dateinamen anzuzeigen. Auch hier gibt es wieder globale Variablen. Ich wollte nun noch Edit-Felder über die Panels legen, um ggf. den Dateinamen zu ändern (das ganze sollte am Ende eben ähnlich aussehen wie in Windows).

Da der Quellcode inzwischen relativ unübersichtlich geworden ist, habe ich mir heute Gedanken darüber gemacht, "meine" Panels als eine eigene Klasse zu definieren. Dann spare ich mir den ganzen Aufwand in meinem Programm, die Eigenschaften von den TImage-Komponenten, den Labels etc. zu setzen. Dann brauch ich ledigich noch Bilder inkl. Dateinamen an die Instanzen meiner Klasse (die ich TIconPanel genannt habe) zu übergeben und die Klasse soll dann den Rest für mich erledigen.

Jetzt bin ich aber auf 2 Probleme gestoßen, die mich schon den ganzen Nachmittag aufgehalten haben, weil ich noch sehr unerfahren im Programmieren bin und nicht weiß, wie man es am besten implementieren sollte:

1. Ich möchte die vielen globalen Variablen weg haben, aber die Daten müssen ja trotzdem in irgendeiner Weise zur Verfügung gestellt werden. Wenn man die Werte für die Abstände etc. variabel halten möchte, würde ich einfach Attribute definieren, die dann jede Instanz der Klasse TIconPanel trägt. Dann kann man über über Properties darauf zugreifen und ggf. die Werte ändern.
Eine andere Möglichkeit wäre (wenn man die Abstände, Größen etc. konstant halten möchte), keine Set-Methoden zu implementieren, so dass man nur zum Lesen auf die Attribute zugreifen kann. Die Werte werden im Konstruktor festgelegt und bleiben immer gleich, solange die Werte niemand im Quellcode ändert
Was ich mir als erstes überlegt habe (und ich habe es auch so implementiert, aber das hat der Übersichtlichkeit geschadet), war, die globalen Variablen in Form von Klassenfeldern zu definieren und dann mit Klasseneigenschaften darauf zuzugreifen. Diese Idee schien mir am naheliegensten, weil ich erst einmal alle Abstände, Größen etc. konstant halten wollte, d. h. diese Parameter sind nicht individuell für jede Instanz sondern sollen für die gesamte Klasse "gelten", es sind also Eigenschaften der Klasse, nicht der Instanzen. Nachdem ich es implementiert habe, habe ich jedoch festgestellt, dass das kaum etwas an meiner Programmstruktur geändert hat. Ich habe beim Öffnen des Formulars einfach den Klasseneigenschaften die gewünschten Werte zugewiesen und dann eben diese Klasseneigenschaften anstatt den globalen Variablen verwendet. Mir kamen diese Klasseneigenschaften jedoch genau wie die gloaben Variablen vor, nur dass ich eben nicht extra Variablen in meinem Formular definieren musste, sondern die "globalen" Klasseneigenschaften der Klasse verwendet habe.
Ich hoffe, dass ich mein Problem klar genug darstellen konnte und mir jemand einen Rat geben kann. Mir geht es hier nicht darum, dass mir jemand Quelltext schreibt (außer, es hilft beim Verständnis ), sondern darum, welches Prinzip sich am besten eignet, mein Problem zu implementieren, das Programm werde ich später vmtl. sowieso nie brauchen Evtl. gibt es noch eine andere gute Möglichkeit, an die ich noch gar nicht gedacht habe.

2. Nun zu meinem zweiten Problem: Eine meiner globalen Variablen ist ein "array of TPanel", das die Panels, die angezeigt werden sollen, enthält. Damit kann man leicht arbeiten: Man kann auf einzelne Panels mittels Index zugreifen, man kann Panels hinzufügen, löschen, die Sortierung ändern etc. Deshalb möchte ich diese Art der Datenspeicherung gar nicht aufgeben. Trotzdem stellt sich mir die Frage, ob es sinnvoll ist, auch hier die globale Variable durch etwas anderes zu ersetzen. Ich hatte wieder die Idee, der Klasse TIconPanel ein array of TIconPanel als Klassenfeld zu übergeben. Beim Konstruktor der Klasse soll die erzeugte Instanz ans array angehängt werden, beim Destruktor wieder entfernt werden. Ist es sinnvoll, das so zu machen? Ich finde es einerseits sinnvoll, andererseits habe ich dann keine Möglichkeit, in meinem Formular z. B. eine zweite Scrollbox ebenfalls mit TIconPanels als Inhalt hinzuzufügen (die z. B. Bilder eines anderen Verzeichnisses anzeigt), weil ich nur ein array für die Klasse habe.
Was erscheint euch hier am sinnvollsten? Kann man überhaupt allgemein sagen, welche Art der Implementierung optimal ist, ohne jetzt schon genau zu wissen, wohin das Programm noch führt und welche Anforderungen ich an die Klasse später vllt. einmal habe? Sollte ich mich jetzt schon endgültig festlegen, wofür ich die Klasse am Ende brauche und was sie können muss, um nun eine "gute" Implementierung zu finden? Über einen Rat wäre ich auch hier sehr froh.

Schon jetzt vielen Dank an alle, die sich das durchgelesen haben und mir evtl. helfen
Miniaturansicht angehängter Grafiken
explorer.jpg  

Geändert von Scurra (13. Feb 2015 um 21:32 Uhr)
  Mit Zitat antworten Zitat