Ee
E
Basisdaten
Paradigmen: multiparadigmatisch, objektorientiert
Erscheinungsjahr: 1997
Entwickler: Mark S. Miller
Wichtige Implementierungen: GCC, MSVC, Borland C, Portland Group, Intel, Clang
Beeinflusst von: Joule, Original-E, Java8
erights.org

E ist eine objektorientierte Programmiersprache für sicheres verteiltes Rechnen, die 1997 von Mark S. Miller,[1] Dan Bornstein, Douglas Crockford,[2] Chip Morningstar[3] und anderen bei Electric Communities entwickelt wurde. E stammt hauptsächlich von der nebenläufigen Sprache Joule und von Original-E ab, einer Reihe von Erweiterungen für Java zur sicheren verteilten Programmierung. E kombiniert nachrichtenbasierte Berechnungen mit einer Java-ähnlichen Syntax. Ein Gleichzeitigkeitsmodell, das auf Ereignisschleifen und Versprechen basiert, stellt sicher, dass es nie zu einem Deadlock kommen kann.[4]

Philosophie Bearbeiten

Die E-Sprache wurde im Hinblick auf eine sichere Datenverarbeitung entwickelt; dies wird vor allem durch die strikte Einhaltung des objektorientierten Computermodells erreicht, das in seiner reinen Form Eigenschaften aufweist, die eine sichere Datenverarbeitung unterstützen. Die Sprache E und ihre Standardbibliothek verwenden durchgängig eine fähigkeitsbasierte Entwurfsphilosophie, um Programmierer bei der Erstellung sicherer Software zu unterstützen und Softwarekomponenten die Zusammenarbeit zu ermöglichen, auch wenn sie einander nicht vollständig vertrauen. In E dienen Objektreferenzen als Capabilities, so dass Capabilities keine zusätzlichen rechnerischen oder konzeptionellen Overhead-Kosten verursachen. Die Sprachsyntax ist so konzipiert, dass sie leicht auf Sicherheitsmängel überprüft werden kann. So wird beispielsweise durch lexikalisches Scoping der Umfang des Codes begrenzt, der auf seine Auswirkungen auf eine bestimmte Variable untersucht werden muss. Ein weiteres Beispiel: Die Sprache verwendet den ==-Operator für Vergleiche und den :=-Operator für Zuweisungen; um Verwechslungen zu vermeiden, gibt es keinen =-Operator.

Berechnungsmodell Bearbeiten

In E sind alle Werte Objekte, und Berechnungen werden durch das Senden von Nachrichten an Objekte durchgeführt. Jedes Objekt gehört zu einem Behälter (analog zu einem Prozess). Jeder Behälter hat einen einzelnen Ausführungsstrang, einen Stapelrahmen und eine Ereigniswarteschlange. Bei der verteilten Programmierung geht es lediglich darum, Nachrichten an entfernte Objekte (Objekte in anderen Vats) zu senden. Die gesamte Kommunikation mit entfernten Parteien wird von der E-Laufzeit verschlüsselt. Eingehende Nachrichten werden in die Ereigniswarteschlange des Bottichs gestellt; die Ereignisschleife des Bottichs verarbeitet die eingehenden Nachrichten eine nach der anderen in der Reihenfolge ihres Eingangs.

E hat zwei Möglichkeiten, Nachrichten zu versenden: den sofortigen Aufruf und das eventuelle Senden. Ein sofortiger Aufruf ist genau wie ein typischer Funktions- oder Methodenaufruf in einer nicht-konkurrierenden Sprache: Der Sender wartet, bis der Empfänger fertig ist und gibt einen Wert zurück. Bei einem eventuellen Senden wird die Nachricht gesendet und gleichzeitig ein Platzhalter für das Ergebnis, ein so genanntes Versprechen, erzeugt. Der Sender fährt sofort mit dem Versprechen fort. Später, wenn der Empfänger fertig ist und ein Ergebnis liefert, wird das Versprechen in das Ergebnis aufgelöst. Da bei der Kommunikation mit entfernten Objekten nur Eventualsendungen zulässig sind, können keine Deadlocks entstehen. In verteilten Systemen minimiert der Versprechungsmechanismus auch die durch Netzwerklatenz verursachten Verzögerungen.

Syntax und Beispiele Bearbeiten

Die Syntax von E ähnelt am meisten der von Java, obwohl sie auch einige Ähnlichkeiten mit Python und Pascal aufweist. Variablen sind dynamisch typisiert und lexikalisch skaliert. Anders als Java oder Python besteht E jedoch vollständig aus Ausdrücken. Hier ist ein extrem einfaches E-Programm:

 println("Hallo, Welt!")

