2.4 Projektorganisation
2.4.1 Namensräume und Imports
.NET und damit Visual Basic organisieren die Namen, die in den Bibliotheken verwendet werden, in einer Art Verzeichnisstruktur. Analog zu einem Verzeichnis auf der Festplatte, das zusammengehörige Dateien zusammenfasst, werden Namen auf sogenannte Namensräume (englisch namespaces) verteilt. Bei der Verwendung von Console haben wir davon nichts gemerkt, weil dieser Name in einem Namensraum ist, der importiert wurde, also nicht extra angegeben werden muss. Diese importierten Namensräume sind auf der Verweise-Lasche der Projekteigenschaften (siehe Abbildung 2.16) aufgelistet und über das in Abbildung 2.15 gezeigte Kontextmenü des Projekts erreichbar. (Klicken Sie mit der rechten Maustaste auf den Projektnamen im Projektmappen-Explorer.)
Abbildung 2.15 Kontextmenü des Projekts
Abbildung 2.16 Importierte Namensräume
Wenn man nun das Häkchen vor System (siehe Abbildung 2.16) wegnimmt, meldet der Compiler einen Fehler. Dies ist im unteren linken Teil von Abbildung 2.17 zu sehen. Wenn man mit dem Mauszeiger über der blau unterkringelten Console stehen bleibt und dann auf den erscheinenden Pfeil klickt, so teilt einem die aufspringende Liste mit, was zu tun ist. Entweder müssen Sie wieder ein Häkchen vor System setzen (Vorschlag Importieren Sie »System«) oder den Namensraum explizit angeben (Vorschlag Ändern Sie »Console« in »System.Console«).
Abbildung 2.17 Fehlermeldungen bei vergessenem Namensraum
Eine Alternative zum Häkchen vor System in den Projekteinstellungen ist die Verwendung von Imports vor dem Programmcode, wie im nächsten Listing zu sehen ist. Dies macht den Namensraum nur in dieser Datei bekannt. Häufig gebrauchte Namensräume macht man im Allgemeinen besser in den Projekteinstellungen bekannt. Wir werden daher im Folgenden den Namensraum wieder in den Projekteigenschaften importieren.
Imports System
Module Module1
Sub Main()
Console.WriteLine("Start {0}!", DateTime.Now)
Console.ReadLine()
End Sub
End Module
Den zweiten Vorschlag in Abbildung 2.17, den Namen Console mit dem Namensraum System zu qualifizieren, zeigt das nächste Listing. So ein »vollständiger« Name ist nun von allen importierten Namensräumen unabhängig und darf auch (muss aber nicht) dann verwendet werden, wenn der Namensraum bereits importiert wurde.
Module Module1 Sub Main() System.Console.WriteLine("Start {0}!", System.DateTime.Now) System.Console.ReadLine() End Sub End Module
Wenn Ihnen das zu viel Tipparbeit ist und Sie trotzdem vollqualifizierte Namen verwenden möchten, können Sie mit Imports durch eine Zuweisung mit dem Gleichheitszeichen auch Synonyme (englisch aliases) für Namensräume oder Module (oder: Klassen, Strukturen, Enumerationen) definieren. Sie haben Vorrang vor gleichlautenden einfachen Imports-Anweisungen. Noch mehr Arbeit kann man sich sparen, wenn man ein Modul importiert. Dann hat man direkt Zugriff auf die über den Modulnamen erreichbaren Modulelemente. Im folgenden Beispiel werden zwei Synonyme definiert und dann der Typ Environment eingebunden, um den systemunabhängigen Zeilenvorschub NewLine direkt verwenden zu können.
Imports S = System '1 Imports C = System.Console '2 Imports System.Environment '3 Module Module1 Sub Main() S.Console.WriteLine("Namensraum {0}!", DateTime.Now) '1 C.WriteLine("Typ {0}!", DateTime.Now) '2 Console.Write("Typ!{0}", Environment.NewLine) Console.Write("Typ!{0}", NewLine) '3 System.Console.ReadLine() End Sub End Module
Hinweis |
Wenn es durch Imports zu Zweideutigkeiten bei der Namensvergabe kommt, wird ein Compilerfehler erzeugt. |
Den Mechanismus der Namensräume kann man auch in eigenen Programmen nutzen. Denn schneller als man dies als Anfänger glauben mag, hat man viele neue Programme geschrieben. Dann kommt der Wunsch auf, das Ganze besser zu organisieren. Der Namensraum im eigenen Programm umschließt eigene Module und darf Punkte im Namen enthalten. Analog zum Ende einer Prozedur wird das Ende eines Namensraums kenntlich gemacht.
Namespace Raum 'Mein.Erster.Raum ginge auch
Module Module1
Sub Main()
Console.WriteLine("Programm gestartet!")
Console.ReadLine()
End Sub
End Module
End Namespace
Ein paar Bemerkungen zu Namensräumen:
- Ein Namensraum darf beliebig viele Module (Typen) enthalten.
- Alle Abschnitte mit identischem Namensraum (auch in verschiedenen Dateien) werden behandelt, als stünden sie in einem Namensraumabschnitt.
- Namensräume dürfen geschachtelt werden, wobei ein Namensraum mit Punkten äquivalent zu geschachtelten Namensräumen ohne Punkt ist.
- Definitionen eines inneren Namensraums haben Zugriff auf den umschließenden Namensraum.
- Module ohne Namensraum sind Teil des globalen Namensraums.
Diese Änderung muss dem Projekt gegebenenfalls noch bekannt gemacht werden. In der Lasche Anwendung der Projekteigenschaften, die Sie in Abbildung 2.18 sehen, wählen wir den Namen Module1 als Startobjekt und zwar mit dem Namensraum Raum davor. Alternativ kann rechts oben der Wurzelnamensraum in Raum geändert und Sub Main ohne qualifizierenden Namensraum ausgewählt werden.
Abbildung 2.18 Einstiegspunkt der Anwendung
Obwohl dies nur nach Kosmetik aussieht, wird sich zeigen, dass eine gute Organisation von Namen im .NET-Framework unbedingt erforderlich ist, um es überhaupt im Alltag nutzen zu können. Denn wer kann sich schon viele Tausend Namen merken, ohne eine Gedächtnisstütze für die Organisation zu haben? Außerdem fällt die Fehlersuche sehr viel leichter, wenn alles in »sprechenden« Namensräumen organisiert ist. Natürlich nur für den Fall, dass Sie Fehler machen …
2.4.2 Lösungen als Hyperprojekt
Dies ist ein guter Zeitpunkt, um von nun an die Beispiele dieses Kapitels unter einem Dach zu organisieren. Dazu legen wir ein neues Projekt mit dem Typ Leere Projektmappe an, wie Abbildung 2.19 zeigt. Als Namen verwenden wir Sprachsyntax, den Speicherort wählen Sie bitte nach Ihren Erfordernissen.
Abbildung 2.19 Neue Projektmappe erstellen
Der Projektmappen-Explorer zeigt dieses neue »Projekt« (Abbildung 2.20).
Abbildung 2.20 Leere Projektmappe
2.4.3 Existierende Projekte hinzufügen
Dieser leeren Lösung können wir nun das Projekt hinzufügen, das wir bereits erstellt haben. Dies erfolgt über das Kontextmenü der Lösung, wie Abbildung 2.21 zeigt.
Abbildung 2.21 Existierendes Projekt hinzufügen
Die Projektdatei ist ErsteKonsolenanwendung.vbproj, wie Abbildung 2.22 zeigt.
Abbildung 2.22 Existierendes Projekt wählen
Hinweis |
Der Lösung wird ein Link auf das Projekt hinzugefügt (Abbildung 2.23), und es wird keine Kopie erstellt. Beim Hinzufügen von einzelnen Quellcodedateien hat man die Wahl, indem man auf den kleinen Pfeil des Hinzufügen-Buttons klickt. |
Abbildung 2.23 Link auf Datei hinzufügen
2.4.4 Neues Projekt hinzufügen
Diesem Projekt fügen wir nun ein neues Projekt in der gleichen Lösung hinzu. Dazu verwenden wir das Menü Datei • Hinzufügen • Neues Projekt… (siehe Abbildung 2.24). Der Name des Projekts ist ImpliziteVariablen, und der Projekttyp ist eine Konsolenanwendung.
Abbildung 2.24 Projekt zur Lösung hinzufügen
Die Projektmappe enthält nun zwei Projekte, wie Abbildung 2.25 zeigt.
Abbildung 2.25 Lösung mit zwei Projekten
Schließlich müssen wir noch das neue Projekt zum Startprojekt machen. Dies erfolgt in den Eigenschaften der Projektmappe, wie Abbildung 2.26 zeigt. Bitte beachten Sie, dass dazu im Projektmappen-Explorer die Projektmappe (erste Zeile) markiert sein muss und nicht ein Projekt oder ein Teil davon. Nach der Festlegung ist das Projekt ImpliziteVariablen im Projektmappen-Explorer fett dargestellt. Eine Alternative zur Festlegung ist der Menüpunkt Als Startprojekt festlegen im Kontextmenü des Projekts.
Abbildung 2.26 Startprojekt festlegen
2.4.5 Quellcodegliederung
Die Entwicklungsumgebung erlaubt es, Teile des Codes aus der Ansicht auszublenden. Dazu klickt man auf eines der kleinen Quadrate mit einem Minuszeichen links neben dem Quellcode. Der Mauscursor in Abbildung 2.27 zeigt auf ein solches Quadrat, und der umrandete Bereich markiert, welche Codezeilen betroffen sind (vom Quadrat bis zum korrespondierenden kleinen Querstrich).
Abbildung 2.27 Zusammenklappbarer Quellcode
Nach einem Klick auf das Quadrat ergibt sich das Bild aus Abbildung 2.28. Der Code ist ausgeblendet, aber die Zeilennummern bleiben erhalten.
Abbildung 2.28 Zusammengeklappter Code
Eine weitere Möglichkeit der Quellcodeorganisation besteht in der Einführung einer #Region-"Name"-Direktive in den Quellcode. Sie hat keinen Einfluss auf die Kompilierung. Abbildung 2.29 zeigt, dass damit mehrere Prozeduren übersichtlicher gruppiert werden können. Die Gruppe reicht vom Quadrat neben #Region bis zum korrespondierenden Querstrich, umfasst also die Zeilen 3 bis 10.
Abbildung 2.29 Gruppierung mit #Region
Hinweis |
Die Kompilierung erfolgt unabhängig davon, ob Quellcode ausgeblendet ist. Ebenso ist die Reihenfolge der Modulmitglieder beliebig. |
2.4.6 Refactoring
In der Praxis wird es nicht vorkommen, dass Sie ein Programm schreiben und dabei nie die Namen von Bezeichnern oder Methodendefinitionen ändern. In solchen Fällen ist es mühsam und fehleranfällig, alle Änderungen von Hand durchzuführen. Viel besser ist es, auf Möglichkeiten der Entwicklungsumgebung zuzugreifen. Markieren Sie zum Beispiel einen Bezeichner, den Sie ändern wollen, und wählen Sie aus dem Kontextmenü (rechte Maustaste) den Punkt Umbenennen … aus, wie in Abbildung 2.30 zu sehen ist.
Abbildung 2.30 Umbenennen
In dem erscheinenden Dialog geben Sie den neuen Namen ein. Durch Bestätigung des Dialogs werden alle Vorkommen des Namens geändert, und zwar in allen Dateien, die mit dem Projekt zusammenhängen. Es gibt für die Entwicklungsumgebung zahlreiche (kommerzielle) Erweiterungen, die die Möglichkeiten automatisierter Quelltextänderungen erheblich erweitern.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.