Eine der wichtigsten Entscheidungen, die wir Programmierer treffen müssen, wenn wir mit einem Projekt beginnen, ist die Auswahl einer Sprache oder einer Reihe von Sprachen, die zur Implementierung des Systems verwendet werden sollen. Diese Entscheidung betrifft nicht nur die Implementierung des Systems, sondern auch das Design. Sollten wir beispielsweise eine objektorientierte oder eine prozedurale Sprache verwenden? Welche Sprache wir wählen, hat einen tiefgreifenden Einfluss auf das Projekt und den Lebenszyklus des Programms, das Teil des Projekts ist. Oft entscheiden wir uns dafür, ohne darüber nachzudenken Zu sehr, basierend auf einigen sehr launischen Faktoren: Dies ist die Sprache, die ich normalerweise verwende, um diese Art von System zu implementieren. Dies ist meine Lieblingssprache und ich programmiere gerne in dieser Sprache.
Da diese Entscheidung tiefgreifende und langfristige Konsequenzen haben wird, sollten wir bei dieser Entscheidung pragmatischer sein. Oftmals werden wir blind voreingenommen sein durch die Sprache, die wir wählen. Und manchmal können die Gründe, warum wir diese Sprache nicht gerne wählen, genau die Gründe sein, warum wir uns für diese Sprache entscheiden.
Wenn wir uns öffnen und ehrlich zu unseren Vorurteilen sind, können wir den Schmerz etwas lindern, der entsteht, wenn wir beim Dekorieren versuchen, einen quadratischen Stift in ein rundes Loch zu stecken. Auch wenn es kein Geheimnis ist, die perfekte Sprache für ein Projekt auszuwählen, gibt es einige Grundsätze, die uns dabei helfen können, eine bessere und passendere Sprachwahl zu treffen.
Keine Sprache ist perfekt
Das kann man von jedem erwarten, sogar von einem Neuling, und viele von uns sind bereit zuzugeben: „Natürlich ist diese Sprache keine perfekte Sprache.“ Aber gleichzeitig würden viele von uns immer noch sagen: „Diese Sprache ist die beste Programmiersprache.“ Der Schlüssel zur Aussage, dass eine Sprache die beste Sprache für ein Projekt ist, ist der Kontext des Projekts, das heißt, die beste Sprache existiert nur innerhalb eines bestimmten Umfangs. Das ist unser erster Grundsatz:
Es gibt keine perfekte Sprache: Jede Sprache hat ihre Stärken und Schwächen.
Zum Beispiel behaupten viele Entwickler, die normalerweise Laufzeitsprachen wie Java oder Python verwenden, dass C oder C++ aufgrund von Bedenken hinsichtlich Details auf niedriger Ebene wie der Speicherverwaltung oder Bedenken hinsichtlich der strikten Granularität der Kompilierung atemlos sind -Zeitliche Typprüfung bei gleichzeitiger Unterdrückung der dezentral auf die Entwickler verteilten Verantwortlichkeiten. Dies gilt, solange sich das von uns entwickelte Projekt nicht auf scheinbar triviale Aufgaben wie die Speicherverwaltung oder die Anzahl der Kopierzuweisungen konzentriert, die in einer einzelnen Schleife erfolgen.
Im Gegenteil, wenn wir an einem Projekt oder einem Teil eines Projekts arbeiten, ist es natürlich, dass wir voreingenommene Anforderungen daran haben, wie effizient der Code sein sollte und wie kritisch und sicher das Programm ist, und diese scheinen langwierig zu sein Details sind möglicherweise genau das, woran wir arbeiten. Der Grad der Granularität, nach dem gesucht werden muss. In diesem neuen Kontext scheint der Laufzeitcharakter von Java oder Python zu gleichgültig oder zu geistesabwesend zu sein. Stattdessen möchten wir in der Lage sein, streng zu steuern, wie viele Verschiebungszuweisungen und Kopierzuweisungen ausgeführt werden, wenn Speicher zugewiesen und freigegeben wird, und so viele Fehler wie möglich zur Kompilierungszeit abzufangen, anstatt Fehler in die Laufzeit gelangen zu lassen (so zu verhalten). Laufzeit abnormal).
Während in der Theorie „keine Sprache ist perfekt“ offensichtlich klingt, weicht unser Verhalten als Entwickler oft von diesem Konzept ab: Wir sagen, wir wissen, dass unsere Lieblingssprachen unvollkommen sind, verwenden diese Sprache jedoch weiterhin für die Projekte Wir entwickeln, unabhängig davon, ob es geeignet ist. Wenn ein anderer Entwickler außerdem unsere Wahl der Sprache in Frage stellt, verteidigen wir unsere Wahl energisch, anstatt in seiner oder ihrer Widerlegung die Wahrheit zu erkennen. Denken Sie daran: Jede Sprache hat ihre Vor- und Nachteile. Verstehen Sie die Stärken und Schwächen der Sprachen, die Sie beherrschen, und treffen Sie dann Ihre Wahl basierend auf Ihrer Situation.
Der Grund, warum Sie eine Sprache nicht mögen, könnte der Grund sein, warum Sie sie verwenden sollten.
Es mag kontraintuitiv erscheinen, aber manchmal kann der Grund, warum wir eine Sprache nicht mögen, der Grund sein Sie sollten es verwenden. Aus sprachlichen Gründen. Was das obige Beispiel angeht: Nach meiner Erfahrung als C++-Entwickler dauert es oft zu lange, ein Projekt abzuschließen, weil so viele verschiedene Konzepte im Auge zu behalten sind (Speicherverwaltung und Objektlebensdauer, die drei Prinzipien der C++-Programmierung usw.). .) Eine einfache Funktion kann umständlich werden. Nach ein paar Wochen der Entwicklung in C++ kann sich die Verwendung von Python, Java oder einer anderen „höheren“ Sprache wie ein Geschenk des Himmels anfühlen: Aber ist das wirklich so?
Manchmal vielleicht sind die Gründe, warum wir eine Sprache nicht mögen, genau die Gründe wir nutzen es. Wenn ich einen Treiber oder ein sicherheitskritisches Echtzeitsystem entwickeln würde, wären die oben genannten Gründe für die Umständlichkeit möglicherweise der größte Vorteil dieser Sprache. C++ bietet beispielsweise einen Mechanismus zum Ausdruck der Logik, die beim Kopieren eines Objekts ausgeführt wird, was von unschätzbarem Wert ist, wenn Effizienz und Genauigkeit gefragt sind.
Das mag alles gut und großartig aussehen, daher ist es schwierig, einen Kontext zu identifizieren, in dem eine Sprache, die Sie nicht mögen, hilfreicher sein könnte. Woher wissen wir also, welche Sprachen, die Sie nicht mögen, hilfreich sind? Das führt uns zu unserem zweiten Prinzip:
Seien Sie ehrlich zu sich selbst: Wissen Sie, warum Sie eine Sprache nicht mögen, nicht Dogmatisieren Sie Ihren eigenen Hass.
Zum Beispiel liegt der Grund, warum ich im obigen C++-Beispiel lange Zeit nicht gerne in C++ programmiere, darin, dass diese Sprache strenges Denken erfordert, sonst ist es leicht, Fehler zu machen, genau wie in der Falle Dschungel (zu viel Fokus auf die Bäume statt auf den Wald als Ganzes). Diese Strenge verhindert, dass Entwickler Fragen stellen wie: „Erstelle ich Objekte auf dem Stapel oder auf dem Heap oder teilweise auf dem Stapel und teilweise auf dem Heap?“ oder „Um diese Klasse erweiterbar zu machen, sollte sie über Vorlagen erfolgen.“ oder Erbschaft?" und andere Entscheidungen. In anderen Sprachen können Entwickler diese Aufgaben erfüllen, indem sie einfach jeweils ein Objekt erstellen und die objektorientierte Vererbung verwenden und dann mit der nächsten Funktion fortfahren, da die Sprache (oder genauer gesagt der Compiler oder Interpreter) diese Aufgaben übernimmt. Detail.
Wenn ich jedoch ehrlich zu mir selbst bin, gebe ich zu, dass mir diese Funktionen von C++ nicht gefallen, weil es mir die Pflicht auferlegt, diese Details auszudrücken. In anderen Sprachen bin ich nicht nur nicht für diese Details verantwortlich, sondern habe auch nicht die Verantwortung, sie auszudrücken: Sie werden vom Entwickler abstrahiert. In einem Kontext, in dem diese Details wichtig sind, sind die Gründe, warum ich C++ nicht mag, genau die Gründe, warum ich diese Sprache verwenden sollte.
Bedeutet das, dass wir die Stirn runzeln und Funktionen verwenden sollten, die uns durch die Sprache irritieren? Vielleicht können Sie es anders sehen: Anstatt diese Funktionen als Nachteile zu betrachten, sollten wir sie vielleicht als Notwendigkeit betrachten, um die Arbeit zu erledigen. Anstatt zu sagen: „Was für eine Tragödie“, sollten wir sagen: „Gott sei Dank kann ich das in dieser Sprache tun.“ Denken Sie daran: In manchen Kontexten sind diese Fähigkeiten ein Geschenk, in anderen Fällen sind sie eine Belastung. Seien Sie ehrlich zu sich selbst und sagen Sie, warum Ihnen ein Merkmal einer Sprache nicht gefällt.
Je vertrauter Sie mit anderen Sprachen sind, desto besser
Hierfür ist hier unser dritter Grundsatz:
Wenn das einzige Werkzeug, das Sie haben, ein Hammer ist, dann Sie Sehen Sie, jedes Problem sieht aus wie ein Nagel.
Diese Regel gilt nicht für die Softwareentwicklung, charakterisiert jedoch viele Softwareentwicklungssituationen deutlich. Oft entscheiden wir uns für eine Sprache oder ein sprachunterstütztes Tool (wie JMS von Java, ASYNCIO von Python, Ruby von Rails usw.), weil wir wissen, dass es sie gibt. Wenn die einzige Sprache, mit der wir vertraut sind, Java ist, werden wir alle Probleme, auf die wir stoßen, an den Java-Kontext anpassen. Beispiel: „Ich muss ein Routing-Framework für eine Kommunikationsanwendung erstellen. Wie mache ich das in Java?“ Dadurch werden die uns zur Verfügung stehenden Tools eingeschränkt und unsere Fähigkeit, das richtige Tool für den Job auszuwählen, künstlich eingeschränkt.
Die Lösung für dieses Problem besteht darin, Ihren Horizont zu erweitern und die Fähigkeiten und Feinheiten anderer Sprachen zu verstehen. Wie Andrew Hunt und David Thomas in „The Pragmatic Programmer“ vorschlagen, besteht eine gute Praxis darin, jedes Jahr eine neue Sprache zu lernen. Es ist nicht so einfach, wie es klingt, und das Erlernen einer Sprache bedeutet für jeden Menschen etwas anderes. Ein weiteres abgeleitetes Problem besteht darin, dass wir diese eine Sprache oft nur für laufende Projekte verwenden, sodass das Erlernen einer anderen Sprache nutzlos ist. Wenn ich beispielsweise ein Android-Entwickler bin und im Grunde jeden Tag nur Java verwende, dann kann das Erlernen von C# wie eine vorzeitige Zeitverschwendung erscheinen.
Lassen Sie sich nicht von Illusionen täuschen. Der Vorteil des Erlernens einer anderen Sprache besteht darin, dass wir ein Problem aus einer anderen Perspektive betrachten und die Werkzeuge verwenden können, die für das Problem am besten geeignet sind. Dazu müssen wir die mit anderen Sprachen verbundenen Vorbehalte und die Art und Weise lernen, wie Entwickler diese Sprachen zur Lösung von Problemen verwenden. Wenn ein Entwickler beispielsweise Metaprogrammierung in C++ durchführen möchte, kann er oder sie Template Metaprogramming (TMP) in C++ verwenden, aber er oder sie kann auch Reflection in Java verwenden. Wenn wir verstehen, wie andere Sprachen ähnliche Probleme lösen, verringert sich das Risiko, dass wir sie für nutzlos halten.
Als weiteres Beispiel: Wenn wir in der Lage sein müssen, die Laufzeiteigenschaften einer Klasse zu ändern, könnte ein C++-Entwickler, der mit den Feinheiten von C++ bestens vertraut ist, versucht sein, eine Kompilierzeitsprache zu entwickeln, die die Klasse erweitert Grenzen dieser Lösung. Und ein anderer C++-Entwickler kann sagen, weil er auch ein gewisses Verständnis von Java hat: „Ich mag C++, aber die Laufzeitreflexion von Java ist besser geeignet, dieses Problem zu lösen.“
Aus diesem Grund gibt es so viele Programmierungen Bei der Auswahl der Sprachen, aus denen Entwickler wählen können, ist es wichtig, Prioritäten zu setzen, welche Sprachen gelernt werden sollen. Sie können heute genauso gut mit den beliebtesten Sprachen beginnen (siehe „Beliebteste Sprachen auf Github“, „Sprachtrends auf Github“, „Die 9 beliebtesten Computersprachen“, laut Facebook für Programmierer). ", usw.).
Sprache ist eher ein Mittel als ein Zweck
Dies ist das vierte und letzte Prinzip, das vielleicht am philosophischsten klingt, aber man kann es auch als das wichtigste bezeichnen:
Programmiersprachen sind ein Mittel, kein Zweck.
Sofern Sie nicht der Autor eines Sprachstandards oder eines Compilers sind, sollten Sie Programmiersprachen als Mittel und nicht als Zweck betrachten. Das Ziel besteht darin, das Projekt abzuschließen: Das ultimative Ziel ist es, das Projekt abzuschließen, und nicht eine bestimmte Sprache verwenden. Das bedeutet nicht, dass nicht jeder Entwickler das Recht hat zu verlangen, was ihm oder ihr an der Sprache gefällt oder nicht gefällt (tatsächlich können diese Vorlieben und Abneigungen, wenn wir ehrlich zu uns selbst sind, zu unseren Gunsten wirken; siehe (das zweite Prinzip oben), aber wir sollten uns nicht selbst täuschen und Entscheidungen treffen wie: „Das ist eine großartige Gelegenheit für mich, diese Funktion der Sprache zu nutzen“, es sei denn, die Funktionen der Sprache passen wirklich zu den Anforderungen des Projekts.
Es ist wichtig, sich daran zu erinnern, dass Sprache nur eine Möglichkeit ist, auszudrücken, wie das vorliegende Problem gelöst werden kann: Stellen Sie sicher, dass Sie die Sprache wählen, die den Problembereich, den Sie lösen, am besten ausdrückt.
Andere Dinge, die es zu beachten gilt
Hier sind einige Dinge, die wir bei der Auswahl einer Sprache berücksichtigen müssen:
Überlegen Sie, wie die Sprache mit anderen Sprachen interagiert. Wenn Sie beispielsweise entscheiden, dass Python die beste Sprache für die meisten Projekte ist, Ihr Projekt jedoch eine klar definierte Komponente enthält, die ein extrem hohes Maß an Granularität oder Effizienz erfordert (was besser für C oder C++ geeignet wäre), dann ist dies der Fall bedeutet nicht, dass Sie Python für dieses Projekt nicht verwenden können. Erwägen Sie stattdessen die Verwendung von Python, das Schreiben einer bestimmten Komponente in C oder C++ und die Verwendung der Python-C-API als Schnittstelle zu dieser Komponente. Beachten Sie, dass wir zum Formulieren einer solchen Lösung wissen müssen, dass Python über eine C-API verfügt. Daher ist es hilfreich, diese Funktionen der gängigsten Sprachen zu kennen.
Middleware kann die Verwendung mehrerer Sprachen ermöglichen. Wenn Sie beispielsweise über zwei Anwendungen verfügen, die kommunizieren müssen, beispielsweise ein mobiles Gerät und eine Serveranwendung, bedeutet dies nicht, dass sie dieselbe Sprache verwenden müssen (natürlich können sie dieselbe Sprache sein, wenn Sie entscheiden, dass dies die beste Entscheidung ist). . Wenn es sich bei dem Mobilgerät um ein Android-Telefon handelt und die Serveranwendung perfekt als Python-Anwendung geeignet ist, können Sie mit einem Nachrichtenbroker wie RabbitMQ gleichzeitig in beiden Sprachen kommunizieren: Die Android-Anwendung kann die Java RabbitMQ-API verwenden , während Serveranwendungen die Python RabbitMQ-API verwenden können.
Nehmen Sie die Eigenheiten anderer Sprachen an. Wenn Sie ein Java-Entwickler sind, verwenden Sie Pakete, um logische Einheiten des Quellcodes zu trennen. Wenn Sie ein Python-Entwickler sind, verwenden Sie die Paketstruktur von Python, um dasselbe zu tun würde einen Namespace verwenden oder dem Klassennamen ein Präfix voranstellen (z. B. „DZone_MyClassName“). Verstehen Sie die Besonderheiten der Sprache, die Sie sprechen, und nehmen Sie sie an: Machen Sie es in Rom wie die Römer. Andernfalls wäre es so, als würde man Deutsch mit italienischem Akzent sprechen, weil man die italienische Aussprache von Wörtern bevorzugt, die unscheinbar klingen würde. Natürlich ist es auch möglich, dass ein Merkmal einer Sprache schon seit langem existiert, aber in diesem Fall muss es einen Grund geben: Stellen Sie sicher, dass Sie den Grund verstehen.