Der Vorteil der Statik – Immutable Data (Teil 2)
Kommentare

Statik ist gut

Als Alternative zur Zugriffskontrolle durch Locks und ähnliche Methoden bietet sich die Implementation der Datenstrukturen in einer unveränderbaren Form an, wie in Listing 2 dargestellt.

Statik ist gut

Als Alternative zur Zugriffskontrolle durch Locks und ähnliche Methoden bietet sich die Implementation der Datenstrukturen in einer unveränderbaren Form an, wie in Listing 2 dargestellt. Diese Implementation der Klassen Product und OrderLine verwendet das Schlüsselwort readonly, um sicherzustellen, dass die Werte der Felder name und price sich nicht ändern können, nachdem sie einmal durch den Konstruktor zugewiesen wurden. Wenn dann die Methode GetValue einer bestimmten Objektinstanz aufgerufen wird, ist sichergestellt, dass sie immer den korrekten Wert für diese Objektinstanz liefert, da keine Änderung der Werte nachträglich möglich ist. Die Datenstrukturen sind nun also persistent.

public class Product {
  private readonly string name;
  public string Name { get { return name; } }
  private readonly decimal price;
  public decimal Price { get { return price; } }

  public Product(string name, decimal price) {
    this.name = name;
    this.price = price;
  }
}

public class OrderLine {
  private readonly Product product;
  public Product Product { get { return product; } }
  private readonly int count;
  public int Count { get { return count; } }

  public decimal GetValue( ) {
    return Product.Price * Count;
  }

  public OrderLine(Product product, int count) {
    this.product = product;
    this.count = count;
  }
}

[TestFixture]
public class Tests {
  [Test]
  public void TestOrderLineValue( ) {
    var product = new Product("Gummiboot", 16.99m);
    var line = new OrderLine(product, 3);
    Assert.AreEqual(50.97, line.GetValue( ));
  }
}  

Im praktischen Umgang mit solchen Datenstrukturen stellen sich nun einige Fragen:

  1. Wann wird eine Datenstruktur als unveränderbar bezeichnet? Sie könnte schließlich andere Daten referenzieren, die nicht unveränderbar sind.
  2. Was passiert, wenn Daten sich ändern müssen? Im Beispiel könnte etwa ein Product seinen Preis ändern.
  3. Ist Persistenz immer der richtige Ansatz?

Die Unveränderbarkeit von Daten ist graduell, und es wird gewöhnlich zwischen „flacher“ und „tiefer“ Unveränderbarkeit unterschieden. Flache Unveränderbarkeit bedeutet, dass eine Datenstruktur Werte speichert, die innerhalb der Datenstruktur selbst nicht geändert werden können. Das trifft auf beide Strukturen aus Listing 2 zu, und diese beiden Klassen sind auch „tief“ unveränderbar, da auch die referenzierten Datentypen selbst unveränderbar sind. Es wäre jedoch denkbar, dass etwa die OrderLine aus Listing 2 mit dem Product aus Listing 1 kombiniert würde, und in diesem Fall wäre die OrderLine „flach“ unveränderbar, aber nicht „tief“, da eine referenzierte Datenstruktur in sich nach wie vor geändert werden könnte.

Auf die Tiefe kommt es an

Aus puristischer Sicht ist eine „tiefe“ Unveränderbarkeit aller Daten sicherlich vorzuziehen, aber in der Praxis kann eine Kombination durchaus sinnvoll sein. Auch komplexe Datenstrukturen wie Listen können „flach“ recht einfach unveränderbar gestaltet werden, die „tiefe“ Unveränderbarkeit hängt allerdings mehr von der Anwendung der Strukturen als von ihrer Implementation selbst ab. Wenn Daten sich „in der wirklichen Welt“ ändern, wird dies bei der Arbeit mit unveränderbaren Datenstrukturen durch Kopien abgebildet. Ein Product mit einem geänderten Preis wird also etwa so erzeugt:

var newProduct = new Product(oldProduct.Name, newPrice);

Zunächst erscheint es, als ob diese Anlage neuer Kopien von existierenden Daten die Effizienz des Codes deutlich beeinträchtigen müsste. In manchen Fällen ist dieser Eindruck sicherlich auch richtig – es wird ein Kompromiss eingegangen, um die beste Lösung zwischen reiner Performanz, Wartbarkeit und Stabilität, Speicherverbrauch und anderen Merkmalen zu finden. Allerdings gibt es auch Situationen, in denen persistente Daten tatsächlich zu Vorteilen in der Performanz und sogar im Speicherhaushalt führen. So können in persistenten Listen etwa Teile der Listen zwischen verschiedenen Instanzen „geteilt“ und damit Speicher eingespart werden.

Die Verwendung von persistenten Daten in parallel ablaufenden Programmen führt zu einer von zwei möglichen Arten der Datenstabilität. Man unterscheidet zwischen Datenstabilität aus Sicht eines Threads selbst, die durch persistente Daten gewährleistet wird, und Datenstabilität aus der Sicht eines übergeordneten Algorithmus, die nur dann gewährleistet werden kann, wenn alle Threads mit den gleichen Daten arbeiten und jederzeit Zugriff auf die Änderungen haben, die von anderen Threads durchgeführt wurden. Die letztere Anforderung wird von persistenten Daten zunächst nicht erfüllt, da der Vorgang des Datenrückflusses noch ungeklärt ist. Dies soll allerdings zukünftigen Artikeln vorbehalten bleiben.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -