JetpackComposeのSlot APIsの紹介

今回はJetpackComposeのSlot APIsについて書いていきます。
スライドを先に作成したため、そのスライドに説明を付与していく形で書いていきます。

speakerdeck.com

本編

f:id:mitoavadn:20210628214111p:plain JetpackComposeにはSlot APIsという概念があります。
今回はそのSlotAPIsをスライドベースで紹介していきます。


f:id:mitoavadn:20210628214232p:plain Slot APIsというのはComposableの上にカスタマイズのためのレイヤを適用するという概念です。

これを用いることで見た目のカスタマイズがしやすくなります。

Slot APIsが無い場合だとカスタマイズするために多くの引数を用意する必要が出てきます。
例えば、Buttonのテキストをカスタマイズできるようにするために、textColortextSizefontWeightなどなど......
Buttonだけでも多くあるため、他のComposableもとなるとより多くの引数が必要になってしまいます。

これがSlot APIsという概念のおかげで引数を大幅に減らすことができ、カスタマイズ性も高くできます。

JetpackComposeで使えるマテリアルコンポーネントのComposableでも多く定義されています。

イメージとしてはComposableで用意されている枠に対してComposableを当てはめることができるような感じです。


f:id:mitoavadn:20210628215735p:plain 例としてTopAppBarというComposableをあげます。
この画像の白い破線で囲まれている部分が


f:id:mitoavadn:20210628215921p:plain Slotになります。
ここに色々なComposableを当てはめることができます。


f:id:mitoavadn:20210628220258p:plain TopAppBarの定義を見てみます。


f:id:mitoavadn:20210628220436p:plain 赤い下線がある部分がSlotとして他のComposableを受け取る引数です。
型を@Composable () -> Unit のように定義することで他のComposableを利用できます。
TopAppBarではtitle, navigationIcon, actionsにComposableを当てはめることができます。


f:id:mitoavadn:20210628220905p:plain TopAppBarでのtitle, navigationIcon, actionsはそれぞれこの位置に当てはめることができます。


f:id:mitoavadn:20210628221108p:plain 利用する際のコード例を見ていきます。
まずは、よくあるような戻るボタン・タイトル・縦3点リーダーを表示する例です。
title, navigationIcon, actionsそれぞれにComposableスコープのラムダを渡しています。


f:id:mitoavadn:20210628221324p:plain あまり多い使い方ではないと思いますが、こういった見た目を実装することもできます。
NavigationIcon部分に複数行のテキスト、Title部分にテキスト+画像+テキスト、Actions部分に枠付きボタンといったことが簡単にできます。
AndroidViewの場合、Title部分にテキスト+画像+テキストを設置するような実装は複雑になるかと思いますがComposeの場合であれば並べるだけで実現できます。
それぞれのComposableで文字色やフォントの指定は行っていないですが、個々の見た目も簡単にカスタマイズすることができます。


f:id:mitoavadn:20210628221925p:plain TopAppBarを見てきましたが、他にもSlotが利用できるComposableは多く存在します。


f:id:mitoavadn:20210628222103p:plain Scaffoldという見慣れないものがあると思いますのでそちらについても説明していこうと思います。 


f:id:mitoavadn:20210628222244p:plain Scaffoldはよくあるようなマテリアルデザインなレイアウト構造の見た目を実現するために使われるComposableです。
Scaffoldで定義されているSlotは


f:id:mitoavadn:20210628222438p:plain このような破線で囲まれている部分にComposableを当てはめることができます。
TopAppBarにBottomNavBar、FABにDrawContentにComposableを配置できます。


f:id:mitoavadn:20210628222756p:plain Scaffoldの定義を見てみます。


f:id:mitoavadn:20210628222833p:plain 先ほど説明したSlot部分は赤い下線がある部分になります。
TopAppBarのSlotと同じように@Composable () -> Unit で定義されています。


f:id:mitoavadn:20210628223204p:plain 最後にまとめです。
Slot APIsによってComposableの見た目をカスタマイズすることができます。
デフォルトで提供されている多くのComposableの多くでSlotが用意されていますので利用しやすいですし、自前でSlotを用意するようなComposableの実装の参考にすることもできます。
自作の色々な画面で利用するような共通のComposableを実装する際にSlotを受け取って表示するようなComposableにするとカスタマイズ性も上がって良いと思います。


f:id:mitoavadn:20210628223610p:plain 今回参考にしたものは以下です。
developer.android.com

developer.android.com

Composeのstate監視がどこまでされるのか試してみた

環境

  • Jetpack Compose 1.0.0-beta06
  • Gradle 7.0.0-alpha15
  • Kotlin 1.4.32

背景

Jetpack Compose(以下Compose)ではState<T>というものがあります。
これはComposeにおいて状態を管理するためのもので、ComposeはこのState<T>の変更を監視し値が変更されるとそのStateを利用しているComposableを自動で再読み込み(recomposition)して値の変更を見た目に反映させます。
詳細は以下リンク先にあります。

developer.android.com

そしてこのStateは以下のように使うこともできます。

class TodoViewModel : ViewModel() {

   // private state
   private var currentEditPosition by mutableStateOf(-1)

   // state
   var todoItems by mutableStateOf(listOf<TodoItem>())
       private set

   // state
   val currentEditItem: TodoItem?
       get() = todoItems.getOrNull(currentEditPosition)

   // ..

コードは以下Codelabから引用

developer.android.com

このコードではcurrentEditPositionInttodoItemsList<TodoItem>として利用できますが、by mutableStateOfを使って定義しているため、Composeの監視対象とされています。
そして、currentEditItemはこの2つの状態を利用しています。
こういった書き方をすることで、ComposeはcurrentEditPositiontodoItemsの変更を監視しつつ、どちらかに変更があったタイミングでcurrentEditItemのゲッターを再度呼び出し見た目に反映させます。

注意点としては、値が変更されたことをトリガーにしたい値(currentEditPositiontodoItems)をby mutableStateOf= mutableStateOfでStateオブジェクトとして定義する必要があります。

本題

ここで、この状態をゲッターで利用している値の監視はどこまで継続されるのか気になったため以下のコードの動作を確かめてみました。

コード

class MainViewModel : ViewModel() {
  var count1 by mutableStateOf(0)
    private set
  var count2 by mutableStateOf(0)
    private set

