ポモドーロテクニックを使うことができるDiscord Botを作りました

スクリーンショット 2022-03-29 0 01 23

はじめに

フィヨルドブートキャンプで学習中のかわせと申します。昨年の3月からお世話になっていて、このたび最終課題である自作サービスを作りました。

github.com

Bot招待はこちら

discord.com

本記事ではそのサービスの紹介とリリースまでの振り返りをしたいと思います。

ポモるの紹介

ポモるとは?

ポモるはDiscord上でポモドーロテクニックを使うことができるDiscord Botです。ユーザーがボイスチャンネルに参加している状態でコマンドを入力するとポモドーロタイマーをスタートさせることができ、休憩の時間になるとアラートで通知します。

解決したかった問題

ニーズとしてはDiscordで勉強する人向けに限られてしまうのですが、複数人でポモドーロテクニックをできない問題を解決するためにつくりました。

あとはフィヨルドブートキャンプのDiscordサーバーでPomomoというポモドーロテクニックを使えるDiscord Botが使われているのですが、このBotがたまに使えなかったりするときがあるみたいで自分がそれを作ることでその問題も一緒に解決したかったんです。

ポモるでできること

ポモドーロテクニックの他に以下の機能を使うことができます。
詳細についてはREADMEでもまとめたのでぜひご参照ください。

  • ポモドーロタイマーの編集

gyazo.com

  • 一時停止

gyazo.com

  • スキップ

gyazo.com

  • リスタート

gyazo.com

  • リマインド機能

gyazo.com

  • カウントダウン機能

gyazo.com

開発期間

約3ヶ月です。時間単位だと合計500時間ほどかけていたみたいでこの期間内はその他のプラクティスと被ることはなかったと思います。

開発期間に完了したプラクティス

  • どんなサービスを作るかを考える
  • ペーパープロトタイプを作る
  • カンバンを作る
  • 技術検証をする
  • Web サービスを作る
  • CI(Continuous Integration)
  • デプロイ
  • 自分で作った Web サービスのコードレビューを受ける
  • Web サービスをリリースする

使用技術

Ruby on Dockerで開発環境を構築して、メインとなるDiscord APIのラッパーライブラリはdiscordrbを使って実装することにしました。

  • Ruby 3.1.0
  • discordrb 3.4.1
  • Docker

f:id:kawase-k:20220408114101p:plain

楽しかったこと

新しい技術のキャッチアップ

今回Dockerを使用して環境を構築したのですがこれをキャッチアップしているときが1番楽しかったかもしれません。元々Dockerを使うつもりはなかったのですがBotに音声を扱わせる必要があったのでそのパッケージをコンテナ上でインストールしておくことでどの環境でも簡単に音声を扱うことができるようにしました。こうしておくと他の人が自分のリポジトリを手元で立ち上げたいときにわざわざローカル環境でパッケージをインストールする必要がなくなりますし下手な話ローカル環境を汚さずに済みます。

同じ環境を手軽に用意できるのがとても便利だなと改めて実感しました。

並行処理について学べたこと

これは終盤になって気づいたことなんですがコマンドBotって並行処理で作られていて、コマンドを入力するたびにスレッドが作成されプログラムが実行されます。

