Przejście na nowy język może być trudne. Aby Twój zespół odniósł sukces, zacznij powoli, przeprowadzaj migrację w małych partiach i często testuj. Kotlin jest kompilowany do kodu bajtowego JVM i jest w pełni interoperacyjny z Javą, co ułatwia migrację.
Budowanie zespołu
Pierwszym krokiem przed migracją jest zbudowanie wspólnego zrozumienia podstaw przez zespół. Oto kilka wskazówek, które mogą pomóc w przyspieszeniu nauki zespołu.
Tworzenie grup naukowych
Grupy naukowe to skuteczny sposób na ułatwienie nauki i zapamiętywania. Badania sugerują że powtarzanie tego, czego się nauczyłeś, w grupie pomaga utrwalić materiał. Kup książkę o Kotlinie lub inne materiały do nauki dla każdego członka grupy i poproś grupę o przeczytanie kilku rozdziałów tygodniowo. Podczas każdego spotkania grupa powinna porównać to, czego się nauczyła, i omówić wszelkie pytania lub spostrzeżenia.
Budowanie kultury nauczania
Nie każdy uważa się za nauczyciela, ale każdy może uczyć. Od kierownika zespołu lub technologii po indywidualnego współpracownika – każdy może zachęcać do tworzenia środowiska uczenia się, które może pomóc w osiągnięciu sukcesu. Jednym ze sposobów na ułatwienie tego jest organizowanie okresowych prezentacji, podczas których jedna osoba z zespołu jest wyznaczona do opowiedzenia o czymś, czego się nauczyła lub czym chce się podzielić. Możesz wykorzystać grupę naukową, prosząc ochotników o prezentowanie nowego rozdziału co tydzień, aż zespół poczuje się swobodnie w tym języku.
Wyznaczanie mistrza
Na koniec wyznacz mistrza, który będzie kierować procesem uczenia się. Ta osoba może pełnić rolę eksperta w danej dziedzinie (SME) podczas rozpoczynania procesu wdrażania. Ważne jest, aby ta osoba uczestniczyła we wszystkich spotkaniach dotyczących Kotlina. Najlepiej, jeśli ta osoba pasjonuje się już Kotlinem i ma pewną wiedzę praktyczną.
Powolna integracja
Kluczem jest powolne rozpoczynanie i strategiczne myślenie o tym, które części ekosystemu należy przenieść w pierwszej kolejności. Często najlepiej jest odizolować to do jednej aplikacji w organizacji, a nie do flagowej aplikacji. Jeśli chodzi o migrację wybranej aplikacji, każda sytuacja jest inna, ale oto kilka typowych miejsc, od których można zacząć.
Model danych
Model danych prawdopodobnie składa się z wielu informacji o stanie i kilku metod. Model danych może też zawierać typowe metody, takie jak toString, equals i hashCode. Zwykle możesz przeprowadzić migrację tych metod i przetestować je w izolacji.
Załóżmy na przykład, że masz ten fragment kodu w Javie:
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 + '\'' +
'}';
}
}
Klasę Java możesz zastąpić jednym wierszem kodu w Kotlinie, jak pokazano w tym przykładzie:
data class Person(var firstName: String?, var lastName: String?)
Następnie możesz przetestować ten kod w ramach bieżącego zestawu testów jednostkowych. Zacznij od małych kroków, po jednym modelu, i przeprowadź migrację klas, które są głównie stanem, a nie zachowaniem. Po drodze często testuj.
Migracja testów
Innym miejscem, od którego możesz zacząć, są testy: przekonwertuj istniejące testy i napisz nowe testy w Kotlinie. Dzięki temu Twój zespół będzie miał czas na zapoznanie się z językiem, zanim napiszesz kod, który będzie dostarczany z aplikacją.
Przenoszenie metod narzędziowych do funkcji rozszerzeń
Statyczne klasy narzędziowe, takie jak StringUtils,
IntegerUtils, DateUtils, czy YourCustomTypeUtils, możesz przedstawić jako
funkcje rozszerzeń Kotlina
i używać ich w istniejącej bazie kodu Java.
Załóżmy na przykład, że masz klasę StringUtils z kilkoma metodami:
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
}
}
Te metody mogą być używane w innych miejscach aplikacji, jak pokazano w tym przykładzie:
...
String myString = ...
String fooString = StringUtils.foo(myString);
...
Korzystając z funkcji rozszerzeń Kotlina, możesz udostępnić ten sam interfejs Utils wywołującym w Javie, a jednocześnie zaoferować bardziej zwięzłe API dla rosnącej bazy kodu Kotlin.
Aby to zrobić, możesz zacząć od przekonwertowania tej klasy Utils na Kotlin za pomocą automatycznej konwersji udostępnianej przez IDE. Przykładowe dane wyjściowe mogą wyglądać tak:
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
}
}
Następnie usuń definicję klasy lub obiektu, dodaj do każdej nazwy funkcji typ, do którego ta funkcja powinna się odnosić, i użyj go do odwoływania się do typu w funkcji, jak pokazano w tym przykładzie:
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
}
Na koniec dodaj adnotację JvmName na początku pliku źródłowego, aby skompilowana nazwa była zgodna z resztą aplikacji, jak pokazano w tym przykładzie:
@file:JvmName("StringUtils")
package com.java.project
...
Ostateczna wersja powinna wyglądać tak:
@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
}
Pamiętaj, że te funkcje można teraz wywoływać w Javie lub Kotlinie zgodnie z konwencjami każdego języka.
Kotlin
// ... val myString: String = "hello" val fooString = myString.foo() // ...
Java
... String myString = ... String fooString = StringUtils.foo(myString); ...
Zakończenie migracji
Gdy Twój zespół będzie już dobrze znał Kotlin i przeprowadzisz migrację mniejszych obszarów, możesz przejść do większych komponentów, takich jak fragmenty, aktywności, obiekty ViewModel i inne klasy związane z logiką biznesową.
Uwagi
Podobnie jak Java ma określony styl, Kotlin ma swój własny idiomatyczny styl, który przyczynia się do jego zwięzłości. Na początku może się jednak okazać, że kod Kotlin pisany przez Twój zespół bardziej przypomina kod Java, który zastępuje. Zmieni się to, gdy Twój zespół zdobędzie doświadczenie w Kotlinie. Kluczem do sukcesu jest stopniowa zmiana.
Oto kilka rzeczy, które możesz zrobić, aby baza kodu Kotlin była spójna w miarę jej rozrastania się:
Typowe standardy kodowania
Na wczesnym etapie procesu wdrażania zdefiniuj zestaw standardów konwencji kodowania. W uzasadnionych przypadkach możesz odbiegać od przewodnika po stylu Kotlin na Androidzie .
Narzędzia do analizy statycznej
Wymuszaj przestrzeganie zestawu standardów kodowania ustalonych dla zespołu, używając narzędzia Android lint i innych narzędzi do analizy statycznej. ktlint, narzędzie do sprawdzania kodu Kotlin firmy zewnętrznej, udostępnia też dodatkowe reguły dla Kotlina.
Tryb ciągłej integracji
Pamiętaj, aby przestrzegać typowych standardów kodowania i zapewnić wystarczający zasięg testów kodu Kotlin. Włączenie tego do zautomatyzowanego procesu kompilacji może pomóc w zapewnieniu spójności i przestrzegania tych standardów.
Interoperacyjność
Kotlin w większości przypadków bezproblemowo współpracuje z Javą, ale pamiętaj o tych kwestiach.
Dopuszczalność wartości null
Kotlin opiera się na adnotacjach dopuszczalności wartości null w skompilowanym kodzie, aby określić dopuszczalność wartości null po stronie Kotlina. Jeśli adnotacje nie są podane, Kotlin domyślnie używa typu platformy, który można traktować jako dopuszczający lub niedopuszczający wartości null. Jeśli nie będziesz ostrożnie obsługiwać typów platformy, może to prowadzić do problemów z NullPointerException w czasie działania.
Wdrażanie nowych funkcji
Kotlin udostępnia wiele nowych bibliotek i cukru syntaktycznego, które zmniejszają ilość kodu szablonowego, co pomaga zwiększyć szybkość programowania. Należy jednak zachować ostrożność i metodyczność podczas korzystania z funkcji biblioteki standardowej Kotlina, takich jak funkcje kolekcji, współprogramy, i wyrażenia lambda.
Oto typowa pułapka, w którą wpadają deweloperzy, którzy dopiero zaczynają pracę z Kotlinem. Rozważmy ten kod Kotlin:
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() }
W tym przykładzie chodzi o wykonanie foo.baz i foo.zap, jeśli nullableFoo nie jest wartością null, co pozwala uniknąć NullPointerException. Ten
kod działa zgodnie z oczekiwaniami, ale jest mniej intuicyjny niż sprawdzanie wartości null i
inteligentne rzutowanie,
jak pokazano w tym przykładzie:
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 }
Testowanie
W Kotlinie klasy i ich funkcje są domyślnie zamknięte na rozszerzenie. Musisz jawnie otworzyć klasy i funkcje, które chcesz podklasować. Kotlin podejmuje tę decyzję, aby promować kompozycję zamiast dziedziczenia. Aby uprościć kompozycję, Kotlin ma wbudowaną obsługę implementowania zachowania przez delegowanie.
To zachowanie stanowi problem dla platform do tworzenia atrap, takich jak Mockito, które polegają na implementacji interfejsu lub dziedziczeniu, aby zastępować zachowania podczas testowania. W przypadku testów jednostkowych możesz włączyć korzystanie z funkcji Mock Maker Inline w Mockito, która umożliwia tworzenie atrap klas i metod finalnych. Możesz też użyć wtyczki kompilatora All-Open aby otworzyć dowolną klasę Kotlin i jej elementy, które chcesz przetestować w ramach procesu kompilacji. Główną zaletą korzystania z tej wtyczki jest to, że działa ona zarówno z testami jednostkowymi, jak i testami z instrumentacją.
Więcej informacji
Więcej informacji o korzystaniu z Kotlina znajdziesz pod tymi linkami:
- Podejście Androida oparte na Kotlinie
- Materiały na temat rozpoczynania pracy z Kotlinem
- Materiały dla użytkowników Javy, którzy uczą się Kotlina
- Ścieżka nauki Java – Kotlin, czyli zbiór materiałów, które pomagają programistom Java uczyć się i pisać idiomatyczny kod Kotlin.