Suche
Spannendere Java-Entwicklung mit Manifold

Manifold: Eine außeridische Technik für die dynamische Erweiterung von Javas Typsystem

Scott McKinney
Manifold

© Shutterstock.com / Fer Gregory

Manifold ist nicht von dieser Welt: Das Framework ermöglicht es Entwicklern, das Typsystem von Java dynamisch und nahtlos zu erweitern. In diesem Artikel untersucht Scott McKinney, Gründer und Engineer bei Manifold Systems, wie das Manifold Framework die Java-Entwicklung attraktiver und produktiver macht.

Einsatzprotokoll

Einsatzort: GEHEIM
Termin: 24.11.17
Uhrzeit: 22:15Z
Programmierer: GEHEIM
Sprache: Java
Software: IntelliJ IDEA

Details zum Vorfall

Zielperson erstellt eine JSON-Datei, Person.json, als Java-Ressource im Paket com.abc.

Die Zielperson begann sofort mit der Verwendung der JSON-Datei aus Java-Klassen im Projekt, als ob es sich bei ihr um eine Java-Klasse vom Typ com.abc.Person handele. Als die Zielperson Eigenschaften der JSON-Datei änderte und hinzufügte, wurden die Änderungen augenblicklich an anderer Stelle im Projekt per Code-Vervollständigung usw. verfügbar. Später führte die Zielperson einen Rename Refarctor an der JSON-Datei durch, es erfolgte eine Umbenennung von Person zu Kontakt. Alle Referenzen zu Person wurden ohne Verzögerung in Kontakt abgeändert. Weiterhin führte die Zielperson mehrere Suchanfragen und Refactorings an den JSON-Propertys und -Typen durch, alle zeigten ein Verhalten, als wenn es sich bei JSON um Java handeln würde.

Auffallend ist, dass es keine generierten Klassendateien auf der Festplatte gab, die mit der JSON-Datei korrespondierten, nachdem die Zielperson das Projekt kompiliert hatte – keine zusätzlichen Build-Schritte, keine Artefakte. Die Zielperson erstellte mehrere Tests für das Projekt und führte sie ohne Zwischenfälle durch. Die JVM schien die JSON-Datei als Java-Klassendatei zu verwenden. Es waren keine zusätzlichen Class Loader involviert, es wurden keine Runtime-Agenten verwendet. Nur eine einzige jar-Datei im Klassenpfad kam zum Einsatz: manifold.jar.

Es wurden ähnliche Ereignisse mit JavaScript-Dateien, Propertys und verschiedenen anderen beobachtet. Die Technologie scheint mit jeder Art von Datenquelle kompatibel zu sein. Offenbar kann mit der Technologie das Typensystem von Java nach Belieben erweitert werden. Andere in jüngster Zeit beobachtete Zielpersonen führten andere absonderliche Aktivitäten durch. Extension Methods wurden wie in C# definiert, strukturelle Typisierung wurde wie in den Sprachen TypeScript und Go genutzt. Weitere Informationen folgen in Kürze.

Fazit

Der Vorfall zeigt Technologie der nächsten Generation. Weitere Beobachtungen sind dringend empfohlen.

Irdischer Ursprung?

So futuristisch das „Einsatzprotokoll“ auch erscheint, es entspricht zu 100 % den Tatsachen. Manifold ist real und als Open-Source-Projekt von Manifold Systems verfügbar; ob es sich dabei um eine rekonstruierte Alien-Technologie handelt, muss noch geklärt werden. In jedem Fall können Sie Manifold mit Ihrem neuen oder bestehenden Java-Projekt nutzen.

Die Verwendung ist einfach: fügen Sie das Framework einfach als Abhängigkeit zu Ihrem Projekt hinzu. Manifold wurde entwickelt, um mit IntelliJ IDEA zu arbeiten, welches frei von JetBrains erhältlich ist. Weitere Informationen zur Verwendung von Manifold mit Ihren Projekt- und Build-Werkzeugen finden Sie in der Setup-Anleitung für Manifold.

Manifold bietet drei wichtige Features:

  • Typsichere Metaprogrammierung — vergleichbar mit F#-Type-Providern
  • Extension Method — vergleichbar mit dem gleichen Feature in Kotlin und C#
  • Strukturelle Typisierung — ähnlich wie Interfaces in TypeScript und Go

Typsichere Metaprogrammierung

