Dirk Richter
Software-Entwicklung und Architektur
Hintergrundwissen zu Gott-Objekten
„Gott-Objekte“ (engl. god objects) sind ein bekanntes Anti-Pattern in der Softwareentwicklung. Sie entstehen, wenn eine einzelne Klasse oder ein Objekt zu viele Verantwortlichkeiten übernimmt und dadurch zu komplex und zentral für das gesamte System wird. Schlechte Wartbarkeit: Geringe Wiederverwendbarkeit: Schwierige Testbarkeit: Verletzung des Single Responsibility Principle (SRP): Erhöhte Fehleranfälligkeit: Schlechte Lesbarkeit: Gott-Objekte führen zu unübersichtlichem, fehleranfälligem und schwer wartbarem Code und sollten deshalb vermieden werden. Stattdessen empfiehlt es sich, Verantwortlichkeiten klar zu trennen und einzelne Klassen möglichst unabhängig voneinander zu gestalten. 1. Zentrale „Manager“-Klassen 2. „Utility“-Klassen mit zu vielen statischen Methoden 3. Fehlende Modularisierung 4. Angst vor vielen kleinen Klassen Beispiel (Pseudocode): Hier übernimmt ApplicationManager Aufgaben aus ganz unterschiedlichen Bereichen – ein typisches Gott-Objekt. Gott-Objekte entstehen meist durch fehlende Trennung von Verantwortlichkeiten, pragmatische „Sammelklassen“ oder unüberlegte Erweiterung bestehender Klassen. Sie sind ein Warnsignal für einen überarbeiteten Entwurf, bei dem man Verantwortlichkeiten besser aufteilen sollte.
Inhaltsverzeichnis
Einleitung
Hauptprobleme
Da das Gott-Objekt sehr viele Aufgaben übernimmt, ist es schwer, Änderungen vorzunehmen, ohne unbeabsichtigte Seiteneffekte zu erzeugen.
Funktionen, die im Gott-Objekt implementiert sind, lassen sich schwer in anderen Kontexten wiederverwenden, da sie eng mit anderen Verantwortlichkeiten verknüpft sind.
Durch die zentrale Rolle und die Kopplung an viele andere Teile des Programms wird das Testen einzelner Funktionen oder Methoden erschwert.
Das Gott-Objekt ignoriert das Prinzip, dass jede Klasse nur für eine einzige Aufgabe verantwortlich sein sollte.
Da viele Teile des Systems vom Gott-Objekt abhängig sind, kann ein Fehler in diesem Objekt große Auswirkungen haben.
Der Code wird unübersichtlich, da zu viele Funktionen und Daten in einer Klasse gebündelt sind.Zusammenfassung
Beispiele von Gott-Objekten
Oft werden Klassen wie ApplicationManager, DataManager oder SystemController geschaffen, die viele verschiedene Aufgaben übernehmen:
Mit der Zeit wächst die Klasse immer weiter und übernimmt immer mehr Verantwortlichkeiten.
Klassen wie Utility, Helper oder Tools werden mit zahlreichen statischen Methoden ausgestattet, die quer durch die gesamte Anwendung gebraucht werden.
Dadurch entsteht ein Sammelbecken für alles Mögliche, ohne klare Trennung der Aufgaben.
Wenn beim Entwurf keine saubere Trennung der Verantwortlichkeiten erfolgt, landen immer mehr Funktionen in einer zentralen Klasse.
Manche Entwickler möchten „zu viele“ Klassen vermeiden und packen daher möglichst viele Funktionen in eine große Klasse, statt die Logik aufzuteilen. 1public class ApplicationManager
2{
3 // Konfigurationsdaten
4 public string ConnectionString { get; set; }
5
6 // Benutzerverwaltung
7 public List<string> Users { get; set; } = new List<string>();
8
9 // Logger
10 public void Log(string message)
11 {
12 Console.WriteLine($"[LOG] {DateTime.Now}: {message}");
13 }
14
15 // Datenbankzugriff
16 public void SaveData(object data)
17 {
18 Log("Saving data to database...");
19 // Verbindung zur DB herstellen und Daten speichern
20 // (Hier nur Dummy-Code)
21 Console.WriteLine("Data saved!");
22 }
23
24 public object LoadData(int id)
25 {
26 Log($"Loading data with ID {id} from database...");
27 // Verbindung zur DB herstellen und Daten laden
28 // (Hier nur Dummy-Code)
29 return new { Id = id, Value = "Sample" };
30 }
31
32 // Konfigurationsmanagement
33 public void LoadConfiguration()
34 {
35 Log("Loading configuration...");
36 // Konfiguration laden (Dummy)
37 ConnectionString = "Server=myServer;Database=myDB;User=myUser;";
38 }
39
40 // Benutzerverwaltung
41 public void AddUser(string username)
42 {
43 Log($"Adding user {username}...");
44 Users.Add(username);
45 }
46
47 public bool Authenticate(string username)
48 {
49 Log($"Authenticating user {username}...");
50 return Users.Contains(username);
51 }
52
53 // Weitere Verantwortlichkeiten...
54 // z.B. Netzwerkkommunikation, UI-Steuerung, etc.
55}
Fazit