Home | Lehre | Videos | Texte | Vorträge | Software | Person | Impressum, Datenschutzerklärung |
Stand: 2024-07-04
weitgehend formuliert von Claude 3.5 Sonnet
Der Hauptzweck der Modularisierung ist es, komplexe Systeme in kleinere, überschaubare und wiederverwendbare Teile zu zerlegen. Dies bringt mehrere wichtige Vorteile mit sich:
Übersichtlichkeit und Wartbarkeit. Große Programme werden in kleinere, leichter verständliche Einheiten aufgeteilt. Dies macht den Code einfacher zu lesen, zu verstehen und zu warten. Änderungen können oft in einzelnen Modulen vorgenommen werden, ohne das gesamte System zu beeinflussen.
Wiederverwendbarkeit. Gut gestaltete Module können in verschiedenen Projekten wiederverwendet werden. Dies spart Zeit und sorgt dafür, dass der Code öfter angewendet und damit getestet wird.
Arbeitsteilung und Zusammenarbeit. Verschiedene Entwickler oder Teams können gleichzeitig an unterschiedlichen Modulen arbeiten. Dies ermöglicht eine effizientere Entwicklung, besonders bei größeren Projekten.
Trennung von Zuständigkeiten. Jedes Modul kann sich auf eine spezifische Aufgabe oder Funktionalität konzentrieren. Dies fördert eine klare Struktur und erleichtert das Debuggen.
Abstraktion und Kapselung. Module können komplexe Funktionalitäten hinter einfachen Schnittstellen verbergen. Benutzer eines Moduls müssen nicht die internen Details verstehen, um es zu verwenden.
Skalierbarkeit. Modulare Systeme sind leichter zu erweitern und zu skalieren. Neue Funktionen können oft durch Hinzufügen neuer Module implementiert werden, ohne bestehenden Code stark zu verändern.
Testbarkeit. Einzelne Module können unabhängig voneinander getestet werden. Dies erleichtert das Schreiben von Tests und das Finden von Fehlern.
Flexibilität und Anpassbarkeit. Module können ausgetauscht oder aktualisiert werden, ohne das gesamte System neu zu schreiben. Dies ermöglicht eine einfachere Anpassung an sich ändernde Anforderungen.
Ein Alltagsbeispiel zur Veranschaulichung: Stellen Sie sich ein modernes Auto vor. Es besteht aus vielen Modulen (Motor, Getriebe, Klimaanlage, Infotainmentsystem etc.). Jedes dieser Module - kann unabhängig entwickelt und getestet werden, - kann bei Bedarf repariert oder ausgetauscht werden, ohne das ganze Auto neu zu bauen, - ermöglicht verschiedene Konfigurationen (z.B. verschiedene Motoren in der gleichen Karosserie).
In der Softwareentwicklung funktioniert die Modularisierung ähnlich. Sie erlaubt es, komplexe Systeme zu erstellen, die dennoch flexibel, wartbar und erweiterbar bleiben. Gleichzeitig macht die Modularisierung die Softwareentwicklung effizienter, flexibler und nachhaltiger, besonders bei größeren und komplexeren Projekten.
In Python sind Module ganz normale
.py-Dateien. Angenommen,
wir haben ein Modul namens mathe_helfer.py
mit folgendem
Inhalt:
def addiere(a, b):
return a + b
def multipliziere(a, b):
return a * b
Alle Elemente (also Variablen, Funktionen, Klassen) eines solchen Moduls können in anderen Python-Dateien verwendet werden – und damit auch in anderen Modulen verwendet werden.
In einem anderen Programm können wir dieses Modul nun so verwenden:
import mathe_helfer
= mathe_helfer.addiere(5, 3)
ergebnis1 = mathe_helfer.multipliziere(4, 2)
ergebnis2 print(ergebnis1) # Ausgabe: 8
print(ergebnis2) # Ausgabe: 8
In dem Programm, das das Modul verwendet, muss man immer
mathe_helfer
vor die Namen der verwendeten Elemente
schreiben. Das ist zwar übersichtlich, kann aber nerven.
Knapper ist der Import mit einem Alias
, hier
mh
:
import mathe_helfer as mh
= mh.addiere(5, 3)
ergebnis1 = mh.multipliziere(4, 2)
ergebnis2 print(ergebnis1) # Ausgabe: 8
print(ergebnis2) # Ausgabe: 8
print(mh.PI) # Ausgabe: 3.14159
Wenn man nur ausgewählte Elemente aus dem Modul benötigt, kann man
diese gezielt importieren und dann ohne Namenszusätze verwenden. Das
kann allerdings zu Namenskollisionen führen, zum Beispiel, wenn man in
der folgenden Beispieldatei noch eine eigene Funktion
addiere
haben wollen würde:
from mathe_helfer import addiere, multipliziere
= addiere(5, 3)
ergebnis1 = multipliziere(4, 2)
ergebnis2 print(ergebnis1) # Ausgabe: 8
print(ergebnis2) # Ausgabe: 8
Es ist zwar bequem, aber wegen der Gefahr von Namenskollisionen keine
gute Idee, einfach mit *
alle Elemente eines Moduls (außer
denen, deren Name mit einem Unterstrich anfängt) zu importieren:
from mathe_helfer import *
= addiere(5, 3)
ergebnis1 = multipliziere(4, 2)
ergebnis2 print(ergebnis1) # Ausgabe: 8
print(ergebnis2) # Ausgabe: 8
Im Prinzip kann ein import
statt am Anfang einer
Python-Datei auch mitten im Programm stehen, sogar innerhalb eines
if
. Aber Vorsicht damit!
Solche Bibliotheken wie Matplotlib und PySide wären für ein einziges Modul, das ja nur aus einer Datei besteht, viel zu komplex. Deshalb gibt es in Python noch eine höhere Ebene der Modularisierung, nämlich Packages. Der Import von Packages sieht äußerlich aus wie der oben beschriebene Import von Modulen.
Ein Package ist ein Verzeichnis, das mehrere Module enthält. Es
sollte eine spezielle Datei namens __init__.py
enthalten.
Packages können auch Unter-Packages enthalten, was eine hierarchische
Strukturierung ermöglicht.
Die Datei __init__.py
wird beim Import des Packages
ausgeführt, so dass dort allgemeine Vorbereitungen getroffen werden
können. Ebenfalls kann zum Beispiel in jener Datei festgelegt werden,
welche Elemente mit dem (nicht empfohlenen!)
from ... import *
importiert werden und welche nicht.