Metaprogrammierung ist ein Begriff, der normalerweise für dynamische Sprachen wie JavaScript, Ruby und Python reserviert ist. Dabei handelt es sich um ein mächtiges Feature für die dynamische Typerstellung, das die fehlende Typsicherheit zur Designzeit in diesen Sprachen ausnutzt – denn sämtlicher Hokuspokus um die Metaprogrammierung ist ein Laufzeitphänomen. Obwohl sie ein flexibles Konzept ist, stellt Metaprogrammierung eine Herausforderung für Programmierer dar, da es keine Typinformationen zur Designzeit gibt, die leicht zu entdecken und verwenden wäre; dabei muss man sie nur kennen.

Der Reiz von Manifold liegt in der Fähigkeit, sowohl Kompilier- als auch Laufzeit-Metaprogrammierung durchzuführen. Diese Fähigkeit wird über Type Manifolds (Typverteiler) erreicht.

Type Manifolds sind Java-Projektionen schematisierter Datenquellen und dienen als solche als Brücke zwischen den Welten der Information und der Programmierung. Genauer gesagt transformiert ein Type Manifold eine Datenquelle in einen Datentyp, auf den der Java-Code direkt zugreifen kann, ohne Build-Schritt oder zusätzliche Kompilierungsartefakte. Kurzgesagt: Mit Manifold ist eine Datenquelle ein Datentyp.

Normalerweise greift man etwa auf Java-Property-Ressourcen wie folgt zurück:

java Properties myProperties = new Properties();
myProperties.load(getClass().getResourceAsStream("/abc/MyProperties.properties")); String myMessage = myProperties.getProperty("my.message");

Wie bei jeder Quelldatei ist eine Propertys-Datei für das Java-Typsystem fremd – es gibt keinen direkten, typsicheren Zugriff darauf. Stattdessen greifen Sie indirekt über den mit hartkodierten Strings bestückten Boilerplate Library Code darauf zu.

Im Gegensatz dazu greifen Sie mit dem Typverteiler Properties direkt auf eine Properties-Datei als Typ zu:

java String myMessage = MyProperties.my.message;

Das Ganze ist präzise und typsicher, ohne generierte Dateien oder andere Build-Schritte. Fast jede erdenkliche Art von Datenquelle ist ein potenzieller Typverteiler. Dazu gehören Ressourcendateien, Schemata, Abfragesprachen, Datenbankdefinitionen, Vorlagen, Tabellenkalkulationen, Webservices und Programmiersprachen. Derzeit bietet Manifold Typverteiler für:

  • JSON und JSON Schema
  • JavaScript
  • Properties-Dateien
  • Bilddateien
  • Dark Java
  • Manifold Templates
  • DDL und SQL (in Arbeit)

Weitere Informationen zu den Typverteilern oder Type Manifolds gibt es in der Dokumentation von Manifold.

Extensions

Der Extension-Verteiler ist eine spezielle Art von Typverteiler, mit dem Sie bestehende Java-Klassen einschließlich Java-eigener Laufzeitklassen wie zum Beispiel String erweitern können. Sie können neue Methoden, Anmerkungen und Schnittstellen zu jedem Typ Ihres Projekts hinzufügen. Nehmen wir an, Sie möchten eine neue Methode auf String erstellen, damit Sie einen String direkt auf der Konsole wiedergeben können. Normalerweise schreibt man mit Java eine „Util“-Bibliothek wie diese:

java public class MyStringUtil { public static void echo(String value) { System.out.println(value); } }

Und Sie würden sie so benutzen:

java MyStringUtil.echo("Java");

Stattdessen erstellen Sie mit Manifold eine Extension Class:

java @Extension public class MyStringExtension { public static voice echo(@This String thiz) { System.out.println(this); }}

Hier haben wir eine neue echo()-Methode zu String hinzugefügt, also benutzen wir sie wie folgt:

java "Java".echo();

Extensions eliminieren viele Zwischencodes wie „Util“- und „Manager“-Bibliotheken sowie Factory-Klassen. Als Folge davon fördern Extensions natürlich eine höhere Objektorientierung, was zu besser lesbarem und wartbarem Code führt. Der vielleicht praktischste Aspekt von Extensions bezieht sich jedoch mehr auf Ihre Gesamterfahrung als auf Ihre Entwicklungsumgebung. Beispielsweise stellt die Code-Vervollständigung bequem alle Erweiterungsmethoden dar, die in einer Extension Class verfügbar sind.

Extensions bieten noch viele weitere Möglichkeiten, in der Dokumentation zum Thema Extension Classes erfahren Sie mehr.

