Der Wechsel zu einer neuen Sprache kann eine Herausforderung sein. Damit Ihr Team erfolgreich ist, sollten Sie langsam beginnen, in kleinen Schritten migrieren und häufig testen. Kotlin wird zu JVM-Bytecode kompiliert und ist vollständig mit Java kompatibel, was die Migration erleichtert.
Team aufbauen
Der erste Schritt vor der Migration besteht darin, ein gemeinsames grundlegendes Verständnis für Ihr Team zu schaffen. Hier sind einige Tipps, die Ihnen helfen können, das Lernen Ihres Teams zu beschleunigen.
Lerngruppen bilden
Lerngruppen sind eine effektive Möglichkeit, das Lernen und Behalten von Informationen zu erleichtern. Studien haben gezeigt dass das Wiederholen des Gelernten in einer Gruppe dazu beiträgt, das Material zu festigen. Besorgen Sie für jedes Mitglied der Gruppe ein Kotlin-Buch oder anderes Lernmaterial und bitten Sie die Gruppe, jede Woche ein paar Kapitel durchzugehen. Bei jedem Treffen sollte die Gruppe vergleichen, was sie gelernt hat, und alle Fragen oder Beobachtungen besprechen.
Eine Kultur des Lehrens schaffen
Nicht jeder sieht sich als Lehrer, aber jeder kann lehren. Von einem Technologie- oder Teamleiter bis hin zu einem einzelnen Mitarbeiter kann jeder ein Lernumfeld fördern, das zum Erfolg beitragen kann. Eine Möglichkeit, dies zu erleichtern, sind regelmäßige Präsentationen, bei denen eine Person im Team über etwas spricht, das sie gelernt hat oder teilen möchte. Sie können Ihre Lerngruppe nutzen, indem Sie Freiwillige bitten, jede Woche ein neues Kapitel zu präsentieren, bis sich Ihr Team mit der Sprache vertraut fühlt.
Champion benennen
Benennen Sie einen Champion, der die Lernbemühungen leitet. Diese Person kann als Fachexperte fungieren, wenn Sie mit der Einführung beginnen. Es ist wichtig, diese Person in alle Übungstreffen zu Kotlin einzubeziehen. Im Idealfall ist diese Person bereits von Kotlin begeistert und verfügt über einige praktische Kenntnisse.
Langsam integrieren
Es ist wichtig, langsam zu beginnen und strategisch zu überlegen, welche Teile Ihres Ökosystems zuerst migriert werden sollen. Oft ist es am besten, dies auf eine einzelne App in Ihrem Unternehmen zu beschränken, anstatt eine Flaggschiff-App zu verwenden. Was die Migration der ausgewählten App betrifft, ist jede Situation anders. Hier sind jedoch einige gängige Ausgangspunkte.
Datenmodell
Ihr Datenmodell besteht wahrscheinlich aus vielen Statusinformationen und einigen Methoden. Das Datenmodell kann auch allgemeine Methoden wie toString, equals und hashCode enthalten. Normalerweise können Sie diese Methoden migrieren und isoliert testen.
Nehmen wir zum Beispiel das folgende Java-Snippet an:
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 durch eine einzelne Zeile Kotlin ersetzen, wie im folgenden Beispiel gezeigt:
data class Person(var firstName: String?, var lastName: String?)
Anschließend können Sie diesen Code mit Ihrer aktuellen Testsuite testen. Beginnen Sie mit einem Modell nach dem anderen und migrieren Sie Klassen, die hauptsächlich Status und nicht Verhalten enthalten. Testen Sie häufig.
Tests migrieren
Ein weiterer Ausgangspunkt sind Ihre Tests: Konvertieren Sie vorhandene Tests und schreiben Sie neue Tests in Kotlin. So hat Ihr Team Zeit, sich mit der Sprache vertraut zu machen, bevor Sie Code schreiben, der mit Ihrer App ausgeliefert wird.
Hilfsmethoden in Erweiterungsfunktionen verschieben
Sie können statische Hilfsklassen wie StringUtils,
IntegerUtils, DateUtils, oder YourCustomTypeUtils, als
Kotlin-Erweiterungsfunktionen
darstellen und sie in Ihrer vorhandenen Java-Codebasis verwenden.
Nehmen wir an, Sie haben eine StringUtils-Klasse mit einigen 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 App verwendet werden, wie im folgenden Beispiel gezeigt:
...
String myString = ...
String fooString = StringUtils.foo(myString);
...
Mit Kotlin-Erweiterungsfunktionen können Sie Java-Aufrufern dieselbe Utils-Schnittstelle zur Verfügung stellen und gleichzeitig eine prägnantere API für Ihre wachsende Kotlin-Codebasis anbieten.
Dazu können Sie diese Utils-Klasse zuerst mit der automatischen Konvertierung der IDE in Kotlin konvertieren. Die Beispielausgabe könnte 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 verwenden Sie ihn, um auf den Typ innerhalb der Funktion zu verweisen, 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
}
Fügen Sie schließlich oben in der Quelldatei eine JvmName-Annotation hinzu, damit der kompilierte Name mit dem Rest Ihrer App kompatibel ist, wie im folgenden Beispiel gezeigt:
@file:JvmName("StringUtils")
package com.java.project
...
Die endgültige Version sollte 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
}
Beachten Sie, dass diese Funktionen jetzt mit Java oder Kotlin mit Konventionen aufgerufen werden können, die der jeweiligen Sprache entsprechen.
Kotlin
// ... val myString: String = "hello" val fooString = myString.foo() // ...
Java
... String myString = ... String fooString = StringUtils.foo(myString); ...
Migration abschließen
Wenn sich Ihr Team mit Kotlin vertraut gemacht hat und Sie kleinere Bereiche migriert haben, können Sie zu größeren Komponenten wie Fragmenten, Aktivitäten, ViewModel-Objekten und anderen Klassen im Zusammenhang mit der Geschäftslogik übergehen.
Hinweise
So wie Java einen bestimmten Stil hat, hat Kotlin einen eigenen idiomatischen Stil, der zu seiner Prägnanz beiträgt. Anfangs sieht der Kotlin-Code, den Ihr Team schreibt, jedoch möglicherweise eher wie der Java-Code aus, den er ersetzt. Das ändert sich, wenn Ihr Team mehr Erfahrung mit Kotlin sammelt. Eine schrittweise Änderung ist der Schlüssel zum Erfolg.
Hier sind einige Dinge, die Sie tun können, um die Konsistenz Ihrer Kotlin-Codebasis zu gewährleisten, wenn sie wächst:
Allgemeine Codierungsstandards
Definieren Sie frühzeitig im Einführungsprozess einen Standardsatz von Codierungskonventionen. Sie können vom Android Kotlin-Stilhandbuch abweichen, wenn das sinnvoll ist.
Tools für die statische Analyse
Setzen Sie die für Ihr Team festgelegten Codierungsstandards mit Android Lint und anderen Tools für die statische Analyse durch. ktlint, ein Kotlin -Linter eines Drittanbieters, bietet auch zusätzliche Regeln für Kotlin.
Continuous Integration
Achten Sie darauf, dass Sie die allgemeinen Codierungsstandards einhalten und eine ausreichende Testabdeckung für Ihren Kotlin-Code bieten. Wenn Sie dies in einen automatisierten Build-Prozess einbeziehen, können Sie die Konsistenz und die Einhaltung dieser Standards gewährleisten.
Interoperabilität
Kotlin ist größtenteils nahtlos mit Java kompatibel. Beachten Sie jedoch die folgenden Punkte.
Null-Zulässigkeit
Kotlin verwendet Null-Zulässigkeits-Annotationen im kompilierten Code, um die Null-Zulässigkeit auf der Kotlin-Seite abzuleiten. Wenn keine Annotationen angegeben sind, verwendet Kotlin standardmäßig einen Plattformtyp, der entweder als null-zulässig oder nicht null-zulässig behandelt werden kann. Wenn Sie Plattformtypen nicht sorgfältig behandeln, kann dies zu NullPointerException-Problemen zur Laufzeit führen.
Neue Funktionen einführen
Kotlin bietet viele neue Bibliotheken und syntaktischen Zucker, um Boilerplate-Code zu reduzieren, was die Entwicklungs geschwindigkeit erhöht. Seien Sie jedoch vorsichtig und methodisch, wenn Sie die Standard bibliotheksfunktionen von Kotlin verwenden, z. B. Sammlungsfunktionen, Coroutinen, und Lambdas.
Hier ist eine häufige Falle, in die Entwickler geraten, die neu in Kotlin sind. Betrachten Sie den folgenden Kotlin-Code:
val nullableFoo: Foo? = 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 sollen foo.baz und foo.zap ausgeführt werden, wenn nullableFoo nicht null ist, um eine NullPointerException zu vermeiden. Dieser
Code funktioniert zwar wie erwartet, ist aber weniger intuitiv zu lesen als eine Null-Prüfung und
ein 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 }
Test
In Kotlin sind Klassen und ihre Funktionen standardmäßig für die Erweiterung geschlossen. Sie müssen die Klassen und Funktionen, die Sie unterklassen möchten, explizit öffnen. Kotlin trifft diese Entscheidung, um die Komposition gegenüber der Vererbung zu fördern. Um die Komposition zu vereinfachen, bietet Kotlin integrierte Unterstützung für die Implementierung von Verhalten durch Delegierung.
Dieses Verhalten stellt ein Problem für Mocking-Frameworks wie Mockito dar, die auf der Implementierung oder Vererbung von Schnittstellen basieren, um Verhaltensweisen während des Tests zu überschreiben. Für Unittests können Sie die Verwendung der Mock Maker Inline Funktion von Mockito aktivieren, mit der Sie finale Klassen und Methoden simulieren können. Alternativ können Sie das Compiler-Plug-in „All-Open“ verwenden, um jede Kotlin-Klasse und ihre Elemente zu öffnen, die Sie im Rahmen des Kompilierungsprozesses testen möchten. Der Hauptvorteil dieses Plug-ins besteht darin, dass es sowohl mit Unittests als auch mit Instrumentierungstests funktioniert.
Weitere Informationen
Weitere Informationen zur Verwendung von Kotlin finden Sie unter den folgenden Links:
- Kotlin-first-Ansatz von Android
- Ressourcen für den Einstieg in Kotlin
- Ressourcen für Java-Nutzer, die Kotlin lernen
- Java to Kotlin learning pathway, eine Sammlung von Ressourcen, die Java-Programmierern helfen, idiomatische Kotlin-Programme zu lernen und zu schreiben.