ポモドーロタイマーをスタートさせたあとにThread.listを確認すると配列の最後にコマンドBotによるスレッド(#<Thread:0x000000010d011568)が作成されているのが分かります。

irb(Bot::Commands::Control):001:0> Thread.list
=> 
[#<Thread:0x000000010e0c8d20 sleep_forever>,                              
 #<Thread:0x0000000112758c18 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/gateway.rb:163 sleep>,
 #<Thread:0x0000000112886518 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/gateway.rb:445 sleep>,
 #<Thread:0x000000010d011568 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/commands/command_bot.rb:486 run>]

もちろんこの間に他のコマンドが実行されるとそれを処理するためのスレッドが作成されてプログラムが実行されます。ですがポモドーロタイマーをスタートさせたスレッドが終了されることはありません。

例)ポモドーロタイマーを一時停止して再開させたあとに確認する。

irb(Bot::Commands::Control):001:0> Thread.list
=> 
[#<Thread:0x000000010cc20d28 sleep_forever>,                       
 #<Thread:0x00000001112b8ad8 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/gateway.rb:163 sleep>,
 #<Thread:0x00000001113e6248 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/gateway.rb:445 sleep>,
 #<Thread:0x000000010d011568 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/commands/command_bot.rb:486 sleep>,
 #<Thread:0x000000011139e8a8 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/commands/command_bot.rb:486 run>,
 #<Thread:0x00000001119458b0 /Users/kota/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/discordrb-3.4.0/lib/discordrb/commands/command_bot.rb:486 sleep>]
  • #<Thread:0x000000011139e8a8:一時停止スレッド
  • #<Thread:0x00000001119458b0:再開スレッド

このように複数のスレッドを持つマルチスレッドを利用して並行処理を可能にしているみたいです。最初は違和感しかありませんでしたが実装したときはとても楽しかったです。

ちなみにコマンドBotの並行処理を利用してスレッドの中にスレッドを作成することで新たに並行処理を実現することもできます。

def alert(session, value = nil)
  # 省略
  init_alert_thread(session, path)
end

private

def init_alert_thread(session, path)
  Thread.new { session.event.voice.play_file(path) }
end

文章にしてしまうと、このinit_alert_threadメソッドが呼ばれると5〜6秒ほどアラートを再生するのですがこの秒間の処理は待機せずに次の処理が実行されるようになっています。こうしておくことでアラートが再生されている間に万が一他のコマンドを実行されることがあっても予期せぬバグを防ぐことができました。

苦労したこと

どんなサービスを作るか考えること

リリースまでを振り返るとこのプラクティスが1番苦労しました。一応作りたいサービスはいくつかあったのですが実際に考えてみると本当に作る必要があるのかだったり、技術的に可能なのか否かで悩んでしまうんですよね。

最終的にフィヨルドブートキャンプで用意されているサービスを作ることにしたのですがメンターの方のアドバイスを頂いたこともあり、世の中にどういった困りごとがあるのかなどを考える力は少し身についた気がしています。

「自作サービス」の課題だから、「どんなサービス」を作るか(解決策)を考えることになるのですが、実はそれは罠で「ユーザーのどんな困りごと(大きな課題でも、ちょっとした問題でも)を解決したいか」(問題設定)のほうが大事だったりします。 「解こうとする問題」の軸を決められると、解決策は最初の案から変わっても構わないので、いい感じの問題(大きすぎると解決が大変。世界平和とか)を設定できるといいですね。問題設定じたいが難題なので、まずは解決策を考えてみてから「それでどんな問題を解消できるのか? それは解決するに足る問題なのか?」を考えてもいいかもしれません(たいへんだけど)。

顧客とのヒヤリングから仕様決め

フィヨルドブートキャンプで用意されているサービスを作ることにしたので以下のようにヒヤリングしてサービスの仕様を決める必要があります。

  • お客さんが解決したい問題は何かをヒヤリングする。
  • お客さんが欲しいものを機能に落とし込む。
  • お客さんが欲しいとは言ってるが必要ではない機能を削り、お客さんを納得させる。
  • お客さんが欲しいとは言ってないが、問題解決のために必要な機能を提案する。
  • 予算、工数を踏まえて現実的にリリースできる形に落とし込む。

これが結構難しくて、お客さんの考えを聞き出してその要望だったりを決められた期間内にサービスへ反映することができるのかをお互いが納得した上で仕様を決めなければいけません。自分で考えたサービスとの違いはまさにこの通りでターゲットの抱えている問題を解決するものを考えるのが自分ではなくお客さんになります。

もちろん開発するのは自分なのでちゃんとお客さんの要望を汲み取らないことには思っていたのとは違う結末を迎えることになります。

また、日報でこういったヒヤリング難しいですと書いてみたところメンターの方に以下の記事を共有していただき助けていただいたことを覚えています。
(当時貼っていただいたリンク先にアクセスできなかったので類似資料へ差し替えています)

www.casleyconsulting.co.jp

この記事を見ると1つのサービスを作り上げるために関係する人たちがいかに異なる考えを持っているかが分かると同時に、顧客自身も欲しいと思っている機能が曖昧でフワフワしている状態になっているとき、そういった要望を鵜呑みにしてはいけないというシステム開発の難しさを理解することができます。

今回こういった内容を上手く実践することができずに苦労してしまいましたが、受託開発が仕事を請け負う時と同じような経験ができたと感じています。

公式ドキュメントを読み解く難しさ

どの公式ドキュメントにも共通して言えることだと思いますが一次情報が英語だったりすると英語が苦手な自分の場合、読み解くのに時間がかかってしまいます。そしてドキュメントに載っている簡単なサンプルコードは理解できたと思いきやそれを応用して使おうとすると一次情報だけではどうも分かりませんとなりがちです。

実際にdiscordrbでも用意されているDocsを最初に見たときはライブラリ側で用意されているメソッドを検索してもヒットせずに変な勘違いをしてしまっていたり、メソッドの説明文を単に翻訳しただけで分かった気になってしまい本来推奨されていない使い方でコードを書いてしまっていたり色々苦戦を強いられてきた気がします。

Docs drb.shardlab.dev

それに加え二次情報もあまり参考にできる記事がなかったこともあり、苦労はしましたが結果的に公式ドキュメントを読む力が身についたと感じています。

やってよかったこと

Web画面をあえて作らないことにしたこと

これだけ聞くとWebエンジニアを目指しているのに何を言っているんだ…。と思うかもしれませんが、現時点でこのサービスにはWeb画面は不要なんです。

もちろん仕様決めの際にポモドーロタイマーをWebからも設定できるような画面を作ろうなどと話もでましたが、

  • 既に解決したい問題をクリアできていたこと
  • ペーパープロトタイプにしたときにデザインが寂しくなってしまっていたこと
  • Discord上でコマンド入力できるので設定画面は使われないかもしれないこと

などという理由からファーストリリースではWeb画面を作らずに進めることにしました。

これからやりたいこと

  • Bot紹介ページと専用サーバーを作る
  • スラッシュコマンドに対応する

あとはDiscord APIを使って機能を実装するのが楽しかったので、Ruby以外の言語でBotを作ってみたりもっとDiscord APIについて知見を広げていきたいなと思っています。

余談

フィヨルドブートキャンプで用意されたサービスを作る人の特権かもしれないのですが、自分以外に欲しいと言っている人がいる前提でサービスを作ることになるのでリリースすると使ってくれる人が必ずいます。これが開発途中の心持ちになっていたときもありますし、既にサービスとして存在するPomomoを使っている人をDiscord上で見かけると早くポモるも使って欲しい〜なんて浮かれていたこともありました。

何が言いたいかというと、誰かが欲しいといっているサービスを作るというとても素晴らしい体験ができたと感じていて、この気持ちはプロのエンジニアになってもずっと忘れずに心に留めておきたいと思います。

おわりに

リリースまでを振り返るとサービスの案出しや仕様決めで紆余曲折してはメンターの方々に助けられ、機能の実装からデプロイまでは着々と進めることができたのではないかなと思っています。やっぱり実装で詰まるとつらいですし分からないことばかりでしたが、最終的に完成させることができて本当によかったです。

ぜひDiscordで勉強をしている方、ポモドーロテクニックに興味がある方、一度サーバーへ招待してみてポモるを使ってもらえると嬉しいです!