チームでコードを書いている途中、こっちの方がいいんじゃないか?という新しい関数を作って乗り換えてみたり、もっといい変数名を思いついたのでリネームしたら予想以上に影響範囲が広かったり、新しいロジックを思いついてみたがまだ本格導入するほど自信がないといった経験はありませんか?
個人プロジェクトでは自分の好きなタイミングでリファクタや導入タイミングを決められますが、チームで開発しているときはこれらは注意事項としてチームメンバーに周知する必要があります。
- より便利な関数ができたのでそちらを使ってほしい
- よりわかりやすい名前にリネームしてほしい
- セキュリティやメンテナンス性の観点からこれ以上使って欲しくない
- まだ実装が固まってないので利用を限定するか、破壊的変更があることを分かった上で使ってほしい
Slackや口頭でも説明ができますが、時間が経つと忘れてしまうものです。できればそういった関数や変数を使おうとしている時にお知らせしてくれると嬉しいですよね。
IDEの力を借りてそれらを伝えることができるのが@Deprecated
と@Experimantal
というアノテーションです。
環境
- Kotlin 1.3.61
- Android Studio 3.5.2(base IntelliJ IDEA 2019.1)
Deprecated
Deprecatedアノテーションは開発者に「これを使うのはオススメしない」と通知することができます。
val path: String
get() = a + b + c
上の例ではもともとpath
プロパティを使っていましたが、これを「これからは使って欲しくない」としたいとします。
使って欲しくない理由としてpath
では絶対パスが取得できるのか相対パスが取得できるのかが名前から推測できないという理由です。path
は元々相対パスが取得できる仕様だったとして、よりわかりやすくrelativePath
を作り今後はそちらを使って欲しいとあなたは考えました。
そこでpath
にDeprecatedアノテーションをつけてみます。
KotlinではDeprecatedアノテーションに2つの引数をとります。
1つめは理由です。どうしてこれを使って欲しくないのかを書きます。
2つめは移行先です。ReplaceWithを使って乗り換え先を示します。ReplaceWithは省略できませんが内容は省略が可能です。
@Deprecated("Misleading name. Replace `relativePath`", ReplaceWith("relativePath"))
val path: String
get() = relativePath
val relativePath: String
get() = a + b + c
このように書くとIDEでpath
を呼び出そうとした時に取り消し線が引かれて表示されます。
またカーソルを合わせると先ほど入力した使ってほしくない理由が表示されます。
これを見れば使おうと思った時に表示されるので忘れずに済みそうです。
またReplaceWithを書いていればIDEが自動で置換もおこなってくれます。
ReplaceWithは正規表現も使えますのでうまくいけばどんな名前でもリネームが1発でできるようになります。が、結構難しいのでまずは空文字でも良いと思います。使われる頻度をゆっくり減らしていく作戦がいいでしょう。
Experimental
こちらはKotlin1.3から使えるようになったアノテーションです。頻繁に破壊的変更が発生する可能性が高いものにつけておくことで、利用者はそれを知った上で使うといった運用ができます。
Experimentalアノテーションを使うには、まずどういう試験的なものなのかを示すためにオリジナルのアノテーションを作成し、そのアノテーションにExperimentalという属性を付与します。
@Experimental
annotation class WeatherExperimental
次に実際に試験的に作っている変数や関数に先ほど作ったアノテーションを付与します。
@WeatherExperimental
fun getWeather(city: String): Weather {
}
このように書くとIDEでgetWeather
関数を呼び出した時にエラーが表示されます。
Experimentalアノテーションを使っている場合は呼び出し元もそれを使っていると承知の上ということを示すため呼び出す関数に@UseExperimental
アノテーションをつけます。
@UseExperimental(WeatherExperimental::class)
fun weather() {
val api = Api()
val weather = api.getWeather("Tokyo")
}
これらのアノテーションはライブラリによく使われますが、プロダクションコード内でも使ってみることで言葉を交わさずとも意思疎通がとれるかもしれません。