Der Wechsel zu einer neuen Sprache kann eine gewaltige Aufgabe sein. Das Erfolgsrezept besteht darin, langsam anzufangen, in Blöcken aufzuteilen und häufig zu testen, um Ihr Team auf Erfolgskurs zu bringen. Kotlin erleichtert die Migration, da es zu JVM-Bytecode kompiliert wird und vollständig interoperabel mit Java ist.
Aufbau des Teams
Der erste Schritt vor der Migration besteht darin, ein gemeinsames Grundverständnis für Ihr Team aufzubauen. Hier sind einige Tipps, die Ihnen helfen können, das Lernen Ihres Teams zu beschleunigen.
Lerngruppen
Lerngruppen sind ein effektives Mittel, um das Lernen und die Bindung zu fördern. Studien zufolge wird das Gelernte in einer Gruppenumgebung festgehalten, um das Gelernte zu untermauern. Laden Sie für jedes Gruppenmitglied ein Kotlin-Buch oder anderes Lernmaterial herunter und bitten Sie die Gruppe, jede Woche ein paar Kapitel durchzugehen. Bei jedem Meeting sollte die Gruppe das Gelernte vergleichen und eventuelle Fragen oder Beobachtungen besprechen.
Eine Lehrkultur schaffen
Nicht jeder sieht sich selbst als Lehrer an, doch jeder kann unterrichten. Von einer Technologie oder einem Team, das zu einem einzelnen Mitwirkenden führt, kann jeder eine Lernumgebung schaffen, die zum Erfolg beitragen kann. Eine Möglichkeit dafür sind regelmäßige Präsentationen, bei denen eine Person im Team über das Gelernte sprechen oder darüber sprechen möchte. Sie können Ihre Studiengruppe nutzen, indem Sie Freiwillige bitten, jede Woche ein neues Kapitel vorzutragen, bis Sie an einem Punkt sind, an dem Ihr Team mit der Sprache vertraut ist.
Einen Champion ernennen
Legen Sie schließlich einen Champion fest, der die Lernleistung leitet. Diese Person kann als Fachleute fungieren, die Ihnen bei der Einführung helfen. Es ist wichtig, diese Person in alle Ihre Übungsmeetings zu Kotlin einzubeziehen. Im Idealfall begeistert sich diese Person bereits für Kotlin und verfügt über einige Arbeitskenntnisse.
Langsam integrieren
Es ist wichtig, langsam anzufangen und strategisch darüber nachzudenken, welche Teile Ihres Ökosystems zuerst zu tun sein sollten. Es ist oft am besten, dies auf eine einzelne Anwendung innerhalb Ihrer Organisation und nicht auf eine Flagship-Anwendung zu beschränken. In Bezug auf die Migration der ausgewählten Anwendung ist jede Situation anders, aber hier sind einige gängige Methoden, mit denen Sie beginnen können.
Datenmodell
Ihr Datenmodell besteht wahrscheinlich aus vielen Statusinformationen und einigen Methoden. Das Datenmodell kann auch gängige Methoden wie toString()
, equals()
und hashcode()
enthalten. Diese Methoden können in der Regel ganz einfach umgestellt und Einheiten getestet werden.
Nehmen wir zum Beispiel das folgende Java-Snippet:
public class Person {
private String firstName;
private String lastName;
// ...
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(lastName, person.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
Sie können die Java-Klasse wie hier gezeigt durch eine einzelne Zeile von Kotlin ersetzen:
data class Person(var firstName: String?, var lastName : String?)
Dieser Code kann dann mit deiner aktuellen Testsuite getestet werden. Die Idee hierbei ist, klein mit einem Modell nach dem anderen zu beginnen und Klassen zu wechseln, die größtenteils Status und kein Verhalten sind. Führen Sie während des Tests regelmäßig Tests durch.
Tests migrieren
Eine weitere mögliche Option ist die Konvertierung vorhandener Tests und das Schreiben neuer Tests in Kotlin. So hat Ihr Team Zeit, sich mit der Sprache vertraut zu machen, bevor es Code schreibt, den Sie mit Ihrer App ausliefern möchten.
Dienstprogrammmethoden in Erweiterungsfunktionen verschieben
Alle statischen Dienstprogrammklassen (StringUtils
, IntegerUtils
, DateUtils
, YourCustomTypeUtils
usw.) können als Kotlin-Erweiterungsfunktionen dargestellt und von Ihrer vorhandenen Java-Codebasis verwendet werden.
Angenommen, Sie haben eine StringUtils
-Klasse mit mehreren Methoden:
package com.java.project;
public class StringUtils {
public static String foo(String receiver) {
return receiver...; // Transform the receiver in some way
}
public static String bar(String receiver) {
return receiver...; // Transform the receiver in some way
}
}
Diese Methoden können dann an anderer Stelle in Ihrer Anwendung verwendet werden, wie im folgenden Beispiel gezeigt:
...
String myString = ...
String fooString = StringUtils.foo(myString);
...
Mit Kotlin-Erweiterungsfunktionen können Sie Java-Aufrufern die gleiche Utils
-Schnittstelle bieten und gleichzeitig eine kürzere API für Ihre wachsende Kotlin-Codebasis bereitstellen.
Dazu könnten Sie diese Utils
-Klasse mithilfe der automatischen Konvertierung der IDE in Kotlin umwandeln. Die Beispielausgabe könnte etwa so aussehen:
package com.java.project
object StringUtils {
fun foo(receiver: String): String {
return receiver...; // Transform the receiver in some way
}
fun bar(receiver: String): String {
return receiver...; // Transform the receiver in some way
}
}
Entfernen Sie als Nächstes die Klassen- oder Objektdefinition, stellen Sie jedem Funktionsnamen den Typ voran, auf den diese Funktion angewendet werden soll, und verweisen Sie damit auf den Typ innerhalb der Funktion, wie im folgenden Beispiel gezeigt:
package com.java.project
fun String.foo(): String {
return this...; // Transform the receiver in some way
}
fun String.bar(): String {
return this...; // Transform the receiver in some way
}
Zum Schluss fügen Sie am Anfang der Quelldatei eine JvmName
-Annotation hinzu, damit der kompilierte Name mit dem Rest Ihrer Anwendung kompatibel ist, wie im folgenden Beispiel gezeigt:
@file:JvmName("StringUtils")
package com.java.project
...
Die endgültige Version sollte in etwa so aussehen:
@file:JvmName("StringUtils")
package com.java.project
fun String.foo(): String {
return this...; // Transform `this` string in some way
}
fun String.bar(): String {
return this...; // Transform `this` string in some way
}
Diese Funktionen können jetzt mit Java oder Kotlin mit Konventionen aufgerufen werden, die jeder Sprache entsprechen.
Kotlin
... val myString: String = ... val fooString = myString.foo() ...
Java
... String myString = ... String fooString = StringUtils.foo(myString); ...
Migration abschließen
Sobald Ihr Team mit Kotlin vertraut ist und Sie kleinere Bereiche migriert haben, können Sie mit größeren Komponenten wie Fragmenten, Aktivitäten, ViewModel
-Objekten und anderen Klassen im Zusammenhang mit der Geschäftslogik fortfahren.
Wissenswertes
Ähnlich wie Java über einen speziellen Stil verfügt Kotlin über einen eigenen idiomatischen Stil, der zu seiner Präzision beiträgt. Vielleicht stellen Sie jedoch anfangs fest, dass der Kotlin-Code, den Ihr Team erstellt, eher dem Java-Code ähnelt, den es ersetzt. Das ändert sich mit der Zeit, wenn Ihr Team immer mehr Erfahrung mit Kotlin hat. Denken Sie daran, dass schrittweise Änderungen der Schlüssel zum Erfolg sind.
Hier sind einige Dinge, die Sie tun können, um Konsistenz zu erreichen, wenn Ihre Kotlin-Codebasis größer wird:
Gängige Programmierstandards
Definieren Sie frühzeitig im Einführungsprozess einen Standardsatz von Codierungskonventionen. Wo es sinnvoll ist, können Sie vom Kotlin-Styleguide für Android abweichen.
Statische Analysetools
Mit Android Lint und anderen statischen Analysetools können Sie die Coding-Standards für Ihr Team erzwingen. klint, ein Kotlin-Linter eines Drittanbieters, bietet zusätzliche Regeln für Kotlin.
Kontinuierliche Integration
Achten Sie darauf, die gängigen Codierungsstandards zu erfüllen, und bieten Sie genügend Testabdeckung für Ihren Kotlin-Code. Wenn Sie dies in einen automatisierten Build-Prozess einbinden, können Sie Konsistenz und Einhaltung dieser Standards gewährleisten.
Interoperabilität
Kotlin funktioniert größtenteils nahtlos mit Java. Beachten Sie jedoch Folgendes:
Null-Zulässigkeit
Kotlin stützt sich auf Annotationen zur Null-Zulässigkeit in kompiliertem Code, um die Null-Zulässigkeit auf der Kotlin-Seite abzuleiten. Wenn keine Annotationen vorhanden sind, verwendet Kotlin standardmäßig einen Plattformtyp, der als Typ mit Null- oder Null-Zulässigkeit behandelt werden kann. Dies kann jedoch zu NullPointerException
-Laufzeitproblemen führen, wenn dies nicht sorgfältig behandelt wird.
Neue Funktionen einführen
Kotlin bietet viele neue Bibliotheken und syntaktischen Zucker, um den Boilerplate-Standard zu reduzieren und so die Entwicklungsgeschwindigkeit zu erhöhen. Seien Sie jedoch vorsichtig und methodisch, wenn Sie die Standardbibliotheksfunktionen von Kotlin wie Erfassungsfunktionen, Koroutinen und Lambdas verwenden.
Hier ist ein häufiger Fehler, auf den neuere Kotlin-Entwickler stoßen. Angenommen, der folgende Kotlin-Code lautet:
val nullableFoo: Foo? = ...
// This lambda executes only if nullableFoo is not null
// and `foo` is of the non-nullable Foo type
nullableFoo?.let { foo ->
foo.baz()
foo.zap()
}
In diesem Beispiel werden foo.baz()
und foo.zap()
ausgeführt, wenn nullableFoo
nicht null ist. So wird ein NullPointerException
vermieden. Dieser Code funktioniert zwar wie erwartet, ist aber weniger intuitiv zu lesen als eine einfache Nullprüfung und Smart Cast, wie im folgenden Beispiel gezeigt:
val nullableFoo: Foo? = null
if (nullableFoo != null) {
nullableFoo.baz() // Using !! or ?. isn't required; the Kotlin compiler infers non-nullability
nullableFoo.zap() // from guard condition; smart casts nullableFoo to Foo inside this block
}
Testen
Klassen und ihre Funktionen sind in Kotlin standardmäßig für Erweiterungen geschlossen. Sie müssen die Klassen und Funktionen, für die Sie abgeleitete Klassen erstellen möchten, explizit öffnen. Dieses Verhalten ist eine Entscheidung bezüglich des Sprachdesigns, mit der die Komposition gegenüber Vererbung gefördert werden soll. Kotlin unterstützt die Delegierung, um die Zusammensetzung zu vereinfachen.
Dies stellt ein Problem bei Mocking-Frameworks wie Mockito dar, bei denen eine Schnittstellenimplementierung oder eine Übernahme erforderlich ist, um das Verhalten während des Tests zu überschreiben. Für Unittests können Sie die Mock Maker Inline-Funktion von Mockito aktivieren, um endgültige Klassen und Methoden zu simulieren. Alternativ können Sie das All-Open-Compiler-Plug-in verwenden, um eine Kotlin-Klasse und ihre Mitglieder zu öffnen, die Sie im Rahmen der Kompilierung testen möchten. Der Hauptvorteil dieses Plug-ins besteht darin, dass es sowohl mit Einheitentests als auch mit instrumentierten Tests funktioniert.
Weitere Informationen
Weitere Informationen zur Verwendung von Kotlin finden Sie unter den folgenden Links:
- Der Kotlin-Ansatz von Android
- Ressourcen für die ersten Schritte mit Kotlin
- Ressourcen für Java-Nutzer, die Kotlin lernen
- Lernpfad von Java zu Kotlin mit einer Sammlung von Ressourcen, die Java-Programmierern helfen, idiomatischen Kotlin-Code zu schreiben und zu erlernen.