Hallo Christian und danke, dass du dir die Zeit genommen hast. Auf der MTC stellst du GraphQL vor, eine Alternative zum klassischen Ansatz mit RESTful Web Services. Kannst du kurz Umschreiben, was GraphQL eigentlich ist?
Christian Schwendtner: Hallo Dominik, sehr gerne! GraphQL ist vorrangig eine flexible Abfragesprache. Das sieht man auch auf der offiziellen Seite von GraphQL, wo getitelt wird „A query language for your API“. Das trifft den Kern von GraphQL ganz gut, denn es stehen die Client-seitigen Datenbedürfnisse im Vordergrund, also die Möglichkeit, auf einfache und flexible Weise die benötigten Daten für Clients abfragen zu können.
Ein spannender Punkt ist hier sicher die Flexibilität, die der Client gewinnt. Dieser kann einfach und genau definieren, welche Daten (inklusive Relationen) er vom Server benötigt. GraphQL ermöglicht also eine sehr Client- bzw. Use-Case-orientierte Sicht. Der Client kann mit einem Request genau die Daten laden, die er für einen Use Case bzw. eine Bildschirmmaske benötigt (kein Under- oder Overfetching).
Wie unterscheidet sich GraphQL von RESTful Web Services?
Christian Schwendtner: Diese Frage bekomme ich sehr oft gestellt, wenn Personen das erste Mal mit GraphQL in Berührung kommen. Bevor man diese Frage beantworten kann, ist es meiner Meinung nach wichtig, den Begriff RESTful Web Services etwas genauer unter die Lupe zu nehmen. Der Begriff ist an sich gut definiert, wird in der Praxis aber oft sehr inflationär verwendet. Wir sagen sehr gern zu jedem Service, das Ressourcen, HTTP-Verben und HTTP-Statuscodes verwendet und Daten in JSON zur Verfügung stellt, REST. Genau genommen ist es das aber nicht. Von REST oder einem RESTful Web Service dürfte man eigentlich erst dann sprechen, wenn alle Kriterien, die Roy Fielding (der Erfinder von REST) definiert hat, erfüllt sind. Ein wichtiges Kriterium dabei ist HATEOAS, also Hypermedia As The Engine Of Application State. Gerade HATEOAS wird aber bei vielen Services, die angeblich RESTful sind, nicht oder nicht ausreichend umgesetzt.
Eine gute Möglichkeit, um eine Idee davon zu bekommen, „wie RESTful“ ein Service ist, bietet das Richardson Maturity Model. In ihm sind verschiedene Level definiert, je nachdem welche Aspekte von REST umgesetzt sind. Ein Service, der nur manche Kriterien von REST erfüllt (z.B. „nur“ Ressourcen, HTTP-Verben, Statuscodes aber nicht HATEOAS) wird gerne REST-ish, REST-like oder REST-wannabe genannt. Das klingt jetzt vielleicht etwas nach Haarspalterei, aber ich denke es ist wichtig, dass man sich darüber im Klaren ist was genau man mit GraphQL vergleicht – speziell, wenn es um den Vergleich mit RESTful Web Services geht.
Meiner Erfahrung nach kann man sagen, dass GraphQL eine gute Alternative zu Level 2 des Richardson Maturity Models darstellt (Verwendung von Ressourcen, HTTP-Verben, Statuscodes), aber nicht gut geeignet ist, um als Alternative zu „echten“ REST-Services zu gelten (Stichwort HATEOAS).
Ein wesentlicher Unterschied bei GraphQL ist die verpflichtende Verwendung eines Schemas. In einem GraphQL-Schema sind alle Typen, die abgefragt werden können (Queries), und Operationen, die durchgeführt werden können (Mutations), definiert. Dadurch ergibt sich die Möglichkeit, eine Abfrage schon zur Übersetzungszeit der Anwendung auf Korrektheit überprüfen zu können oder Features wie Code-Completion zur Verfügung zu stellen.
GraphQL bietet aber einige interessante Konzepte – z.B. Fragmente: Am Client kann man GraphQL-Fragmente verwenden, um ein großes Query in kleinere Teile aufzuteilen. Das kann verwendet werden, um das Query des jeweiligen Use Cases (bzw. der jeweiligen Maske) nicht an einer Stelle definieren zu müssen, sondern die Datenbedürfnisse pro UI-Komponente definieren zu können. Das hat den Vorteil, dass die Datenbedürfnisse dort definiert werden, wo sie am besten bekannt sind. Aus den Fragmenten kann dann ein (großes) Query zusammengesetzt werden, das alle Datenbedürfnisse aller Komponenten der jeweiligen Maske enthält und die benötigten Daten können dann mithilfe eines Querys – per Request – geladen werden.
Eine weitere interessante Sache bei GraphQL sind Subscriptions. Mit einer Subscription kann sich ein Client auf ein Event des Servers registrieren, um so über Änderungen informiert zu werden (z.B. unter Verwendung von WebSockets). So kann man sehr einfach Push-Funktionalität in Anwendungen realisieren. Man könnte sagen, dass GraphQL ein opinionated Ansatz ist – das bedeutet, dass für bestimmte Probleme bestimmte Lösungen vorgesehen sind, man bekommt also einen kompletten Lösungsansatz mit allen Vor- und Nachteilen.
Wo liegen die Schwächen von GraphQL?
Christian Schwendtner: Viele sind von der Einfachheit, wie man die Client-seitigen Datenbedürfnisse in GraphQL definiert, beeindruckt. Man darf aber auch nicht die Serverseite vergessen. Durch die Freiheit, die man am Client gewinnt, muss man am Server oft mehr Denkarbeit investieren, um nicht in Performance-Probleme zu laufen. Da der Client flexibel seine Datenbedürfnisse definieren kann – frei nach dem Motto „wünsch dir was“ – ist auf der Serverseite besonderes Augenmerk auf Performance zu legen. Das sollte nicht zu spät im Projekt geschehen.
Eine indirekte Schwäche von GraphQL ist, dass es manchmal als „REST 2.0“ oder als „das bessere REST“ angepriesen wird. Ich denke nicht, dass das stimmt. Hier werden oft unterschiedliche Dinge verglichen. Die Abfragesprache ist meiner Meinung nach keine Alternative für einen „echten“ REST-Service, aber durchaus für viele REST-ish Services, wie man sie sehr oft sieht. Bei denen geht es eher darum, auf einfache und flexible Art Daten für den Client zur Verfügung zu stellen.
Nehmen wir an, ich habe eine App entwickelt, die noch auf RESTful Web Services setzt, wie schwer wäre eine Umrüstung auf GraphQL und ist das überhaupt praktikabel?
Ich denke, dass sich RESTful Web Services und GraphQL gut ergänzen können. Man kann GraphQL als Gateway einsetzen, um dem Client eine einheitliche Sicht auf die Daten zu ermöglichen. Der GraphQL-Gateway würde dann nicht selbst die Daten (z.B. aus einer Datenbank) laden, sondern die vorhandenen REST-Endpunkte aufrufen und als Aggregationspunkt fungieren.
Man würde damit einem Client die Flexibilität von GraphQL zur Verfügung stellen und trotzdem die eigentlichen Services als RESTful Services belassen. Gerade bei Microservice-Architekturen kann diese Vorgehensweise durchaus sinnvoll sein.
Bei einem neuen Projekt kann man natürlich über den alleinigen Einsatz von GraphQL nachdenken. In diesem Fall würde ich die Entscheidung von der konkreten Problemstellung abhängig machen. Blind jedes Problem mit GraphQL zu lösen, halte ich nicht für den richtigen Ansatz.
Welche Erkenntnis sollte jeder Besucher deiner Session mit nach Hause nehmen?
Dass GraphQL ein interessanter Ansatz ist, aber auch nicht die Lösung für alle Probleme. Sehr oft suchen wir nach der Lösung für all unsere Probleme. Oft vergessen wir dabei vielleicht, auf das konkrete Problem einzugehen und manchmal landen wir dann an dem Punkt „Wir hatten zwar eine Lösung, aber sie passte nicht zum Problem“. Ich denke, dass die Verwendung von GraphQL sehr sinnvoll sein kann, aber dass es nicht alle unsere Probleme auf magische Weise löst.
Ich hoffe, dass bei meiner Session für REST-Liebhaber und -Gegner etwas dabei ist. Erstere können dann vielleicht die Session mit der Überzeugung verlassen, dass GraphQL nichts für sie ist und Letztere finden eventuell endlich das Tool ihrer Wahl.
In der täglichen Arbeit als Entwickler und Architekt muss man oft Entscheidungen für eine Technologie treffen. Wichtig ist nicht selten aber auch die fundierte Entscheidung gegen eine Technologie. Ich hoffe, dass meine Session etwas zur Entscheidungsfindung beitragen kann – für oder gegen GraphQL – beides ist ein legitimer und wichtiger Output.
Interviewt von: Dominik Mohilo
Dominik Mohilo studierte Germanistik und Soziologie an der Goethe-Universität in Frankfurt. Seit 2015 ist er Redakteur bei S&S-Media.