  val countResult1: Int
    get() = count1 + count2
  val countResult2: Int
    get() = countResult1 + 1
  val countResult3: Int
    get() = countResult2 + 1
  val countResult4: Int
    get() = countResult3 + 1
  val countResult5: Int
    get() = countResult4 + 1
  val countResult6: Int
    get() = countResult5 + 1
  val countResult7: Int
    get() = countResult6 + 1
  val countResult8: Int
    get() = countResult7 + 1
  val countResult9: Int
    get() = countResult8 + 1
  val countResult10: Int
    get() = countResult9 + 1
  val countResult11: Int
    get() = countResult10 + 1
  val countResult12: Int
    get() = countResult11 + 1
  val countResult13: Int
    get() = countResult12 + 1
  val countResult14: Int
    get() = countResult13 + 1
  val countResult15: Int
    get() = countResult14 + 1
  val countResult16: Int
    get() = countResult15 + 1
  val countResult17: Int
    get() = countResult16 + 1
  val countResult18: Int
    get() = countResult17 + 1
  val countResult19: Int
    get() = countResult18 + 1
  val countResult20: Int
    get() = countResult19 + 1
  val countResult21: Int
    get() = countResult20 + 1

  fun onClickCount() {
    count1++
  }

  fun onClickCount2() {
    count2++
  }
@Composable
fun Main() {
  val viewModel: MainViewModel = viewModel()

  Column {
    Text(text = "Count1:${viewModel.count1}")
    Text(text = "Count2:${viewModel.count2}")

    Spacer(modifier = Modifier.height(10.dp))

    Text(text = "Result1:${viewModel.countResult1}")
    Text(text = "Result2:${viewModel.countResult2}")
    Text(text = "Result3:${viewModel.countResult3}")
    Text(text = "Result4:${viewModel.countResult4}")
    Text(text = "Result5:${viewModel.countResult5}")
    Text(text = "Result6:${viewModel.countResult6}")
    Text(text = "Result7:${viewModel.countResult7}")
    Text(text = "Result8:${viewModel.countResult8}")
    Text(text = "Result9:${viewModel.countResult9}")
    Text(text = "Result10:${viewModel.countResult10}")
    Text(text = "Result11:${viewModel.countResult11}")
    Text(text = "Result12:${viewModel.countResult12}")
    Text(text = "Result13:${viewModel.countResult13}")
    Text(text = "Result14:${viewModel.countResult14}")
    Text(text = "Result15:${viewModel.countResult15}")
    Text(text = "Result16:${viewModel.countResult16}")
    Text(text = "Result17:${viewModel.countResult17}")
    Text(text = "Result18:${viewModel.countResult18}")
    Text(text = "Result19:${viewModel.countResult19}")
    Text(text = "Result20:${viewModel.countResult20}")
    Text(text = "Result21:${viewModel.countResult21}")

    Button(onClick = viewModel::onClickCount) {
      Text(text = "count")
    }
    Button(onClick = viewModel::onClickCount2) {
      Text(text = "count2")
    }
  }
}

結果

このコードを実際に動かしてみたときの動きは以下のようになります。 f:id:mitoavadn:20210506155005g:plain

2つのボタンいずれかを押すとResult1〜Result21の部分まで値が更新されました。
この結果からstateを使っているゲッターの監視は少なくとも20個くらいでも機能していることがわかります。
実際にどれくらいの数でも監視が可能なのかはたまた無制限なのかまでは調べられていませんが、大体のアプリケーションはここまで伝播させるケースは無いかと思いますので、「このゲッターは監視対象になるのか?」ということはほとんど気にしなくても良さそうです。

ちゃんといくつまで変更検知できるか試してみようかとは思ったのですが、大変そうだったので20個くらいでやってみました。
もし試した方がいれば教えてください。

2021/05/06 16:30頃追記

コードを生成するコードを作成して、変数をいくつまで変更検知できるか試してみました。
生成コードpythonで書きましたが、特に理由はないです。

f = open('foo.txt', 'w', encoding='UTF-8')
for i in range(8000):
    f.write('val countResult%s: Int\n' % (i + 1))
    f.write('get() = countResult%s + 1\n' % (i))

f.close()

結果として確認できたのは8000個の変数まで変更検知されていました。
f:id:mitoavadn:20210506164104g:plain

それ以上の変数(8500個以上など)も試してみましたが、そちらはビルド時にClass too largeとなってしまい検証はできませんでした。
これらのことから、ビルドできる範囲内であれば変数がいくつあっても変更検知できそうです。

追記ここまで

mito.

「チームで育てるAndroidアプリ設計」本を読んだ感想まとめ

mitoです。

こちらの記事は、自分のTwitterアカウントで連続ツイートの内容をまとめて追記したものになります。
元のツイートは以下リンクです。

本自体の紹介

本自体の概要は以下リンクにあります。

peaks.cc

この本は9章まであり、前半の1~4章が新規開発にフォーカスした内容、後半の5~8章が大規模開発にフォーカスした内容、最後の9章が新規開発と大規模開発で何が違うのかという内容になっています。

まとめ部分にも書いていますが、Androidアプリ開発者だけでなくiOSやバックエンド、フロントエンドなどのプロダクト開発している人たちにとっても読んで損しない内容になっていると思います。

新規開発フォーカス

前半部分である、1~4章まで読み切ったタイミングでの感想です。

なぜアーキテクチャが必要なのかという話から始まり、これから開発を始める・アーキテクチャを考えるというときに、どういった軸を考慮した方が良いか、非同期処理やエラーハンドリングといった多くのアプリケーションで必要となる部分をどうするかという話も細かくされていました。

自分が設計の存在を知り、学び始めた頃に感じていた「なんでモジュール分割するんだろう」「いくつもファイル分割することでコードがどこにあるのか探しにくくない?」とか思っていた点に関しても納得ができる話もあってあの頃に読みたかったな〜と感じました。

また、「アーキテクチャパターンはプロダクトの性質によって適したものが違う」という話自体は色々なところで聞いたことがありましたが、実際どういったプロダクトはどのアーキテクチャが適しているんだ...と思っていました。
そう思っていた部分に対して、メンバーの熟練などに合わせ、そのチームに適したアーキテクチャ選定をという話があり、プロダクト(チーム含む)の性質にとって適したもの(進め方)が違うということをやっと理解できました。

新規開発を進めやすくするためのリポジトリテンプレの話も結構細かくされていて、これからプロジェクト作っていくぞってなった時にもとても参考になりそうです。

ここまで読んで、自分主導でアーキテクチャ導入していたprocon30でのAndroidアプリのチーム開発は反省点が大きいなと感じました。
チームに合わせたもの・チームに浸透させるという部分が特に反省だと思いました。

大規模開発フォーカス

最後まで読み切りました。

後半の章では新規開発から成長していき、市場の規模・プロダクトチームの関係者・コードの量も多くなったプロダクトにおいて、既存機能の保守をしつつも新規機能を実装していくことの難しさやなるべくスピードを落とさずに進めるにはどうするのかということが経験ベースで詳しく書かれていてとてもためになりました。

多くの人が同時に1つのアプリケーションのコードを触ることになるため開発ルールをきちんと定め、チームで合意・浸透させることの大切さがとても伝わりました。

mitoが今やっているプロダクトは新規開発を経てこれから成長フェーズになっていく段階のため、新規部分の話も大規模部分の話もその違いの話も勉強になるところがとても多かったです。

5月4日23時ごろ追記

設計の改修をするとなったときにどこか一部のみ行うのではなく、移行方法をドキュメント化しそのドキュメントの方法に従って行えば移行できるという状況にしてメンバーで分担して一気に行うという部分で、「ここは仕方ない」という感じで特例を作ってしまうと「ここでも」「あ、ここはまた別の特例」となっていきそうなので一気に片してしまうという点でも良いなと思いました。

ActivityやFragmentと同じようなものとしてControllerというものがあることも初めて知れました。
追記ここまで

まとめ

全体を通して、「こう言った背景や考えでこう決定をした、その結果どうだった」ということが詳しく書いてあり、これからチームとして色々なことを決めていく上での考え方としてとても参考になると思います。

チームでプロダクト開発している人にとってもこれからという人にとってもためになるであろう話が多かったです。

Android特有の話も出てきてAndroidアプリ開発にフォーカスした内容ではありますが、大枠の話はプラットフォーム問わないであろう話になっていますので、iOSやバックエンド、フロントエンドなどのプロダクト開発している人たちにとっても良さそうな内容です。

最後にもう一度、「チームで育てるAndroidアプリ設計」へのリンクです。
良い本ですのでぜひ読んでみてください。
peaks.cc

mito.

オーダーメイド枕専門店に行った話

こんにちは、mitoです。

背景

もともと寝具類に特にこだわりがあったわけではなく特に知識もなかったので、セットで安く売られているものを使っていました。
ただ、専門店の出す寝具というものに興味がなかったわけではなかったです。
高級なものに変えることでどんな変化があるのかというのは気になっていました。
そして、今まではほとんどなかったと思っていますが、ここ最近夜中に目が覚める日があったのでこれは睡眠まわりの改善の機運だと思いました。

調べてみた

割と店多いですね。
どの店がいいんだろうなと思いながらも徒歩でもいけるくらいの距離にあった一番近い店にしました。
ピロースタンド というお店です。

実際に行ってみた

行ったお店は思っていたよりは小さめな店内でした。
ただ、フィッティング用のベッドが2つあり棚に種類違いの枕が多く置かれていて、確かに専門店だ...という感動を少し覚えました。
どんな感触のものがあるんだろうなと棚に近づくと、
「感染予防の観点から触れないようにお願いします」といった旨の文言が書かれていて、確かにそうだよなという感じで素材の説明だけを見ていました。
当然、何もわからないです。今まで使っていたものの素材がどういう風なものであるということすら知らないので当然ですね。

フィッティングしてもらった

分からないなりに素材の説明を見ていると店員さんが声を掛けてくださってフィッティングを行えるということでした。無料です。

質問表記入

店員さんが準備してくださっている間、睡眠周りに関する質問が書かれた紙を記入していきました。
質問の項目としてはいびきや寝相、睡眠サイクルとかがあった気がします。

高さ測定

仰向け状態での高さ

記入後、まずは頭と首の高さを測ってもらいました。
分かる人には分かって欲しいのですが、こどもの国のワンダーミュージアムにある赤い棒のようなものが無数にあってそれを手などで押すと反対側にその形のまま押し出されるやつのようなものを使って行いました。
ちゃんと伝わるようにいうと、「枕 測定器」で画像検索してみてください。出てきたやつです。
後頭部に高さを測る機器を当ててもらい寝る時の後頭部と首の高さの差を測ってもらいその結果を見ながら説明を受けました。
結果から首部分はこれくらいの高さで頭の部分はこれくらいの高さがあった方がいいということが分かった後は実際に枕を頭の下に敷いてその枕の下に木の板を挟んで高さの調整が行われました。
このときに仰向けで天井を見たときに視線が真上ではなく少し斜めを見るくらいに調整した方が良いという説明を受けてなるほどなとなっていました。

横を向いている状態での高さ

仰向け状態での高さ調整が終わると今度は横を向いた時の高さを調整しました。
このとき一緒にどういう姿勢で横を向くのが良いのかという説明も受けました。
横を向いた時の高さ調整のために何度か寝返りをうっていると店員さんから一言
「(ベットの大きさが)シングルサイズだと狭いですね、少なくともセミダブル以上が良いですよ」
枕の調整を行っていたらベットサイズも変えた方がいいという話になっていました。
ベットは部屋の広さが確保されたら変えてみます。
ちなみに、寝転がって立て膝状態での寝返りを左右にうつときにスムーズにできなかった(左右に倒すたびに腰の位置を動かす必要がある、そうしないと壁にぶつけたりベットから落ちそうになったりなど)らそのベットサイズは小さいらしいです。
高さは枕を上正面から見た時の上下左右それぞれの高さを調整しました。
ちなみにですが、横幅などの枕の大きさは一番大きいサイズでした。

素材選び

高さを測り終えると今度は素材の話になりました。
特にこだわりがあったわけではありませんが、今まで使っていた枕が柔らかめだったため今回も柔らかめのものを選びました。
柔らかめを選んでもその中でもいくつか素材がありました。
それぞれの素材の違いの説明を受けながら実際に試してこれがいいなというものを探していました。(ちなみにこの時に硬めのものも試させてもらいました)

枕カバー選び

枕カバーもいくつもありました。
冷感のものや枕の向きがわかるものなどがありました。
店員さんも注意して欲しいと言っていたのですが、枕の上下左右をそれぞれ調整して高さが違い枕本体にも向きがわかるタグなようなものがついていたのでカバーをしていても向きがわかるのは大事だなと思いました。

他にも項目があった気もしますが、フィッティングが終わりました。
枕の手入れの仕方や定期的に素材の調整が店でできるといったことも教えてもらいました。
その日は空いてたこともあり、1時間後くらいには枕の受け取りができました。

使ってみた感想

使ってみて、今まで使っていた枕とは劇的に感触などが違う!といったような感覚は特になかったです。
ただ、何日も使ってみた結果、最初の方に書いていた夜中に目覚めることも昼間に眠たくなくこともほとんど無くなってきて、朝もスッと起きれるので睡眠の質が良くなってきているんだろうなと感じてきています。
興味ありつつもなんだかんだ行っていなかった枕専門店ですが行って正解だと思いました。
良い枕が手に入ったこともよかったですが、店員さんが睡眠に関して教えてくださったのもとてもありがたかったです。
ありがとうございました。🙏

mito.

高専プロコン移動部門

プロコン本戦参加記 移動部門

前回(前々回)のブログの続きです。

この記事は第一弾を書いた後すぐくらいから書き始めた物を、長くなりそうだからという理由で下書き放棄していた記事に加筆・修正を加えた物です。

前回までの話

mitoavadn.hatenablog.com

なんやかんやあってプロコン予選通過し、プロコン本戦に参加することができました。

本編

出発日にmitoだけがいない

卒研のテーマを確定させないとなぁというのと夏休み期間中の開発の進め方をどういう風にしようかというのを考えていた、夏休み前の前期期末試験期間中の頃にあるメールが届きます。
「内定式のお知らせ」
内定式どんなことするんだろうなぁと考えながら、メールから日付を確認しカレンダーに追加します。(TimeTreeっていうアプリを使っているのですが、良い)
この時に、この日の近日中で何か予定入っていないかなと見てみると、ある予定が見えました。
プロコン本戦
内定式の日が本戦2日前・移動日前日というように見えたのですが、まぁきっとそんなことなく、間違いの可能性もあるので念のため教授にプロコン本戦と移動日の日程を聞きます。
何も間違っていないですね...

ちょっとこれは予想していなかったので、教授やメンバーと内定式後に一人で直接行くか沖縄に帰ってきてみんなと行くかを相談して、直接行くことに決めました。
プロコン本戦直前に数日いなくなり、プロコン会場までも直接行くということでメンバーに迷惑をかけることになってしまうので、報告と謝罪を行います。
この時に「もしプロコン会場にmitoがつけなかったらよろしくね」みたいなことを言った覚えがあります。

これで、プロコン移動日にmitoだけが東京から宮崎に向かうという、他のメンバーや他のチーム・教員とは別行動が決定しました。

予想外な

2019年10月6日(Wikipedia調べ)にある速報がTwitter上に流れます。
台風発生
まだこれだけなら、台風の時期だしよくあることなんですが、問題は進路と強さ
プロコン前日から1日目くらいにかけてくる予報のめっちゃ強い台風
確か発表されてすぐの進路では、移動日前後に沖縄から飛行機が飛ぶか怪しいくらいの位置にいる進路だったと思います。
ここから旅程を変更するべきかこのままの旅程で行くかどっちにしろ行けるのかというのでICT委員会内がバタバタしていました。(特に教授や委員長、お疲れ様でした。)

その進路を見て「これ、わんちゃんmitoだけが会場に行けるんじゃね?」という疑惑が出てきて、「mitoだけが辿り着けたら全チーム分の発表よろしくね!」っていうことを周りから言われ始めます。
mitoは台風が沖縄に来る前には東京に飛んでるし、沖縄に台風が来る日くらいには長崎の会場に東京から向かうしで余裕でつけると思っていました。

変化する進路

そこから日が過ぎていくにつれて台風の進路に変化が出てきます。
なんと、プロコン本戦当日前後に宮崎周辺に台風がいるという進路予想になっていきます。
これを受けてプロコン実行委員が開催するかどうかに関して協議を始めていたはずです。
もし、プロコン本戦当日近日に台風が宮崎にいるなら、mitoはもちろん他のメンバーたちもつけません。(着けたとしても開催は厳しい)

結局、進路がまたずれてプロコン本戦は開催できそうということになって、沖縄から向かう組の飛行機も飛べそうという感じになってきました。

ただ、mitoが問題になってしまいました。
進路が最初の頃とだいぶ変わって、プロコン本戦前日に関東に台風が来ることになってしまっていました。

もともと、mitoの予定としてはプロコン本戦前日の朝の便で出発するつもりでしたが、台風の進路と規模的にその日の飛行機は全て飛ばないかもしれないという案内がANAから届きます。

「あ、これはまずい」という感じになり教員とどうやったらいけそうかという相談をしました。
その結果、飛行機をキャンセルして内定式の日(プロコン本戦の前々日)に新幹線で移動するという案が出てきました。ただ、時間的にも経路的にもその日のうちには宮崎までは行けないので、一旦関西あたりで一泊することになりそうです。
ただ、この時も新幹線のチケットをネットで買えず(理由は覚えていない)、台風で激混みするだろうから「最悪、立ちっぱかもね」という話を「まさかそんなことはない」と楽観視して過ごしていました。

とりあえず、この方法なら行けそうだなと思いつつ、最悪の状況を考えてメンバーに謝罪しに行きます。
「mitoは行けないかもしれないからよろしく笑」

時は流れ

内定式当日朝に新幹線の切符を買いに行きました。
そしたら、予想通り台風の影響か大混雑していて、みどりの窓口に入りきらないくらいの人の数でした。
ここで問題が。
- この人数で、内定式までに買って移動できるか
- 今までに自分自身で新幹線のチケットを買ったことがない
- 新幹線に乗った経験も関東-東北間だけで、関東-九州の長距離は皆無

チケット購入機で区間を登録し購入しようとすると「その経路は機械では取り扱えないので窓口を利用してください」と機械に言われ、「この人数並ぶのか...」と思いつつも仕方ないので並びました。
もう少しで、窓口にたどり着けるとなっていたときに混雑緩和のため、要件を聞いて回っていた職員の方と話すと、「それなら機械でできますのでそちらでお願いしてもよろしいでしょうか」となってしまったので、困惑しつつ機械にダメと言われたことを説明すると、職員の方も困惑しながら、「では、そのままでどうぞ」となりました。
(いまだに機械にダメと言われた理由が分かっていないけど、東日本から西日本に跨った移動だからかなと思っている)

窓口で色々と話した結果、広島乗り換えと大阪乗り換えの2案が出て、今日のうちでなるべく西にたどり着いておきたいということで、広島乗り換えにしました。
ただ、それでも今日で長崎までたどり着くわけではなかったので広島に一泊し、鹿児島まで新幹線、その後電車にすることにしました。

内定式中も同期や人事の方々と台風やばそうですねという話をしつつ解散しました。
そしたら、ちょうど同じ時間帯に新幹線で同じく西に行く予定の同期の人と一緒に向かっていると、
「これやばそうですね」と言われつつあるTwitterの写真を見せてもらいました。
そこには人としか見えないんじゃないかというくらいの人数のいる現在の駅の様子が写っていました。
この写真を見て、正直「あ、詰んだ」と思いました。

新幹線移動

それから同期の人とは別れ、駅のホームに行くと本当に人だらけで、歩ける余裕もほぼないような状態でした。
この時、ふと飛行機の時刻表を見るとこれから向かえばギリギリたどり着くかどうかの便があってそれに切り替えるべきかどうかをめっちゃ悩みます。
とりあえず、親がそういった交通系に詳しかったので電話で相談します。が結局新幹線で向かうことになりました。

指定席の席と席の間にも人が立って乗るくらいに人が多い状態ではありましたが、なんとか乗ることができました。
品川-広島間では自由席のチケットしか取れなかったので、mitoも立ちながら乗っていました。
そう、ずっと立ったまま3~5時間くらい(精神的にもだいぶ辛かったし遅延とかもしてたからちゃんとした時間は覚えていない)過ごしました。

分かる人にはわかると思うのですが、漫画「メジャー」海堂の夢島編で、ただ立っているだけのトレーニングがあって、それを見てた時は「へー、立ってるだけでこんなに辛いんだ〜」くらいの気持ちだったのですが、実際にやって分かったことは冗談抜きでめちゃめちゃきついということです。
幸い、mitoが立ってた場所はわりとスペースがあったので荷物を床に置くことができていたのでまだ楽でした。

スマホの充電残量が微妙だったこともあり、ほとんどスマホを触らず、音楽も何も聴かず、本も持っていない状況でただひたすらつくのを待っていました。
たまに現在位置を調べてどこまで来ているのかを見ていましたが、前に見た時より全然進んでいるように見えなく、辛い気持ちになっていました。ただ、調べてなかったらなかったでまた別の辛さがあったと思います。

広島駅まであと一駅になると立っている人たちももう座る人もいないと、空いている席に座り始め自分も座ると、座るってこんなに素晴らしいことなんだなと感じました。
それからまたしばらく経って、広島駅に着いたのがだいたい日を跨いだくらいだったはずです。
新幹線に乗り始めたのが19-20時くらいだったはずなのでそういうことです。
疲れたから早くホテルで休みたいという気持ちもありつつ、せっかく初めて広島に来たのだから少し見てまわりたいな気持ちもあったが時間も時間だったので、休むことにしました。

明日の朝食や小腹のためにコンビニに行くと広島カープのグッズコーナーで一棚あったことと、閉まって入れなかったのですがカープロードみたいなのがあったことにすごいなと驚いたのが広島での唯一の思い出です。
もう少し早くついていれば、近辺だけでも散歩したかったなというのが本心です。

翌朝

結構早めの新幹線でしたが時間に余裕を持って駅につきました。
ただ、自分がついていても新幹線がついているとは限らず...
台風はまだ本州上陸していないが関西の方にはもう風の影響が出ていてそこからくる新幹線だったので、だいぶ遅延していたみたいです。
この間に駅構内でお土産を物色します。
この頃には、また台風の進路が変わっていて関西方面に上陸する予定になっていたので、大阪ではなく広島に降りたことが救いになってました。

実は広島から自分が乗る新幹線は直接鹿児島まで行くわけではなく博多駅で乗り換えでした。ちなみに乗り換える新幹線の名前は「みずほ」です。
乗り換えの時間が到着予定から1時間程度だったので心配してましたが、心配しても新幹線が速くなるわけではないので、諦めて待っていました。
結果として博多駅に着いたのは、乗り換え予定時間から30分ほど経ってからでした。
新幹線の中で乗り換え予定時刻が過ぎた時は心底焦っていました。

乗る予定だった新幹線はもう出発してしまっただろうな、どうしようと悲しみつつ、一縷の望みをかけ駅員さんに聞くと「どの新幹線が出発したとかはわからないけど、全体的に遅延してるから行ってないかも」と言われ、勝手に駅員さんは何時の便が出てるとか把握しているもんだと勝手に思っていたので意外でした。(まあ考えてみればそういったこと全て把握しているのは大変か)

どこに行けば何が出発したとか知れるんだろうと思いつつ駅内を歩いていると、電子掲示板が見えました。
そこには、「みずほ」の名前はあれど、乗る予定の号数はありませんでした。
しかし、自分が乗る予定のものよりも早い時間に出発予定のものが遅延で出発していなかったので少し希望を持ちつつ、表示されるまでチームメンバーへのお土産を探していました。

しばらくして、もう一度電子掲示板を見に行くと...
>みずほ n号車<
この時、心の中で「みずほぉぉぉぉ!」と叫んでしまいました。
ちなみにみずほという名前に関して知っていることは艦これの瑞穂だけだったので、頭の中はそればっかになっていました。
この出来事から「みずほ」っていう名前が結構好きになりました。

それから鹿児島につけるという安心でお土産を見て回ってました。

鹿児島到着

鹿児島についてからはもう安心しきっていて電車も一本でいけたので、美味しそうなサンドイッチ店でサンドイッチとコーヒーを買って悠々と電車を待っていました。

電車に乗っている途中で綺麗な海が窓から見えて「いいな〜」と思っていたら、テレビでしか見たことないような海のすぐそばにある人気もない駅で電車が止まり、「全て投げ出してここで降りたい!」って思ったのはここだけの話。
電車を乗ったことがあるのが東京都内だけだったので、こんな海のすぐそばや自然に囲まれつつ電車で移動するという体験は初めてだったのでとても楽しかったです。

そして、会場の最寄駅についたときに最後の事件が起こります。
その駅では、交通系ICカードが使えなかったのです。
完全に想定していなかったので驚いていると、周りにいた高専生らしき集団も同じように戸惑っていました。
教員らしき人がいて学生らしき大人数だったのでプロコンに参加する高専生だろうな〜ってわかりやすかった。
そこから徒歩で、取られている宿泊地に向かいました。

かくして、mitoは台風とすれ違いつつなんとかみんなの待つ宿泊地にたどり着くことができました。
その後も休む間もなく色々とありましたが、それはまた別のお話。

最後に

ここまでの長文を読んでくださりありがとうございます。
これが、mitoの移動部門のほぼ全てです。
次はいよいよプロコン当日の話になるのですが、それを書ききるのはいつになるでしょうか。
mitoの次回作にご期待ください!

mito.

DIの話

この記事はICT Advent Calendar14日目の記事です。

前日はnemu_souでした。
何か作ったらしいのでえらいですね()。

nemu-sou.hatenablog.com

こんにちは、mitoです。

みなさん、DIしてますか。

DIとは

Dependency Injection のこと

DIとは、コンピュータプログラムのデザインパターンの一つで、オブジェクトなどの間に生じる依存関係をオブジェクト内のコードに直接記述せず、外部から何らかの形で与えるようにする手法。(IT用語辞典)

「依存性の注入」とよく言われています。

依存性とは

ここでいう依存性というのはあるクラス内で他のクラスを利用している状況のことです。
例えば、Aというクラス内でBクラスを利用しているということがあったとします。

class A {
    val b: B = B() // インスタンス化

