MIDGARD · Multi User Dungeon Alpha 0.1

Kapitel 12: Best Practices & Architektur

In diesem letzten Kapitel des Manuals fügen wir alles zusammen. Du lernst, wie guter LPC-Code langfristig aussieht, welche Denkweisen dir helfen, Fehler zu vermeiden, und wie du deine Objekte so strukturierst, dass sie auch nach Jahren noch verständlich und wartbar bleiben.

Weiter zu Kapitel 13

Großes Lernbeispiel – Waldlichtung zur Wikingerzeit (Raum, Hebel, Versteck, NPC, Items)

12.1 Was bedeutet „guter Code“ im MUD?

Guter LPC-Code ist nicht der cleverste oder kürzeste Code. In einem MUD ist guter Code vor allem:

  • verständlich für andere (und für dich selbst in einem Jahr)
  • robust gegenüber Fehlern und unerwarteten Situationen
  • leicht erweiterbar
  • sicher im Umgang mit fremden Objekten
  • konform mit der Mudlib

Viele Anfänger versuchen, möglichst „mächtig“ zu programmieren. Erfahrene Magier versuchen, möglichst langweiligen Code zu schreiben – weil langweiliger Code stabil ist.

12.2 Klarer Aufbau von Objekten

Ein häufiges Anfängerproblem ist chaotischer Code: Funktionen überall, globale Variablen ohne Struktur, Logik im falschen Objekt.

Bewährtes Grundschema für viele Objekte:


// 1. Includes & Inherits
#include <properties.h>
inherit "/std/thing";

// 2. Konstanten & Defines
#define MAX_USES 3

// 3. Membervariablen
int uses;

// 4. create()
protected void create() {
  ::create();
  uses = MAX_USES;
}

// 5. Öffentliche Schnittstellen (Spielerbefehle)
int cmd_use(string str) { ... }

// 6. Interne Hilfsfunktionen
protected void do_effect(object who) { ... }
      

Diese Reihenfolge ist keine Pflicht, aber sie hilft enorm, sich schnell im Code zurechtzufinden.

12.3 Trennung von Verantwortung

Eine der wichtigsten Regeln guter Architektur lautet: Ein Objekt sollte genau eine Hauptaufgabe haben.

Schlechte Beispiele:

  • Ein Raum, der Quests verwaltet
  • Ein Item, das Spielerlevel verändert
  • Ein NPC, der globale Spielzustände speichert

Bessere Aufteilung:

  • Raum: Umgebung & Beschreibung
  • Item: Interaktion & Effekte
  • Questobjekt: Questlogik
  • Serviceobjekt: Berechnungen, Verwaltung

Wenn du merkst, dass ein Objekt immer größer wird, ist das meist ein Zeichen, dass du es aufteilen solltest.

12.4 Lesbarkeit vor Cleverness

LPC erlaubt sehr kompakte Konstrukte. Aber kompakt heißt nicht automatisch gut.

Schwer lesbar


if(o&&living(o)&&interactive(o)&&o->QueryProp(P_HP)>0)
  o->SetProp(P_HP,o->QueryProp(P_HP)-10);
      

Besser lesbar


if (!objectp(o)) return;
if (!living(o)) return;
if (!interactive(o)) return;

int hp = o->QueryProp(P_HP);
if (hp <= 0) return;

o->SetProp(P_HP, hp - 10);
      

Ja, das ist länger. Aber Fehler lassen sich hier viel leichter finden.

12.5 Defensive Programmierung als Standard

In einem laufenden MUD können jederzeit Dinge passieren: Spieler loggen aus, Objekte werden zerstört, Räume neu geladen.

Deshalb gilt:

  • Jeder Objektzugriff kann fehlschlagen
  • Jeder Funktionsaufruf kann einen Fehler werfen
  • Jede Referenz kann plötzlich 0 sein

Beispiel mit catch()


mixed res;
if (catch(res = ob->DangerousCall())) {
  log_file("errors", "DangerousCall failed in "+object_name(this_object())+"\n");
  return;
}
      

Defensive Programmierung fühlt sich am Anfang „übertrieben“ an, spart dir aber später extrem viel Zeit.

12.6 Weniger globale Variablen

Globale Variablen sind bequem, aber gefährlich. Sie machen Abhängigkeiten unsichtbar und Fehler schwer nachvollziehbar.

Problematisch


object last_user;

void use(object who) {
  last_user = who;
}
      

Was passiert, wenn zwei Spieler gleichzeitig interagieren?

Besser


void use(object who) {
  // benutze who lokal
}
      

Speichere nur das, was wirklich dauerhaft zum Objekt gehört.

12.7 Logging statt stilles Scheitern

Ein häufiger Anfängerfehler ist: Fehler passieren – aber niemand merkt es.

Schlecht


if (!ob) return;
      

Besser


if (!ob) {
  log_file("debug", "ob missing in "+object_name(this_object())+"\n");
  return;
}
      

Logs sind deine Augen, wenn etwas schiefgeht, während du nicht online bist.

12.8 Zusammenarbeit & Code-Stil

LPC-Code wird selten nur von einer Person gelesen. Achte daher auf:

  • einheitliche Einrückung
  • sinnvolle Funktionsnamen
  • Kommentare bei nicht offensichtlicher Logik
  • keine „magischen Zahlen“ ohne Erklärung

Kommentare sollten erklären warum etwas passiert, nicht was passiert – das sieht man im Code.

12.9 Typische Anfängerfallen – zusammengefasst

  • zu große Objekte
  • direktes Manipulieren fremder Objekte
  • fehlende Sicherheitsprüfungen
  • keine Fehlerbehandlung
  • übermäßig cleverer, schwer lesbarer Code

Fast jeder erfahrene Magier ist genau in diese Fallen getappt. Wichtig ist nicht, sie nie zu machen – sondern sie zu erkennen und daraus zu lernen.

12.10 Abschluss & Ausblick

Du hast jetzt ein vollständiges Grundlagenverständnis von LPC: von Datentypen über Objekte, Vererbung, Events, Sicherheit bis hin zu sauberer Architektur.

Der nächste Schritt ist Praxis: kleine Räume bauen, Items schreiben, Code lesen, mit erfahrenen Magiern sprechen.

Guter LPC-Code entsteht nicht über Nacht – sondern durch viele kleine Verbesserungen.

Willkommen in der Welt der MUD-Entwicklung.

Fast fertig!

Du hast das komplette Anfänger-Manual gelesen. Nutze es als Nachschlagewerk, kehre zu Kapiteln zurück und erweitere dein Wissen Schritt für Schritt.

In Kapitel 13 gibt es noch ein großes Beispielprojekt zum Lernen. Das wird toll!

Weiter zu Kapitel 13

Großes Lernbeispiel – Waldlichtung zur Wikingerzeit (Raum, Hebel, Versteck, NPC, Items)