Cookpad TechConf 2019 資料一覧
※こちらはQiitaから移動してきた記事です。
------------------------------------------------
Cookpad TechConf 2019に参加してきました。後日スライドと動画は公開されるとのことですが、現在公開されてる資料をまとめておきます。
【追記】
公式で公開されました→Cookpad TechConf 2019
資料一覧(敬称略)
13:05 - 13:25
宇野 雄
クックパッドが目指す、これからのデザインとプロダクトのあり方 - Speaker Deck
↓ご本人の解説
https://note.mu/saladdays/n/n5e914ab0f108
13:25 - 13:45
長野 佳子
Cookpad TechConf 2019 CookpadMart - Speaker Deck
13:45 - 14:05
須藤 耕平
料理の学習体験をデザインする
14:05 - 14:25
藤井 謙士朗
Cookpad TechConf 2019 Komerco Service Dev - Speaker Deck
14:35 - 14:55
渡辺 喬之
Challenges for Global Service from a Perspective of SRE 2nd season - Speaker Deck
14:55 - 15:15
伊尾木 将之
レシピを解析する!Machine Readable Recipe(MRR: 機械可読なレシピ)の開発
15:15 - 15:35
渡辺 慎也
クックパッド動画事業開発のチャレンジ
15:50 - 16:05
三木 康暉
Cookpad TechConf 2019 〜霞が関〜 クックパッドiOSアプリの 破壊と創造、そして未来 - Speaker Deck
16:05 - 16:20
水谷 正慶
スケーラブルなセキュリティ監視基盤の作り方 /techconf2019-mizutani - Speaker Deck
16:20 - 16:35
宇津 宏一
新規アプリ開発を支えるユーザ・決済基盤 - Speaker Deck
16:35 - 16:50
小杉山 拓弥
Re:silience から始めるカオスエンジニアリング生活 / A Life of Chaos Engineering Starting with Resilience - Speaker Deck
17:00 - 17:30
成田 一生
基調講演
17:40 - 18:20
LTセッション(見つけた順で追加更新)
クックパッドiOSアプリのパフォーマンス改善 - Speaker Deck
個人的感想
トップバッターの宇野さんが
「デザインはユーザーにとっての入口で、そこが悪いと中身がどんなに良くても使ってくれない」
「これからは(も?)全員でデザインを作り上げていく時代」
と言っていたこともあってか、デザインの話が多かった印象です。
デザインは専門外なので、新鮮な気持ちで聞けました。
Figmaが熱く推されてました。気になるな…
あと、「毎日の料理を楽しみにする」というミッションに向けて全力で取り組んでいるのを発表からもひしひしと感じました。
あそこまで料理について深く考察することなんてあっただろうか…
技術的なことはもちろん、料理を見つめ直す意味でもとても有意義な時間でした。
(LTセッションでRubyフルコミッタの方たちが登壇されるってどういうことなの…(困惑))
Cookpad TechConf 2019に参加しました。
Cookpad TechConf 2019に招待枠で参加してきました。持つべきは友。
つぶあんちゃんをモフりつつ、いざ恵比寿へ
タイムテーブル
Qiitaで資料一覧を投稿したので、こちらを参照してください。
それぞれのセッションに対する感想
クックパッドが目指す、これからのデザインとプロダクトのあり方
つい最近Yahooから入社された方(17営業日でConference登壇とかすさまじい…)。
詳しい内容はご本人のNoteを見るのが一番いいと思います。
デザインの話が中心、しかしデザインに全然明るくない私でもわかりやすく、納得感がある説明でした。
「らしさ≠見た目が同じ」であり、らしさを出すには「期待値に対するふるまい」が共有されていることが大事、というのはなるほどな~となりました。
わしエンジニアだしデザイナーじゃないし勉強せんで良いわ、とならずにこっちの知識も取り入れようと思った次第。
生鮮ECクックパッドマート - サービスの立ち上げから拡大に向けて
クックパッド・マートは正直サービス内容を知ったのは今回が初めてです。(名前は聞いてた)
検証がかなり地道な作業で驚きつつ、その結果に対する分析力の高さは凄いなと感じました。
料理の学習体験をデザインする
日々の料理を考える上でのあるあるがめっちゃ出てきて聞いてる間何度もうなずいた。
我々は「家にあるもので何も見ずにパパっと作れる人」になりたいのだ。
何をもって料理スキルの上達とするかを定義するにあたり、
食材 + 味付け、調味料 + 調理方法
として色々な課題をクリアする方式にしたのはうまいなーと感心しきりでした。
新規サービス開発を加速させる技術とデザイン
最初のセッションでもおすすめされていたFigmaを導入して、スピード感が増したという事例。
スピードが求められている時に現状のプロセスを変えることに着手した勇気と、それを実現させた努力が素晴らしいです。
Challenges for Global Service from a Perspective of SRE 2nd season
Cookpadこんなにグローバル展開してるんだとお恥ずかしながら初めて知りました。
「1行のログの向こうには、1人のユーザーがいる」はなかなかエモい名言。
レシピを解析する!Machine Readable Recipe(MRR: 機械可読なレシピ)の開発
「分量:ウィスパー ジバニャン」の衝撃(実際にある)。
材料
— みーた▽UX Engineer (@earlgrayMK) February 27, 2019
ウィスパー、ジバニャン見つけた👀
#CookpadTechConf pic.twitter.com/Ug1YOcPJmE
IoT家電がCookpadのレシピを理解して自動でそのとおり料理できる、という未来につながるかもしれない夢のある技術です。
クックパッド動画事業開発のチャレンジ
スーパーでよく見かけるCookpad storeTVの広告配信制御のお話でした。
専門外技術でついていくのが難しかった。。。資料公開求む。
〜霞が関〜 クックパッドiOSアプリの破壊と創造、そして未来
タイトルがすごい(小並)。
お台場とか霞が関とかプロジェクト名に地名を使う文化があるんですかね?
内容はアーキテクチャの見直しとObjective-Cの撲滅。大きなサービスだとアーキテクチャもカオスになるんですね。。。
スケーラブルなセキュリティ監視基盤の作り方
なかなか聞くことができないセキュリティの話。
こういうアラートって、単純にメッセージコードをトリガーにしてアラート発報だと思ってました。。。
全部拾ってると精神が摩耗してしまう→だから必要な物だけ拾えるようにロジックで制御しよう!という流れ。
これも難しかったので復習したい。
新規アプリ開発を支えるユーザ・決済基盤
Cookpad.apk #2でも登壇されていた宇津さん。
今回はAndroidではなく決済やアプリ内課金の機能を共通化するcuisineの話でした。
個人アプリ開発ではめったに触らない分野なので難しかった。(さっきから難しいしか言ってない)
Re:silience から始めるカオスエンジニアリング生活
カオスエンジニアリングってなかなかのパワーワードですよね。
簡単に言えばわざとシステムに悪いことして、それに耐えられる作りにしましょうという手法(予防接種的な考え)。
これがマイクロサービス化するとそのマイクロサービス間での関係性(Known-Unknownsとか)が絡んでくるという。。。
基調講演
最後はCTOによる講演です。
定款に「毎日の料理を楽しみにする」「全世界で実現出来たら解散」って書くことの凄さ。
「なぜ毎日の料理を楽しみにするのか」というミッションに対する疑問を主軸に話が進みました。
料理する=自分が摂取するものをコントロールできるってのは確かにそうで、外食ばかりだと意識しないうちに凄まじい塩分、糖分を摂取します。
(店の味にするには引くほど調味料使う)
じゃあそのミッションを実現するには…?ってのを考えた結果がどんどん発表されている新規サービスなんだ、と理解できました。
なかなかエモい講演でした。
お待ちかね懇親会
流石Cookpadというクオリティでした。全部美味しい。
また来年も参加したいと思えるConferenceでした。
すごいぞTapTargetView
Qiitaで記事書きました↓
https://qiita.com/hammer0802/items/b17afe4ee25bc3c3723b
Material Designな動きになります。
(2020/03/26)
Qiitaから持ってきました↓
--------------------------------------
TapTargetViewって何?
こんな感じにAndroidアプリの機能やボタン説明をおしゃれに紹介できるライブラリです。(配布元より転載)
これによって、何の機能が、どのボタンを押せば利用出来るか、ユーザーが直感的に理解できます。
以下のGitHubリポジトリで配布中
導入方法
app配下の`build.gradle`に以下の定義を追加するだけです。簡単。
repositories {
jcenter()
}
dependencies {
implementation 'com.getkeepsafe.taptargetview:taptargetview:1.12.0'
}
使い方
私が作成したサブウェイのサンドウィッチレシピを作って保存するアプリでも、初回起動時にこのTapTargetViewを使ったチュートリアルを実装してます。
今回はそのコードを見てみましょう。(言語はKotlinです)
//シーケンスに実行したい場合はTapTargetSequenceを使用
val sequence = TapTargetSequence(this) //Activityの指定(今いるActivityならthis)
.targets(
TapTarget.forView(findViewById<View>(R.id.create), "まずはこちらのボタンを押してレシピを作成しましょう!") //Target対象のView(第一引数)とタイトルテキスト(第二引数)を入力
//以下オプション
.outerCircleColor(R.color.colorPrimary) //外円の色
.titleTextColor(android.R.color.white) //タイトルテキストの色
.drawShadow(true) //影の有無
.outerCircleAlpha(0.97f) //外円の透過度
.cancelable(false) //外円の外を押したらキャンセルできるかどうかの指定
.tintTarget(false) //Target Viewに色をつけるかどうかの指定
.id(1), //シーケンスID(順序性の指定)
TapTarget.forToolbarOverflow(toolbar, "操作方法を忘れた場合はこちらをクリック!", "もう一度チュートリアルを見ることができます。") //第三引数は説明テキスト
.outerCircleColor(R.color.colorAccent)
.titleTextColor(android.R.color.white)
.descriptionTextColor(android.R.color.white) //説明テキストの色指定
.descriptionTextAlpha(1.0f) //説明テキストの透過度指定
.drawShadow(true)
.outerCircleAlpha(0.97f)
.cancelable(true)
.id(2)
)
sequence.start() //実行
上記以外のオプションもあり、配布元で確認できます。
実行すると…
こんな感じ↓
https://qiita-image-store.s3.amazonaws.com/0/292799/169d47f5-4a7f-c9f7-afd2-7cfce4cc9c66.gif
終わりに
手軽にスタイリッシュ感が出るので、興味のある方は試してみてください。
SUBWAYシミュレーターのプライバシーポリシー
序文
hammer's labの提供するアプリ、SUBWAYシミュレーター(以下本アプリ)は、一部ストレージを使用する機能があります。また、広告配信のためにGoogle AdMob、利用状況解析のためにGoogle Firebase Analyticsを使用しています。
以下はその使用に関するプライバシーポリシーを示すものとします。
ストレージ権限について
本アプリでは、アプリ内で作成した画像保存のためにストレージを使用します。画像は内部ストレージに保存されます。
上記以外にストレージの使用はしません。
広告について
本アプリでは、広告配信ツールとしてAdMob(Google Inc.)を使用しており、AdMobがご利用者の情報を自動取得する場合があります。取得する情報、利用目的、第三者への提供等につきましては、以下の広告配信事業者のアプリケーション・プライバシーポリシーのリンクよりご確認ください。
・Google 広告に関するポリシー
https://policies.google.com/technologies/ads?hl=ja
利用状況解析について
本アプリでは、今後の開発の参考とするため、アプリの利用状況データを収集するツールとしてFirebase(Google Inc.)を使用しており、Firebaseがご利用者の情報を自動取得する場合があります。取得する情報、利用目的、第三者への提供等につきましては、以下のGoogleプライバシーポリシーのリンクよりご確認ください。
・Google プライバシーポリシー
https://policies.google.com/privacy?hl=ja
法令、規範の遵守と見直しについて
hammer's labは、保有する個人情報に関して適用される日本の法令、その他規範を遵守するとともに、本ポリシーの内容を適宜見直し、その改善に努めます。事業内容の変更、法令の改正等により、事前に公表することなく任意の時期に変更される場合が有ります。
個人情報の第三者への開示・提供について
ご提供いただきました各種情報は、次のいずれかに該当する場合を除き原則として第三者に提供することはありません。
- 利用者様の同意がある場合。
- 法令に基づき開示を求められた場合。
- 司法または行政機関から開示を求められた場合。
お問い合わせ
プライバシーポリシーに関するお問い合わせは、 hammerxhammer0802@gmail.com までご連絡ください。
複数チェックボックスでチェックがついてるものの値だけ加算する
○○という名前のcheckbox項目がチェックされたら、○○がmapコレクションで紐づいている数値を加算し、逆にチェックが外れたら減算する(≒合計値を元の値に戻す)というコードを書いてみました。
配列とマップ関数はこんな感じ
//チェックボックスに表示する文字列の配列 val hoges = arrayOf( "フガ", "ムニ", "モチャ", "ニャー" ) //view名からIDを取得するためのマップ関数 val hogeMap = mapOf( "フガ" to "huga", "ムニ" to "muni", "モチャ" to "mocha", "ニャー" to "nya-" ) //チェックボックス項目に紐づいた値を設定するマップ関数 val hogePrices = mapOf( "フガ" to 100, "ムニ" to 200, "モチャ" to 300, "ニャー" to 400 )
あと、レイアウトファイルにはチェックボックスを項目数分用意し、IDを「checkBox + (hogeMapで設定した文字列)」となるようにネーミング。
例)ID : checkBoxhuga
for文を使ってhogesの項目名をチェックボックスに設定し、クリックしたらチェックされているチェックボックス項目に紐づいた数値を加算します。
私が作っているアプリではスピナーの値とチェックボックスの合計を加算してTextviewに表示してます。
//チェックボックスの合計値を入れる変数を宣言 val checkPrice = 0 for (hoge in hoges){ //レイアウトファイルのチェックボックスのViewIDを取得 val viewId = resources.getIdentifier("checkBox"+ hogeMap[hoge], "id", packageName) //findViewByIdでviewIDの紐付け val checkbox = findViewById<CheckBox>(viewId) //デフォルトをfalseに設定 checkbox.isChecked = false //チェックボックスに表示する文字列をセット checkbox.setText(hoge) checkbox.setOnClickListener(View.OnClickListener{ //クリックするたび合計値は0にする hogePrice = 0 //再度hogeの項目数分forを回す for (hoge in hoges){ val viewId2 = resources.getIdentifier("checkBox"+ hogeMap[hoge], "id", packageName) val checkbox2 = findViewById<CheckBox>(viewId2) //チェックされている項目であれば、数値を合計値に加算する if (checkbox2.isChecked == true){ checkPrice += hogePrices[hoge].toString().toInt() //map関数の戻り値はint?型なので、int? -> string -> intに変換が必要 } } //スピナーの値とチェック合計値を加算してsetText val sum = spinnerPrice + checkPrice price.setText(sum.toString())
最初は以下のような、全体の合計値を先に変数宣言してから、都度加算や減算するやり方でした。
if (checkbox2.isChecked()){ totalPrice += hogePrices[hoge].toString().toInt() }else{ totalPrice -= hogePrices[hoge].toString().toInt() }
ただ、これだと
スピナーの値をtotalPriceに代入(≠加算)
→チェックボックスを何個かON
→スピナー項目を変更(ここでtotalPriceがリセットしてスピナー項目の値そのものになる)
→チェックボックスをOFF
とすると、スピナー項目の値からチェックボックスの値分減算して想定より値を低く出せてしまうことが判明。
直前のスピナーで選択されていた項目を参照するやり方が見当たらないので、スピナーを変更したらチェックボックスを全部OFFにする対応策を考えたものの、ユーザーフレンドリーじゃないなと思い無事お蔵入りに。
ケースバイケースですが、こういう風に変更した部分だけ再計算するより、全体の値を再計算するとうまくいけるという学びがありました。
Spinnerを関数化して使い回そう
1画面で複数のSpinnerを使って選択出来るようにしたかったのでやり方を調べたが、検索してもヒットするのは1画面にSpinner1個を作る方法のみ…
しゃあないので色々試行錯誤してみました。
【参考】
スピナー(Spinner)を使用するには - 逆引きAndroid入門
文字列からリソースIDを取得する
【前提条件】
「array1」「array2」という配列と、「spinner1」、「spinner2」というIDのSpinnerを用意
【ソースコード】
class MainActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fun spinner(itemArray: Array<String>, spinnerName: String){ val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, itemArray) adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) //引数のStringを使ってリソースのViewIDを抽出 val viewId = resources.getIdentifier(spinnerName, "id", packageName) val spinner = findViewById<Spinner>(viewId) //アダプターを設定 spinner.adapter = adapter // スピナーのアイテムが選択された時に呼び出されるコールバックリスナーを登録 spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { val spinner = parent as Spinner } override fun onNothingSelected(arg0: AdapterView<*>) {} } } spinner(array1, "spinner1") spinner(array2, "spinner2") } }
※はてなってKotlin文法の自動彩色対応してないのね…