    fun hoge() {
        b.greeting()
    }
}

class B {
    private val text: String = "Hello, DI"

    fun greeting() {
        print(text)
    }
}

こういう状況でAというクラスの動きにはBというクラスが必要になって、Bクラスがなかった場合にAクラスは機能しません。
これが依存で「AがBに依存している」と言われてます。

ただ、依存という言葉自体にあまり良いイメージはないと思います(薬物...?)
実は英語版のDependency injectionのページには

A "dependency" is an object that can be used

とあり、訳すと「"Dependency"は使用できるオブジェクトです」
そう、オブジェクトです。
オブジェクト指向でのオブジェクトと捉えて問題ないと思います。
そう考えると考えやすくなるかと。

注入とは

注ぎ入れること。つぎこむこと。(Google検索結果)

つまり

あるクラスに対してそのクラス内で使っている他のクラス(オブジェクト)を外部から注入・渡してあげるという感じです。

↑の例ではAクラスの中でBクラスをインスタンス化(生成)させて使っているので、外部から注入されていません。
これに対して、外部(他クラスなど)から入れて・渡してあげることです。

外部って誰?っていう気持ちになるかもしれませんが、今のところはあまり気にしなくてもいいです。(一応書いておくと、Aを使おうとしている他クラスだったりDIコンテナだったりです。)

DIの種類

DIというのは上記の説明のようにパターンの名前でしかないので、それを実現するためにはいくつか種類があります。
- Constructor Injection
- Setter Injection
- DIコンテナを使う

Constructor Injection

コンストラクタ(Constructor)で渡してあげる方法です。

class A(val b: B) { // コンストラクタで渡す
    fun hoge() {
        b.greeting()
    }
}
// Bクラスは上記のコードと同じ

Setter Injection

セッター(Setter)で渡してあげる方法です。

class A(val b: B) {
    lateinit var b: B // セッターを使って後で渡す