Strukturierte Typisierung

Java ist eine nominell typisierte Sprache – Typen sind anhand der in ihren Definitionen angegebenen Namen zuzuordnen. Zum Beispiel:

java public class Foo { public void hello() { println("hello"); } }
public interface Greeting { void hello(); }
Greeting foo = new Foo(); // error

Das Beispiel wird nicht kompiliert, da Foo nicht explizit Greeting nach Name in seiner Implements-Klausel implementiert. Eine strukturell typisierte Sprache wie TypeScript oder Go hat dagegen kein Problem mit diesem Beispiel. Grundsätzlich erfordert die strukturelle Typisierung nur die Implementierung der Interface-Methoden; eine Klasse muss nicht deklarieren, dass sie ein strukturelles Interface implementiert. Manifold bietet diese Möglichkeit über die @Structural-Annotation:

java @Structural public interface Greeting { void hello(); }

Das Hinzufügen von @Structural zu Greeting ändert dessen Verhalten in strukturelles Verhalten – Java benötigt keine Klassen mehr, um diese Kombination namentlich zu implementieren, nur seine Methoden müssen implementiert werden.

Hinweis: Eine Klasse kann weiterhin ein strukturelles Interface nominell implementieren. Auf diese Weise können sowohl Menschen als auch Tools Ihren Code schneller verstehen. Die allgemeine Idee ist, ein Interface strukturell zu verwenden, wenn man es sonst nicht nominell verwenden kann, oder wenn es den Code übermäßig kompliziert. Mehr über die Manifold Structural Interfaces erfahren Sie hier.

Vorteile

Die Kerntechnologie von Manifold ist eine dramatische Abkehr von herkömmlichen Java-Werkzeugen. Es gibt keinen Codegenerierungsschritt im Build-Prozess, keine zusätzlichen .class-Dateien oder .java-Dateien zu verwalten, keine Annotationsprozessoren und keine zusätzlichen Class Loaders zur Laufzeit. Zu den Vorteilen dieses Ansatzes gehören:

  • Zero Turnaround – direkter typsicherer Zugang zu Daten; Änderungen können sofort vorgenommen, entdeckt und genutzt werden.
  • Leichtgewichtigkeit – direkte Integration mit Standard-Java, keine speziellen Compiler, Annotationsprozessoren oder Runtime-Agenten erforderlich.
  • Effizient, dynamisch – Manifold produziert nur die Typen, die benötigt werden.
  • Kein Codegenerierungsschritt im Build-Prozess – keine generierten Dateien, keine speziellen Compiler.
  • Unterstützung der IntelliJ IDEA – alle Manifold-Typen und -Erweiterungen funktionieren mit IntelliJ.

Darüber hinaus ist Manifold nur eine JAR-Datei, die Sie in Ihr bestehendes Projekt einfügen müssen – Sie können es inkrementell verwenden, ohne Klassen neu schreiben zu müssen oder sich an eine neue Vorgehensweise anzupassen.

Zusammenfassung

Zu guter Letzt schließt Java mit Manifold die Lücke zu vielen Funktionen, die bisher ausschließlich dynamischen Sprachen vorbehalten waren. Darüber hinaus liefert Manifold diese Eigenschaften mit intakter Typsicherheit. Metaprogrammierung, Extension Classes und strukturelle Typisierung sind leicht verfügbar und vollständig in IntelliJ IDEA integriert. Das mag unmöglich oder weit hergeholt klingen, aber Sie können es aus erster Hand überprüfen – erkunden Sie Manifold auf Manifold.Systems.

Die Wahrheit liegt irgendwo da draußen!

Verwandte Themen:

Geschrieben von
Scott McKinney
Scott McKinney
Scott McKinney is the founder and principle engineer at Manifold Systems. Previously, he was a staff engineer at Guidewire where he designed and created Gosu. He currently pounds code by the truckload while listening to way too much retro synthwave.
Kommentare

Hinterlasse einen Kommentar

2 Kommentare auf "Manifold: Eine außeridische Technik für die dynamische Erweiterung von Javas Typsystem"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Peter
Gast

@Extension public class MyStringExtension { public static voice echo(@This String thiz) { System.out.println(this); }}

auf http://manifold.systems/ sieht das anders aus. Beides compiliert, aber was ist jetzt korrekt, bei so viel magic ?

Anonym
Gast

Ich verstehe die Frage nicht. Kannst du es bitte verfeinern? Danke