Hier ist eine rekursive Funktion zur Berechnung der Fakultät einer Zahl, geschrieben in E. Funktionen werden mit dem Schlüsselwort def definiert.

 def factorial(n :int) :int {
   if (n == 1) {
     return 1
   } else if (n > 0) {
     return n * factorial(n-1)
   } else {
     throw("invalid argument to factorial: "+n)
   }
 }

In der ersten Zeile ist :int eine Schutzfunktion, die das Argument und das Ergebnis der Funktion einschränkt. Ein Guard ist nicht ganz dasselbe wie eine Typdeklaration; Guards sind optional und können Einschränkungen angeben. Das erste :int stellt sicher, dass der Körper der Funktion nur ein ganzzahliges Argument verarbeiten muss. Ohne das zweite :int wäre die Funktion nicht in der Lage, einen Wert zurückzugeben. Die Möglichkeit, im Voraus zu erkennen, dass Informationen aus der Funktion entweichen, ist für die Sicherheitsprüfung hilfreich.

Da E die sichere Zusammenarbeit unterstützen soll, ist das kanonische Beispiel für E-Programme die Münzanstalt, ein einfaches elektronisches Geldsystem in nur wenigen Zeilen E. Der folgende Code definiert eine Funktion, die Münzanstalten herstellt, wobei jede Münzanstalt ihre eigene Währung hat. Jede Münzanstalt kann Geldbörsen herstellen, die ihre Währung enthalten, und jeder Besitzer von zwei Geldbörsen mit derselben Währung kann sicher Geld zwischen den Geldbörsen transferieren. Durch eine schnelle Prüfung des Quellcodes kann ein E-Programmierer leicht feststellen, dass nur Münzanstalten die Menge des im Umlauf befindlichen Geldes ändern können, dass Geld nur geschaffen und nicht vernichtet werden kann, dass Münzanstalten nur Geld ihrer eigenen Währung herstellen können und dass nur der Inhaber eines Geldbeutels dessen Saldo ändern kann.

 def makeMint(name) :any {
   def [sealer, unsealer] := makeBrandPair(name)
   def mint {
     to makePurse(var balance :(int >= 0)) :any {
       def decr(amount :(0..balance)) :void {
         balance -= amount
       }
       def purse {
         to getBalance() :int { return balance }
         to sprout() :any { return mint.makePurse(0) }
         to getDecr() :any { return sealer.seal(decr) }
         to deposit(amount :int, src) :void {
           unsealer.unseal(src.getDecr())(amount)
           balance += amount
         }
       }
       return purse
     }
   }
   return mint
 }

Objekte in E werden mit dem Schlüsselwort def definiert, und innerhalb der Objektdefinition wird jede Methode mit dem Schlüsselwort to eingeleitet. Die guard-Ausdrücke in diesem Beispiel veranschaulichen, wie eine Werteinschränkung (wie in :(int >= 0) oder :(0..balance)) angegeben werden kann.

Das Mint-Beispiel verwendet einen eingebauten Mechanismus, den sogenannten Sealer. Die Funktion makeBrandPair erzeugt zwei zugehörige Objekte, einen Versiegler und einen Entsiegler, so dass der Versiegler ein Objekt in einer Schachtel versiegeln kann und der Entsiegler das einzige Objekt ist, das den Inhalt der Schachtel abrufen kann. Auf der E-Website finden Sie eine ausführlichere Erläuterung dieses Geldbeispiels[5].

Einzelnachweise Bearbeiten

  1. Alex Handy: The future of software security. In: SD Times. 14. November 2016;.
  2. Peter Seibel: Coders at Work: Reflections on the Craft of Programming. Apress, 21. Dezember 2009, S. 95–96; (englisch).
  3. E's History. In: www.erights.org.
  4. Mark S. Miller, E. Dean Tribble, Jonathan Shapiro: Concurrency Among Strangers. In: Trustworthy Global Computing. 3705. Jahrgang, 2005, S. 195–229, doi:10.1007/11580850_12, bibcode:2005LNCS.3705..195M (agoric.com [PDF]).
  5. Jonathan Rees, Mark Miller: From Objects To Capabilities - Simple Money. In: erights.org. ERights, 2001, abgerufen am 8. Juli 2014: „Before presenting the following simple example of capability-based money, we must attempt to head off a confusion this example repeatedly causes. We are not proposing to actually do money this way! A desirable money system must also provide for...“

Kategorie:Programmiersprache