    fun hoge() {
        b.greeting()
    }
}
// Bクラスは上記のコードと同じ

DIコンテナを使う

DIコンテナと呼ばれるDIを実現してくれるライブラリのようなものです。
DIコンテナには多く種類がありそれぞれ使い方も全然違うのでここでは説明しないです。

なぜ使うのか

よく言われているのは - テストがしやすくなる
- 柔軟になる

ただ、これを聞いただけではへ〜そうなんだになると思います。(自分も前まで利点は知っていたけどそうなんだくらいにしか思ってなかった)

テストがしやすくなる

Bをモック化してAのテストがしやすくなります。
モックに関しての話はテストの話になってくるので省略するのですが、AクラスがBクラス内のgreeting関数をちゃんと実行できているかなどを試すことができます。

柔軟になる

今、Bクラスをインスタンス化するには、B()だけで済んでいますが、もしBクラスのインスタンス化に仕様変更が入ってめちゃくちゃ長かったり複雑だったりした場合(良い例が思いつかなかった)に、Bクラスをインスタンス化して使っているクラス(例ではAクラス)全てのインスタンス化部分を書き直さないといけなくなります。

他にもいろいろな利点や欠点があるのですが、そこは調べてください。

最後に

今年度で高専も卒業ということで、それに関する記事はまた2,3月くらいにでも書こうと思います。
卒論を書き終わった頃には技術に関する記事をまた書いていこうかなとも思っているので、卒研頑張ります。

翌日は、ねるねるです。
サーバーサイドに強いっていう印象だったけど、プロコンの時にAndroidの話をしていた気がするなって思っています。
翌日からTNG Weekみたいです。

neruneru0419.hatenablog.com

プロコン本戦参加前

はじめに

