
Teilen Sie:
Karl ist Developer Advocate bei Vonage und kümmert sich um die Wartung unserer Ruby Server SDKs und die Verbesserung der Entwicklererfahrung für unsere Community. Er liebt es zu lernen, Dinge zu entwickeln, Wissen zu teilen und alles, was allgemein mit Webtechnologie zu tun hat.
Arbeit in einem mehrsprachigen Team
Lesedauer: 7 Minuten
Als Entwickler, die in einem Team arbeiten, sind wir oft daran gewöhnt, dass alle Teammitglieder mit denselben Sprachen, demselben technischen Stack und denselben Tools vertraut sind. Je nach Kontext kann das bedeuten, dass man mit mehr als einer Programmiersprache arbeitet.
Wenn Sie am Frontend arbeiten, müssen Sie wahrscheinlich HTML, CSS und JavaScript "sprechen". In einem Full-Stack-Kontext können Sie auch eine beliebige Anzahl von Back-End-Programmiersprachen hinzufügen. Unabhängig von jeglicher Spezialisierung oder Fokussierung auf einen bestimmten Teil des Stacks verfügen die Entwickler in einem solchen Team über ein gemeinsames technisches Vokabular und einen gemeinsamen Bezugsrahmen, der durch den verwendeten Tech-Stack definiert ist. Seit ich dem Developer Relations Team bei Vonage beigetreten bin, musste ich mich jedoch an eine ganz andere Realität gewöhnen als die, die ich gerade beschrieben habe.
Eines der Hauptziele unseres Teams ist es, Entwicklern bei der Nutzung der zahlreichen Kommunikations-APIs von Vonage zu helfen und sie zu unterstützen. Eine Möglichkeit, dies zu tun, ist die Bereitstellung von SDKs, die einen Teil der Komplexität der APIs abstrahieren, um sie einfacher in eine Anwendung zu integrieren. Die Entwickler, die die APIs von Vonage nutzen, tun dies natürlich mit einer Vielzahl von Programmiersprachen und technischen Stacks. Daher bieten wir SDKs für viele verschiedene Sprachimplementierungen und Umgebungen: Server-SDKs für Ruby, PHP, Python, Java, Node und .net; Client-SDKs für JavaScript, iOS und Android.
Als Ruby Developer Advocate des Teams besteht ein Teil meiner Aufgabe in der Pflege und Verbesserung unserer Ruby-SDKs. Wenn ich einen Fehler beheben oder eine Funktion hinzufügen muss, schreibe ich dazu Ruby-Code. Meine Teamkollegen schreiben jedoch keinen Ruby-Code. Stattdessen schreiben sie PHP, Python oder C#. Es kann sein, dass wir zwar an der Implementierung der gleichen Funktion arbeiten, aber in völlig unterschiedlichen Sprachen.
Ich denke, dass meine JavaScript-Kenntnisse ziemlich gut sind, aber es ist nicht meine Hauptsprache. Ich habe in der Vergangenheit etwas PHP geschrieben (obwohl unser PHP-Befürworter Jim mir versichert, dass sich die Sprache seitdem sehr verändert hat!) und kenne ein wenig Python, aber ich würde mich in keiner dieser Sprachen als Experte bezeichnen, und ich fühle mich definitiv am wohlsten, wenn ich mit Ruby-Code arbeite.
Wenn ich aber ein gutes Teammitglied sein und meine Kollegen bei ihrer Arbeit unterstützen will, muss ich mich gelegentlich außerhalb meiner Ruby-Komfortzone bewegen.
In den etwa sieben Monaten, seit ich dem Team beigetreten bin, habe ich mich dabei ertappt, wie ich für Kollegen, die an Fehlern oder Funktionen für ihre (Nicht-Ruby-) SDKs arbeiten, als Gesprächspartner oder zweites Paar Augen fungiere. Ich habe geholfen, Pull Requests für die PHP-, Python- und .net-Bibliotheken zu prüfen. Ich habe sogar einige kleine Commits in eines der Python-Repos eingebracht.
Sich (manchmal) unbequem zu fühlen, ist eigentlich gut
Die Arbeit in einem mehrsprachigen Team kann durchaus einige Herausforderungen mit sich bringen. Ich möchte jedoch darauf hinweisen, dass sie auch viele Vorteile mit sich bringt.
Als Entwickler streben wir danach, unser Handwerk zu beherrschen. Wir bauen unser Fachwissen so weit auf, dass wir uns in einem bestimmten Wissensbereich wohl fühlen. Der Aufbau dieser "Wissens-Komfortzone" bringt viele Vorteile mit sich - wir können selbstbewusst, schnell und effizient arbeiten, ohne ständig Dinge nachprüfen oder nachschlagen zu müssen. Auf der anderen Seite kann es uns aber auch faul machen und zu Annahmen verleiten. Wenn wir mit einem neuen Problem oder einer neuen Situation konfrontiert werden, können wir manchmal auf vertraute Muster zurückgreifen und denken, dass wir die Lösung bereits kennen, ohne klar über das Problem nachzudenken.
Im Zen-Buddhismus gibt es ein Konzept namens Shoshinwas übersetzt so viel wie "Geist des Anfängers" bedeutet. Es bezieht sich im Wesentlichen auf die Idee, offen für Möglichkeiten und ohne Vorurteile zu sein, wenn man ein Thema studiert oder sich einem neuen Problem nähert. Die Aneignung von Fachwissen lässt den "Anfängergeist" verschwinden, aber gelegentliches Verlassen der eigenen sprachlichen Komfortzone kann helfen, ihn wiederherzustellen.
Wenn ich zum Beispiel an einer Funktion für eine der Ruby-Bibliotheken arbeite und darüber in einem reinen Ruby-Kontext nachdenke, kann ich in die schlechte Angewohnheit verfallen, mich nur auf die Lösung zu konzentrieren und nicht klar über das Problem nachzudenken. Wenn ich jedoch dieselbe Funktion mit Kollegen in einem PHP- oder Python-Kontext diskutiere, bin ich gezwungen, alle Ruby-spezifischen Annahmen über die Lösung abzulegen und mich stattdessen auf das Problem zu konzentrieren.
Die tägliche Zusammenarbeit mit Entwicklern aus anderen Sprachräumen räumt nicht nur mit Vorurteilen auf, sondern kann auch Ihren Horizont auf andere Weise erweitern. Es öffnet Sie für andere Ansätze und Vorgehensweisen und letztlich auch für andere Denkweisen.
Es gibt eine linguistische Theorie, die als Linguistische Relativität oder die Sapir-Whorf-Hypothese. Diese Theorie besagt, dass die Struktur einer Sprache beeinflussen kann, wie wir denken und wie wir die Welt sehen. Diese Theorie wurde mit Blick auf menschliche Sprachen und nicht auf Programmiersprachen entwickelt. Da Programmiersprachen jedoch von Menschen entworfen werden, kann dieselbe Theorie angewandt werden.
Das Design von Programmiersprachen kann bestimmte Orthodoxien darüber schaffen, wie Software geschrieben werden sollte. Sprachen können stark oder schwach typisiert sein. Bestimmte Sprachen eignen sich für einen imperativen Ansatz, andere für einen deklarativen. Sprachmerkmale wie diese können dazu führen, dass man beim Schreiben von Code auf eine bestimmte Art und Weise denkt.
Wenn man nur eine bestimmte Art zu denken kennt, kann man in die Falle tappen und glauben, dass diese Art die richtige ist. Die Erfahrung mit verschiedenen Sprachen und Ansätzen öffnet Sie für die verschiedenen Denkweisen, die das Design dieser Sprachen nahelegt. Es kann Ihnen zeigen, dass es nicht unbedingt einen "richtigen" Weg gibt, sondern nur verschiedene "Wege", jeder mit seinen eigenen Kompromissen.
Obwohl Ruby beispielsweise schon immer eine dynamisch typisierte Sprache war (und auch heute noch standardmäßig ist), haben wir jetzt die Möglichkeit, eine statische Typüberprüfung in unsere Ruby-Programme einzuführen. Bibliotheken wie Sorbet gibt es schon seit einigen Jahren, und mit Ruby 3 wurde diese Option nun auch nativ eingeführt. Denkweise in einer statisch typisierten Weise zu denken, ist den meisten Ruby-Entwicklern wahrscheinlich immer noch etwas fremd, und wir können viel lernen, wenn wir uns Code in einer statisch typisierten Sprache wie C# ansehen.
private static void ValidSmsResponse(SendSmsResponse smsResponse)Wenn wir uns eine Methodensignatur in einer uns unbekannten Sprache wie dieser ansehen, haben wir keine vorgefassten Meinungen über die Sprache. Um zu verstehen, was der Code tut, müssen wir uns fragen was wozu jedes Element der Signatur dient und warum es so geschrieben wurde. Wir können aus diesem Prozess lernen und das Gelernte in unseren Ruby-Code einfließen lassen.
Lernpunkte und Tipps
In den letzten Monaten habe ich einige hilfreiche Ansätze für die Arbeit in einem mehrsprachigen Team kennengelernt, von denen ich hier nur einige vorstellen möchte.
Herauszoomen, um den Kontext herzustellen
Vor einigen Monaten arbeitete Jim an der Abschaffung und Entfernung verschiedener Traits aus einer der PHP-Bibliotheken und brauchte jemanden, der ihm die Änderungen an der Codebasis erläutert, die er vornahm. Zu Beginn unseres Gesprächs verlor ich mich ein wenig in den Untiefen der PHP-spezifischen Syntax. Was in dieser Situation wirklich geholfen hat, war, herauszuzoomen und die Änderungen auf einer höheren Abstraktionsebene zu besprechen. Anstatt darüber nachzudenken, was eine bestimmte Codezeile bewirkt, war es einfacher, den Kontext der Änderungen zu verstehen, indem man Dinge wie "Was ist der Zweck dieses Traits?", "Welche Beziehung besteht zwischen diesen Klassen? Wenn man erst einmal einen klaren Kontext für die Funktionsweise eines unbekannten Codes gefunden hat, ist es viel einfacher, sich in die Details der Implementierung zu vertiefen.
Mentale Modelle wiederverwenden
Eine weitere Möglichkeit, die sich als nützlich erweisen kann, wenn man sich auf unbekanntes Terrain begibt, ist die Wiederverwendung oder Umwidmung bestehender mentaler Modelle. Während unserer Lernreise als Programmierer haben wir alle viel Zeit damit verbracht, solide mentale Modelle für die zahlreichen technischen Konzepte zu entwickeln, mit denen wir arbeiten. Die gute Nachricht ist, dass viele dieser Modelle im Kontext anderer Programmiersprachen wiederverwendet oder umfunktioniert werden können.
Ein Beispiel ist der Versuch, einem Nicht-Ruby-Entwickler etwas wie Ruby-Blöcke zu erklären. Syntaktisch gesehen sind Blöcke eine Besonderheit der Sprache Ruby, aber wenn ich einem JavaScript-Entwickler erklären muss, was sie sind, kann ich sagen: "Sie funktionieren ähnlich wie Callback-Funktionen". Sicherlich sind sie nicht dasselbe, wenn man in die Details der Sprachimplementierung einsteigt, aber als allgemeines mentales Modell, um zu erklären, was sie tun und wie sie verwendet werden, ist es wahrscheinlich nahe genug.
Konzeptionell ist die Übergabe eines Blocks an map in Ruby:
[1, 2, 3].map do |num|
num + 1
endunterscheidet sich eigentlich nicht so sehr von der Übergabe einer Callback-Funktion an map in JavaScript:
[1, 2, 3].map(function(num) {
return num + 1;
});Je nach unserer syntaktischen Wahl in beiden Sprachen könnten sie sogar aussehen ziemlich ähnlich aussehen:
# Ruby
[1, 2, 3].map { |num| num + 1 }// JavaScript
[1, 2, 3].map(num => num + 1)
Gemeinsamkeiten erkennen, um Unterschiede zu verstehen
Eine weitere Möglichkeit, dieses Thema aufzugreifen, ist die Suche nach den Gemeinsamkeiten zwischen verschiedenen Sprachen und Technologiepaketen. Ich erwähnte bereits die Vorteile, die sich aus der Erforschung und Offenheit für die verschiedenen Ansätze ergeben, die Programmiersprachen verfolgen können. Letzten Endes zielen diese Sprachen und die um sie herum gebauten Werkzeuge jedoch im Allgemeinen darauf ab, dieselben Probleme zu lösen.
So gibt es beispielsweise für die meisten Programmiersprachen Testbibliotheken. Die Syntax, die sie verwenden, ist von Sprache zu Sprache unterschiedlich; einige, wie RSpec, verwenden sogar eine eigene DSL. Letztendlich lösen aber alle Testbibliotheken das gleiche Problem. Im Allgemeinen verwenden sie alle in irgendeiner Weise Assertions.
Minitest und PyTest sind beides Testbibliotheken, eine für Ruby und die andere für Python. Die Identifizierung der Ähnlichkeiten zwischen den beiden Bibliotheken kann einen Grundkontext liefern, der dann helfen kann, die interessanten Unterschiede in der Funktionsweise oder der Implementierung aufzuzeigen.
Eine Welt jenseits von Ruby
Ich denke, was ich damit sagen will, ist, dass es zwar verlockend sein kann, in seiner Komfortzone zu bleiben und bei dem zu bleiben, was man gewohnt ist, aber was ich in den letzten Monaten erlebt habe, hat mich daran erinnert, dass es eine ganze weite Welt voller lebendiger und interessanter Dinge gibt, die in anderen Sprachen als Ruby passieren. Ich liebe Ruby und habe sicher nicht vor, es als meine Hauptsprache aufzugeben, aber ich freue mich sehr darauf, in einige dieser anderen Sprachen einzutauchen und sie weiter zu erforschen.
Teilen Sie:
Karl ist Developer Advocate bei Vonage und kümmert sich um die Wartung unserer Ruby Server SDKs und die Verbesserung der Entwicklererfahrung für unsere Community. Er liebt es zu lernen, Dinge zu entwickeln, Wissen zu teilen und alles, was allgemein mit Webtechnologie zu tun hat.