ゆめみの Android の採用コーディング試験を公開しました

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165251/f4418fc1-6e9c-9152-96f9-5825a6b384dc.png width=640>
株式会社ゆめみの Android の採用コーディング試験を公開しました :tada: 

https://github.com/yumemi-inc/android-engineer-codecheck

会社の採用試験どうしよう、、と悩んでいる採用担当の方がいましたら、ぜひご活用ください :ok_woman: 
レビューできる人がいないという場合には、ぜひ弊社までご相談いただけたらと思います。

## なんで公開したの？

主に応募のハードルを下げるのが狙いです :smirk:
どんな試験なのか分かっているだけで、だいぶ気が楽になりますよね :relieved:

また、逆に無茶な応募が減るということもあるのではとも考えています。

## どんな試験？

ざっくり説明すると **メチャクチャなコードを改善してください** というものです :muscle:

詳しくはリポジトリの [README](https://github.com/yumemi-inc/android-engineer-codecheck/blob/main/README.md) をご覧ください。

**※ 新卒か中途かによって必須課題が変わる点にはご注意ください。**

## 公開しちゃって大丈夫なの？

### 誰かが良い解答を公開したら、それを真似すればいいんじゃ？

そもそもどれが良い解答なのかを判断しなければなりません。
どれが良い解答なのか判断できたら、合格で何も問題ありません :ok_woman: 

あるあるかもしれませんが、丸パクリするような人に限って、あまり良くないコードをパクっていることが多いイメージです。

あと、実はちょっとした工夫をしているので、おそらく大丈夫です。:sunglasses:

### 事前に解いていて、Git の履歴を改竄して期限内に提出とかできるんじゃ？

最終的にできるようになっているのであれば問題ありません。
逆に Git 操作がきちんとできるんだなと好印象です。

試験の解答期限の１週間というのは、応募者に無理をさせないためのものです。
できる人であれば、１日で試験完了して合格しています。

## 試験で見ているところは？

**おかやまん個人** として見ているところを大まかな項目ごとに書いていきます :sunglasses: 
試験内容に明示されている内容を見るのは当たり前なので、他のところだけピックアップします。
さすがに全ては書ききれませんが、少しでも参考になれば幸いです。

### README について

#### 環境構築するために必要な情報が記載されているか

AndroidStudio の canary 版でしか動作しなかったり、特定のスクリプトを実行しなければ動作しなかったり、、、
アプリを動作させるのに特殊なことをしなければならない状態であれば、きちんと記載されているか確認します。

#### 各 Flavor の役割が記載されているか

特定の Flavor では固定のモックデータを扱うなど、不具合なのか意図した動作なのか判断できない場合があります。
余計な確認コストを削減するためにも記載しておきましょう。

### Git について

#### 適切に .gitignore が設定されているか

他のメンバーの環境でビルドができなくなってしまったり、ビルドの度にファイルの変更が発生してしまったり、、、
きちんと設定していないとそもそも開発がストップしてしまうため、これができていないと厳しいです。

開発するときは、何を管理対象にするかしないのかをきちんと確認しましょう。

#### 意味のある粒度でコミットを作成しているか

意味のある粒度でコミットを作成していれば、リバートコミットで範囲を絞って元に戻したり、チェリーピックでコミットを丸ごと別ブランチに移植したりすることができます。
粒度が小さければ小さいほどいいというわけではありませんが、粒度が大きいよりはメリットがあるという感覚です。

たまに **全てを１つのコミットにまとめてきた！** という方がいらっしゃいますが、開発プロセスや意図が伝わりづらくレビューするのが大変になるので、やめていただけると幸いです :innocent: 笑

チーム開発する上で、他のメンバーやレビュアーのことを考えている方って、それだけでステキですよね :relaxed: :sparkles:

#### 適切なブランチ運用

様々なブランチ運用がありますが、開発を進めるにあたって問題がなければどれでも大丈夫です :ok_woman: 

課題のチェック項目ごとにブランチを切って、GitHub のプルリクエスト機能を利用して修正理由を明確に記載していると好印象です。
たまに、プルリクエスト機能を利用してるけど、説明に何も書いていない **なんちゃってプルリクエスト** をしている方がいますが、それではあまりプルリクエストを出す意味がありません。。（ GitHub Actions を利用しているとかであれば話はちょっと変わってきます）

##### ブランチ運用例

- [Git flow](https://nvie.com/posts/a-successful-git-branching-model/)
- [GitHub flow](https://guides.github.com/introduction/flow/)
- [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html)

### ライブラリについて

#### 追加・更新・削除時の影響をきちんと確認しているか

ライブラリを追加・更新・削除すると、勝手に他のライブラリのバージョンが上がったり下がったりしてしまうことがあります。
リリースノートを確認したり、変更前後の依存関係を比較したりすることをオススメします。

また、これまでコードレビューをしてきた経験上、プロガードの設定が漏れていることが多いです。
試験のコードは、リリースビルドで難読化を有効にしているので要注意です :cop:

#### 不要なものを記述していないか

未使用のライブラリを記述しないというのは当たり前ですが、きちんと `implementation` `debugImplementaion` `testImplementaion` `androidTestImplementaion` などの使い分けができているかは重要です。

特に、リリースビルドにデバッグ用のライブラリが入っていないかは要確認です。

#### 正しく扱えているか

バージョンによって挙動が変わったりするため、利用しているバージョンのドキュメントを確認して実装しているか確認します。

正直なところ、確認するのは骨が折れます。。
いろいろなことが知れる機会だと思い、自分の心を鬼にして確認しています :japanese_ogre:

例えば、JSON を扱うときに利用される kotlinx.serialization の `ignoreUnknownKeys` という設定についてです。
`true` に設定すると、以下のように`Project` クラスには存在しない `launguage` というものが JSON データにあった場合、例外を発生させずに無視してデシリアライズを続行します。（デフォルトでは `false` ）

```kotlin
val format = Json { ignoreUnknownKeys = true }

@Serializable 
data class Project(val name: String)
    
fun main() {             
    val data = format.decodeFromString<Project>("""
        {"name":"kotlinx.serialization","language":"Kotlin"}
    """)
    println(data)
}
```

https://github.com/Kotlin/kotlinx.serialization/blob/v1.3.0/docs/json.md#ignoring-unknown-keys

このような動作を把握していないと API が更新された時に、アプリがクラッシュしたり、期待する動作をしなくなったりしてしまいます。

ライブラリを導入する際は、くれぐれもお気をつけください！

### コードについて

基本的に、試験の課題を確認していただけたら分かると思います。

https://github.com/yumemi-inc/android-engineer-codecheck/milestone/1

ですが、せっかくなので少しだけピックアップします。

#### 読みやすいコードになっているか

自分がこれまでに見てきた中でも最高にイケていないコードを、かなり省略してご紹介いたします。

**※ ゆめみではなく前職のときに遭遇しました**

```kotlin
var _a = mapOf("Emi" to 3, "Taro" to 12, "Takuya" to 35)
var _b: Any? = null

fun main() {
    _b = mutableListOf<Any>()
    (_b as MutableList<Any>).add(_a["Takuya"] as Any)
    (_b as MutableList<Any>).add(_a["Emi"] as Any)
    (_b as MutableList<Any>).add(_a["Taro"] as Any)
    _b = (_b as MutableList<Any>)[0] as Int -
    ((_b as MutableList<Any>)[1] as Int + (_b as MutableList<Any>)[2] as Int)

    println(_b!!)
}
```

みなさんは、最後に何が表示されるかパッと分かりますか？
私は分かりません 笑

実際には、こんなコードが１つのファイルに１万行ほど書かれており、震えが止まりませんでした。

サービスやアプリを長く提供し続けるためにも、簡潔性・可読性・保守性の高いコードを書けることは非常に重要です。

#### テストを書きやすいコードになっているか

テストがあるに越したことはありませんが、無理くり書いたテストコードは保守性を大きく損ねる危険性があるため要注意です。
まずは、責務を分割したり、モックと簡単に差し替えられるような構成にしたりして、テストを書きやすくすることをおすすめします。

### UI について

#### 画面回転や端末の画面サイズ、フォントサイズ、ダークモードのことを考えているか

Android アプリ開発者の宿命と言っても過言ではありません。

- 画面回転するとダイアログが２つ表示されてしまう
- 端末によって大幅にレイアウトが崩れてしまう
- フォントサイズを大きくすると、文字が見切れてしまう
- ダークモード時に文字が見づらくなってしまう

あるあるですよね。。
この辺りのこと対応できていると好印象です。

#### プレビューで確認できるようしているか

xml では tools 属性、Jetpack Compose では Preview アノテーションを利用しているか確認します。

https://developer.android.com/studio/write/tool-attributes?hl=ja#design-time_view_attributes

https://developer.android.com/jetpack/compose/tooling#preview

アプリを実行しなくてもレイアウトの確認ができると、開発効率は想像以上に上がります。
初めの段階からプレビューできるようにしておくのをおすすめします。

#### ネストを浅くしているか

ネストが深いと、可読性やパフォーマンスが低下してしまいます。
たまに、１つの ConstraintLayout だけで表現できる箇所を、ConstraintLayout を複数ネストさせて表現してきてしまう方がいらっしゃるのでご注意ください。

ConstraintLayout は、非常に便利ですので一通りの機能を試してみることをおすすめします。

https://developer.android.com/training/constraint-layout?hl=ja

### その他

#### エラー発生時にどのようにしているか

エラーを握りつぶして、ユーザーが何も分からない状態になっているのは論外です。
場合によっては、エラーをキャッチせずにアプリを落とす方が良いこともありそうです。

理想的には、エラーが発生したことや発生原因をユーザーに伝え、その後ユーザーがどうすればいいかまで誘導できればステキです :heart_eyes:

#### どのくらい自動化しているか

自動化できるものってたくさんありますよね。
コードの整形、モックデータの生成、ビルド、テスト、デプロイ、、などなど

GitHub Actions や Firebase などのおかげで、この辺りも比較的簡単に自動化できるようになってきました。
しかし、コーディング試験で一時的なデプロイ環境を用意して、デプロイまで自動化している猛者には、さすがにビビりました :older_man:

## あとがき

以上、ゆめみの Android の採用コーディング試験の紹介でした。
ゆくゆくは英語などにも対応して、海外の企業でも利用できるように改善していく予定です。

一生懸命考えて作成した試験ですが、まだまだ改善の余地はあると思います。
何かお気づきの際には、優しくご教示いただけますと幸いです。

教材として、採用試験として、たくさんの方にご活用していただけたらと思いますので、ぜひ拡散お願いいたします！

### 同じ会社の iOS の記事

https://qiita.com/lovee/items/d76c68341ec3e7beb611