 私たち、マンゴーごはんは#procon30にGooTravelという、オフライン環境下でのインバウンド客のサポートをするスマートフォンアプリで自由部門にて参加しました。

4月前

 チームが決まりました。
 自分がチーム決め前の面談時に出したリーダーはやりたくないという希望を考慮していただき、リーダーではなかったです。
 メンバーは
- ウエハラ(2年)
- りんぱんまん (5年)
- 漆黒のキャサリン(3年)
- mito(5年)
- たぴおか(1年)(後に合流)

でした。
 1年生のたぴおかは入学後に加入することになります。
 この頃は、去年予選落ちしたmitoとりんぱんまんがいるけど大丈夫かな〜、でもウエハラは結構喋るしキャサリンも去年結構喋るチームにいたしなんとかなるかな〜くらいに考えていたと思います。
 ちなみに、チームリーダーはウエハラでした。
 2年生でチームリーダーの経験がない状態で、学年もバラバラなチームのリーダーをうまく勤めてくれました。:crap:
 さすが委員長

 ちなみに、チーム名のマンゴーごはんに関してなんですが、これはキャサリンが好きと言っていたタイの料理らしいです。
 調べたところ、味付けしたもち米にマンゴーをそのまま乗っけて提供する屋台とかで出るような食べ物らしいです。
 一度、メンバーみんなで食べてみたいんですが、日本で食べれる場所ってあるのかな???(作るしかない??)

始まったアイディア出し

