▼前半part.1こちらから▼
https://qiita.com/kobayashimakoto/items/4fe942815c7fc941821f
今回は前回に引き続いて、どのような流れでアプリを作ったのかをご紹介します。
はじめに
会社員の皆さん
他部署の人の「名前」や「趣味」をいくつ言えますか?
「みんなの趣味くらい余裕で知ってるわ」と言えるように
お手伝いをするアプリを作ったのでご紹介します。
アプリ概要 〜TeaTime〜
TeaTime(茶会)とは
広く、お茶などを飲みながら話を交わすのを楽しむ集まり。
※ 精選版 日本国語大辞典「茶会」の解説
簡単な使い方説明
つまり、このアプリに登録しといたら、登録者の間でいい感じにお茶会をセッティングしてくれて
そのお茶会に参加することで、仲良くなれる機会を得るというわけです。
なんで作ったのか?
・近年、会社の成長に伴い社員の新陳代謝が激しい
・コロナ禍による社員間の交流の減少
などの原因から社内での交流が著しく低下している。
その結果、誰がどの部門に所属してどんな業務をしているか分からない状態。
そこで
「社内交流アプリをみんなに使ってもらって、お互いのことをもっと知ろう!」
という背景があって、このアプリの開発がスタートしました。
ユーザー体験シナリオの作成
アプリを作る上で最初に着手したのがユーザー体験シナリオでした。
ユーザー体験シナリオとは、ユーザーがアプリを起動して、その体験を得るまでにどのような工程を踏むかを言語化したものです。
僕はlucidを使って、作成しました。
部門長
「ユーザー体験シナリオを描き始める時、どこを起点にするかわかる?」僕
「やっぱり、一番最初のログインから順番に・・・じゃないでしょうか。。。(自信なさげ)」部門長
「答えの一つとして ユーザーが一番嬉しくなる瞬間 がいいかもね」
今回は「お茶会を通じて社員同士の仲を深める」ことが ユーザーに価値を与える瞬間 になります。
それを叶えるために
・どんな機能があれば嬉しいか
・どんなイベントがあればお茶会に出席してもらえるか
・どうすればリピートしてもらえるか
etc・・・
を考えました。
その結果、「絶対に必要な機能」「あれば嬉しい機能」などが見えてきました。
アプリに限らず、「どうすればプロダクトの価値をユーザーに届けられるのか」は超重要。
単にコーディングだけじゃなく、マーケティング的な考え方も必要なんだと考えさせられました。
TASKの優先順位つけた?
先輩
「どこから着手しますか?」僕
「とりあえず書きやすいHTML/CSSからやろうかなと・・」先輩
「優先順位はつけた?」僕
「まだっすね・・」
TASKに優先順位をつける
期間内に動くものを作るために「アプリが動く > デザイン」 を前提に置きつつ、必要な機能を
重要度順でMUST > HAVE TO > WILL にバラしました。
MUST (これがないとアプリとして成立しない)
・特定のチャンネルにメッセージ送信機能
・ユーザーのslack_id 取得機能
・お茶会リストの作成機能
HAVE TO (なくてもアプリとして成立するが、できる限り着手したい)
・スラックによる外部認証を用いたログイン/ユーザー登録機能
・過去のお茶会リスト一覧
・定期実行処理の設定
・ログイン時にslackのアイコン画像取得機能
・HTML/CSSの記述(「動くものをつくること」が重要なので優先度が下がる)
WILL (時間的に余裕があればやる)
・SP対応
まずはHTML/CSSガン無視でMUST機能から着手しました。
理由としては、「アプリとして動くもの」をいち早く作るため。
なので最初の方はアプリというよりかは、機能パーツが散在しているような感じでした。
次第に機能同士が結合して、ストーリーを帯びている感じがワクワクしました。
DB構造
DBは以下のように、「お茶会テーブル」、「スタッフテーブル」とそれらをつなぐ中間テーブル「お茶会リスト」、日付テーブルのみとかなりシンプルな内容になりました。
ここで転けると終盤、ちゃぶ台返し を喰らいかねないので、先輩方にがっつりレビューしていただきました。
(ちゃぶ台返し:必要な機能に対し、DB構造が適応できず、テーブル設計からやり直すこと)
コードの一部 ご紹介
メインギミックの一つであるslackログインについて当時実装したコードをご紹介します。
class OauthsController < ApplicationController
require "net/http" #URLメソッドを使用するために必要
require 'json' #JSON を使うために必要
def oauth
login_at(params[:provider])
end
def callback
# 「login_from」はsorceryのメソッド
# Slack-apiにより取得したユーザーの情報が@user_hashに格納されて返される。
@user = login_from(params[:provider])
id = @user_hash[:user_info]['user']['id']
# 画像取得処理(API投げる)
uri = URI.parse("https://slack.com/api/users.info?user=#{id}")
request = Net::HTTP::Get.new(uri)
#発行されたトークンをセット
request["Authorization"] = Rails.application.credentials.authorization
request_options = {
use_ssl: uri.scheme == "https"
}
response = Net::HTTP.start(uri.hostname, uri.port, request_options) do |http|
http.request(request)
end
#取得したJSONデータをハッシュに変換
result = JSON.parse(response.body)
#画像取得完了
avatar = result['user']['profile']['image_1024']
name = @user_hash[:user_info]['user']['name']
email = @user_hash[:user_info]['user']['email']
# DBの文字が20文字以内の制限になっているため
if name.size > 20
name = name.slice(0, 20)
end
# スラックIDでMstUser内検索し、見つかればsessionにデータを格納するのみ。
# 見つからなければ新しくユーザーを作成した上で、sessionにデータを格納する。
if existing_user = User.find_by(slack_id: id)
existing_user.update!(name: name, image_url: avatar, recess_flag: '0')
session[:user_id] = id
redirect_to root_path
else
User.create!(name: name, slack_id: id, email: email, image_url: avatar)
reset_session
session[:user_id] = id
redirect_to root_path
end
end
def logout
current_user.update!(recess_flag: '1')
reset_session
end
end
改めて見るとツッコミどころ満載な内容になっています(⌒-⌒; )。
・クラス名分かりにくい!(何やねんOauthsって)
・require
はクラスの外に置こうよ・・・
・どっからどこまでどんな処理してるか分からん・・・
・名前の文字数削る処理はモデルに書けよ。ていうかDBの設定直せよ・・・
・メソッド名「callback
とかaoth
」ってよく分からん
・gemであるsorcey
を使っているけど中途半端な使い方してる・・・
・API叩く処理は外部クラスに切り分けようよ・・・
・コメントがわかりにくい・・・
etc
先輩曰く、「3ヶ月前に書いたコードは改善したくなってる」の意味がなんとなく分かりました。
ただ、上記のように、すぐに改善する方法が頭に浮かぶのは、それだけ研修や業務を経て、
プログラマーとして成長できたと前向きに考えています。
そして、「動くアプリ」を作ったことは自分にとって大きな自信にもつながりました。
最後に
ここまで見ていただきありがとうございました。
次回は、
・アプリを実際に運用してみてどうだった?
・改善するなら何を考えるか?
・アプリを作る上で「やらかしたこと」
についてご紹介します。
続きのpart.3 はこちらから!