自己紹介
どうも、ikasumi1503です。独学でweb開発を練習してきたのですが、ひょんなことから「アンドロイドを開発しろ」と言われたのでJetpackCompose始めてテトリス作りました。いきなり谷底の中に身を投じたのですが、なんとか這い上がってきました。以下はテトリス開発時に学んだことや困ったことの記録です。
学んだこと
MVVMパターンとは
JetpackComposeはMVVMパターンで書きました。
MVVMとは、Model、View、ViewModelの三つの頭文字を取ったもので、これらを連結させたものです。それぞれ、おおまかに以下のようになります。
Model ... 主にアプリの機能やデータ構造・型定義、データ取得/保存処理を担う部分
View ... アプリの表示部分
ViewModel ... アプリの現在の状態を管理する。ViewとModelの橋渡しをする部分。
飲食店でたとえるなら、Viewは出されている料理、Modelは調理や発注をする厨房、ViewModelは接客のようなイメージです。
呼び出す関係性を矢印で表すと、次のようになります。
Model → ViewModel → Model
一方向で流れてますね。逆方向にも呼べるようにすると、役割が逆転したり、再利用性が低くなるというのを避けています。
ファイル構成
そして実際には、次のようなファイル構成で組みました。
com.example.tetrisapp/
├── app/
│ ├── MainActivity.kt
│ └── core.ui.theme/
├── feature_game/
│ ├── data/
│ ├── domain/
│ │ ├── entity/
│ │ ├── model/
│ │ └── usecase/
│ ├── ui/
│ │ ├── game_component/
│ │ ├── viewmodel/
│ │ │ └── GameOverScreen.kt
│ │ ├── GameScreen.kt
│ │ ├── MainScreen.kt
│ │ └── MenuScreen.kt
│ └── util/
│ ├── GameConstants.kt
│ └── LevelConstants.kt
app/
アプリの入り口。MainActivity.kt はJetpack Composeアプリが起動されると最初に開かれる。
core.ui.theme
テーマカラーやTypographyなどUIのスタイル定義を含む。
feature_game/
このアプリの主要機能である「テトリスゲームのロジックとUI」を含む機能モジュール。
data/
データソースに関する実装を置く場所。APIでデータをストレージから引っ張ってきたりするらしい。
domain/
ビジネスロジック層(Model) に該当。
entity/
ゲームの状態、ミノなどの純粋なデータ構造やそのデータの処理を置く。
model/
entityでどんな関数を使うか、どんなデータを定義するかを置いておく場所。modelは中に何があるかを紹介して、entityは紹介されたものの機能を置いておく。
usecase/
アプリ専用の処理を置いておく場所。ViewModelから呼び出される。どこからでも呼び出すとuseCaseっていう紐が絡まってがんじがらめになるので、UIからは直接呼び出さないようにする。
ui/
アプリの表示部分(View)を構成。
game_component/
ゲーム画面で使われるコンポーネントを管理。
viewmodel/
各画面の状態やイベントを管理する ViewModel を配置。
GameScreen.kt, MainScreen.kt, MenuScreen.kt: 各画面を構成するJetpack ComposeのComposable関数。
util/
ゲームに必要な定数類をまとめて定義。
細かい処理などはGitHubを見てください。
念のため言いますが、初心者開発なのでAIが吐き出したのと同じレベルのアプリです。参考にするのは自己責任でお願いいたします。
https://github.com/ikasumi1503/TetrisApp
困ったこと
一つの処理を作るのにUI→ViewModel→Modelというステップを踏まないといけなかったので、めんどくさかったこと
→ Android Studioのスニペット機能を使う
→ ファイルのテンプレート作成機能があるみたいなので、それを使う
→ そもそも別のアーキテクチャ使う
平凡な解決策しかないですが、自動化はいい感じのツールがない限り大抵泥臭くなりますよね。応急措置です。
UseCaseの中でUseCaseを使ってしまったこと
→ Util関数を作って対応する
→ UseCaseになっている部分をviewModelのfunにして必要な時に呼び出す
一つのUseCaseを変えるために他のUseCaseを変えないといけない...というのを防ぐために、UseCaseの層数は1つにしといた方がよさそうです。本プロジェクトでは直すのが面倒だったので、そのままにしておきますが次回以降直しておきます。
テトリスの設計を図にしてまとめていなくて、処理がシンプルにまとまっていなかった点
→ 図にしてどの関数が必要かをまとめておくと後々まとめなおさなくて楽できそうです。
以上が反省点になります。
あまりにも谷底に勢いをつけて突っ込みすぎた点
今回は本や公式のレポジトリなどをあまり見ずにとりあえずはじめてみました。形になるのは早かったのですが、あとから修正する内容がかなりありました。当アプリは計13日で作ったのですが、この修正作業がなければ2~3日は作業を短縮できたのではないかと思います。
新しい技術を触って何かを作るときにはまとまった知識(例えば本)を3時間ほどかけて流し見するとだいぶ変わるかもしれません。地図を把握するだけで大幅なショートカットが期待できます。
最後に
知らないものを使って何か作りたいと思えば意外とそれっぽいものを作れますね。引き続きアプリを作ったり新しいツール触っていこうと思います。
ご覧いただきありがとうございました。