 出ないですね...
 いろいろなアイディア出し方法を試してみたんですが、プロコン向けなアイディアは全然なかったです。
 その中でもいまだにずっと印象に残っているアイディアがあって、アイディア出しの序盤くらいで出た、「粘着テープのようなものでサッカーボールを作って、それを子供に遊んでもらってゴミ回収をする」というものです。
 このアイディア、IT要素もなく粘着テープなボールをどうやって蹴るんだ...って感じですよね、楽しそうだけど。

沈黙のアイディア出し

 これは他の人の記事にも書かれるであろうことなんですが、本当にアイディア出し中喋る人があまりいなくて、mitoが無理やり喋ろう・しゃべらなきゃって考えていました。(結局あまりしゃべれていない)
 正直、mitoは自分が積極的に喋るというより喋っている人たちの話を整理することの方が性に合っていると思っているので大変でした。(去年含む)
 そこから出ないまま時が流れ、企画書提出締め切り約1週間前くらいになっていたと思います。
 時間もないということで、去年一昨年あったアイディアを新しく練り直し企画書も修正していきました。

企画書作成

 時間がありません!
 仕事を結構分担して作業していたのですが、それぞれの進捗は良くなく本当に終わるんか...?って感じでした。
 今見てみると、提出期限2日前の水曜日時点で、企画書全体の構成が確定していない・システム名決まってない・ロゴ完成していない・背景とニーズやばい・もう確定して色変更するだけな状態が開発計画とアルゴリズムの2枚(12枚中)・システム構成の矢印やばい・etc...
 今だから言えることで、この時期に自分のタスクにそこまで余裕があったわけではないのですが、mitoが全部やってしまわないといけない・終わらないのではと一人で考えて悶々としていました。
 結果的にはmitoがほとんど書いてしまうということもなく完成しました。
 結局今年度も自分たちのチームが一番遅くまで作業していて20時くらいに学校から帰り、最終版を提出したのは23時とかだったと思います。
 でも19時くらいには一通り終わって、チームメンバー全員で通しで流れを見た記憶があるので、去年よりはマシだったかなと思います。(正直、去年がどんな感じだったか覚えていない)

結果発表

予想

 正直、通るやろ!笑くらいの気持ちでした。
 はい、去年もそう思っていた節はあるのであてにならないうえに若干嘘ですね。
 確かに通るんじゃないかと思ってはいたけど、それ以上に落ちるとも思っていました。
 それは自分たちのチームだけでなく、うみまもると競技以外は落ちるとまで思っていました。
 GooTravelとunihomeはそれぞれ部門が違う感じが提出前からしていたので、それで落とされるのではないかと思ってました。(これは結果が出た後にるいことも話した記憶)

予選結果

 受かるとも落ちるとも思っていたので、結果発表の時はソワソワしてて結果を見て、自由部門に沖縄の文字が見えてめっちゃ嬉しかったし、課題部門見ても2チームとも通っててさらに嬉しかったです。
 それから少し経ってPCKの結果を見て、全チーム通過が決定しそれも嬉しかったです。

開発期間

mitoの考え

 企画書を書いている時点、なんならアイディア出しの時点でmitoは、「今年の開発はガチガチに設計など組んでガチ開発をしてやろう」と考えていました、そう考えていたんです。
 なので、他のメンバーには実際に開発をしてもらおうとしていた機能に似た機能を持つアプリの勉強を兼ねて開発をお願いしておき、自分はその間にどう設計を組んだら良いかどういう開発方針がいいかをいろいろ考え、GitHubのREADMEにひたすら書いていました。
 設計や開発方針を色々と考えていたのは、チームメンバーがAndroidに限らずチーム開発をあまりしたことがなかったため、つまづいてしまわないようにとmitoが開発しやすいようにという目的がありました。(最後は自己中)
 この時に、前にインターンシップでお世話になったメンターさん(ぎあもとさん)やぱらぱら、nemu_souなどにどういう風に開発を進めていけば良いか相談に乗っていただいていました。ありがとうございました。

開発はじめ

 開発では一番最初に、ConstraintLayoutというレイアウトの組み方を教え実際に体験してもらい、使えるぐらいにはマスターしてもらえたはずです。その後、Android開発の仕方(主に、ライフサイクルやリソースファイルに関して)を教えて、あとは各々に開発のヒントを出して調べながらやってもらうという方法で進めました。このときに、その開発期限を明確にしなかったのが問題の始まりではなかっただろうかと考えてます。
 開発期限を明確にしなかったのには一応理由があって、自分以外がAndroidアプリ開発ほぼほぼ初めてでどれくらいでその機能を調べながらできるかの予想ができず、自分の頃を思い出そうにも自分の場合は学業など他のことを気にせず集中してやっていたし3年以上前のことであまり覚えてなく参考にならなかったです。
 なので、時々進捗を聞いてどれくらいの期間で終われそうか各々決めていこうとしました。

進まない進捗

 そして、進捗を聞くと、
「まだ調べきれていないです」→「お、頑張れ〜」
「調べはしたんですがわからなくて」→「どこがわからない?」
「他が忙しくてあまり進捗生やせていないです...」→「プロコンだけが全てじゃないしな、頑張れ〜」
「一応書いたんですけど、なんかうまく動かなくて」→「コードをGitHubにあげて、見るから」→「あげます(あげるとは言っていない)」→「あげた?」→「あげていないです、あげます(あげるとは言っていない)」
みたいな感じで、想像以上に進んでいなかったです。何が悪いんでしょうかね(mitoが甘い)

嬉しい誤算

 その中でも、一番嬉しい誤算だったのがたぴおかです。
 彼女は一年生ということもあったので、mitoも周りもとりあえず開発やプロコンの雰囲気とかに慣れてもらおう、本人がやってみたいということ(プロコンに関すること)を優先的に挑戦してもらおうくらいの気持ちで考えていました。
 それで、本人に聞くと「コードが書きたい」ということだったので、最初に一番簡単な機能のタスクを与えました。
 すると、なんということでしょう。
 たぴおか「完成しました、プルリク投げました」
 mito「一番最初にプルリク投げてきて、それも完成して修正するとこもそんなないやんけ、ウケる」
 こんな感じでした。(多少の誇張や捏造はあります)
 そう、一番最初にプルリクを送ってきて、一番最初にタスクを終えたのです。(mitoを除く)
 この時は本当にびっくりして、素直にすごいと思いました。
 その後、まだコードを書きたいと言っていたので、少しずつ難易度を上げながらタスクを振っていったのですが、それらをことごとく、「完成しました、プルリク投げました」っていうので、超優秀だと思いました。
 そして、最終的にはりんぱんまんに振っていたタスクに近いレベルのタスクを投げても終わらせてきたので本当に驚き。
 mitoの50を超えるコードレビューに対しても折れることなく全て修正してきました。(優秀)
 このころあたりから、同級生とかと「1年生ってプロコンでこんなにコード書いたりタスクこなしたりだったけ?」という話を何回もした記憶があります。
 ここではたぴおかの話しかしてませんが他のチームの1年生である、きしりん・2tf・らずも優秀だと思ってます。
 たぴおかには開発以外でもアプリアイコン作成をやってもらいました、良いアイコンになったと思います。(若干横にずれてるけど)

他チームの方が聞きに来る状態

 夏休み後半や終わったあたりから、チームりんごのベーコンのるいこやきしりんからAndroidアプリ開発に関しての質問が飛んできて、自分のチームメンバーよりも多く質問され答えた覚えがあります。
 この時に、がっつりと質問に関する開発を教えながらうまく進めることができなかったのですが、そのツケが後々来ることになります...

結果

 Androidアプリ開発をmitoはずっとやっていたので、今回のプロコンの開発は例年よりスムーズに進んでいって、プロコン出発前にはデモで見せるような機能はほとんど出来上がっている状態でした。
 実際、本戦でのデモの前もデモ用のデータを追加したり少し修正したりくらいで済みました。
 ただ、本来であればそうでないといけないだろうし、mito的にももっと早めに一通り終わらせる予定だったのでそこは残念でした。

提出書類作成(操作マニュアルや動画、パンフレット原稿)

 基本的に、ウエハラにお願いしてそれっきりでした。
 例年通りみたいな結果になってしまって、申し訳なかったです。
 ベースをウエハラに書いてもらって、それをmitoやM教授が添削して〜っていう感じを繰り返していました。

チーム紹介動画

 チーム紹介動画に関しては、短い動画をいくつか撮ってそれをisatakuに投げて編集してもらいました。
 istakuには、この紹介動画以外にもプレゼン中に使う動画も作ってもらいました。
 編集がめっちゃ上手くて助かりました、ありがとうございます。
 この動画ではmitoとりんぱんまんがリフティングしてウエハラとたぴおかが話をした後に、mitoがチームメンバーに設計の話をしているところがあります。

プロコン行くまでの総括

 楽しかったです。大変だったけど

動かないSlackのチャンネル

 チーム結成からプロコンに行くまでの期間中、チームのSlackチャンネルでの発言がとても少なく、喋っているのはmitoかウエハラだけという状況がずっと続いていました。
 最初の方はまだ打ち解けていなかったのもあったと思うんですがあまり話し合い等は活発的ではなく、集まりもほとんどないような状態でしたがプロコンが近くなるにつれて自然とSlackでコメントする人も増えていって雰囲気も良くなってきていたと思います。(アイスブレイク大事ですね!)
 チーム開発やコミュニケーションなどで多くの問題点や課題が発生していました、それらに関しては都度、他のメンバーにもどうなっているかどうした方が良かったかというのを話していっているので、来年以降に活かされることを願っています。

やったこと

 今回のプロコン本戦に行くまでの期間で、mitoはメンバーに対してひたすらこれやった?これ今から考えなくていいの?という役割と進捗管理をずっとしていました。
 思っていたより、みんなやるべきこととか見えてなくて忘れてたり楽観視してたりしていました、それをmitoが問い詰めるみたいな形になっていたので、特にリーダーはリーダーとしての役割ができていないと結構落ち込んでしまっていたのですが、今年の経験を覚えて次に活かしてくれれば良いと思います。

最後に

 お気づきの方しかいないと思うのですが、この記事ではまだプロコンに行っていません!(表現が合っているのか微妙)
 なので続きの記事が存在します。それも2つ
 残りの記事は
- 高専プロコン移動部門
- 高専プロコン当日
 の話です、今から書くのでしばらくかかります。 (申し訳ないです。)
 お楽しみに!