はじめに
現在情報系の大学院1年生のつむぎといいます。web業界に行きたいと思い、フロントエンジニアのポートフォリオとしてタスク管理サービスFroteを独学で開発しました。まだ完成とは程遠いですが、今回はとりあえずサービスが公開出来るまでの過程を書いていきたいと思います。作成したものはこちらです[Frote] [github]
開発しようと思った背景
予算的、技術的に一般ユーザーが満足するクオリティのものは作れないと思ったので、自分が欲しいものを作ろうと決めました。毎日のタスクをvscodeのテキストファイルで管理していたのですが、問題点が大きくわけて2つありました。1つは依存関係のあるタスク同士が分かりにくいという問題です。Aが終わらないとBが出来ない状態を「BはAに依存している」と定義するとAとBは並列の関係にあるべきではありません。つまり、AのほうがBより優先度は高いですが、あたかも同じ程度の優先度に見えてしまっていました。2つ目は優先度の決定に時間がかかるという問題です。依存関係も気にしつつ、こちらのほうが優先度が高いななどと判断する必要がありました。後からタスクを追加する場合もどこに入れようかなどで悩み、結果として時間がかかっていました。
この2つの問題点を解決できるようなtodoアプリは僕が探した感じは見つからなかったので、僕が作ろうと考えた次第です。Frote(フローテ)はFree priorityからフランス語のprioriteを混ぜて命名しました。
開始時のスキル
大学でCとDBをがっつりとJavaを少し、あとはatcoderでC++を趣味程度で触っているくらいしか知識がありませんでした。html,css,javascriptはhello worldが出来るレベル。
要件定義
・自分の技術力をアピール出来るようなもの
・タスクの依存関係の可視化、優先度の自動決定が出来るタスク管理サービス
・お金は極力かけない
・時間の関係上学習コストは出来る限り少なくしたい
・レスポンシブ対応
技術選定
React
今の流行り的にSPAはやりたいと思い、採用しました。
TypeScript
C言語をやっていたせいか静的型付言語っぽい方が好きなので採用しました。
styled-components
コンポーネント志向と相性の良いCSS in JSの中で有名なのを採用しました。emotionやtailwindcssなども考えましたが、最初は生のcssを触りたかったこととstyled-componentsの方が採用例が多かったことからこちらにしました。
material-ui
reactのUIコンポーネントライブラリとして定番なものを選びました。
recoil
状態管理はrecoilでやっています。最初はuseContextでやっていたのですが、大変だったので移行しました。reduxによるチャットアプリケーションなども作ってみましたが、reduxは必要以上に複雑であまり好きではありませんでした。
Laravel(php)
バックエンド言語は悩みましたがphpにしました。nodejsとGOは最初に触るのには不安がありましたし、railsはSPAが得意そうな印象があまり無かったです。スクレイピングなどもする予定が無かったので、phpと一番人気のフレームワークlaravelを採用しました。
heroku
本当はAWSにしたかったのですが、費用と学習コストを考えてherokuにデプロイすることにしました。
mySQL
スタンダードなものを採用しました。
その他使用技術
react-roter,react-hook-form,styled-media-query,vscode,prettier,npm,webpack, Babel,Composer,Git,GitHub
DockerやCircle CI、Github Actions,jest,storybook,nextjsなども使いたかったのですが、一度に手を出しすぎると大変そうだったので今回は断念しました。
基本設計
優先度の決定
パラメータなしはきついので、緊急度と重要度というパラメータをタスク追加時に決めてもらう。
依存関係の可視化
依存関係のあるタスクはリスト構造で保存することにし、依存関係のあるタスクの集まりを「リスト」と呼ぶ。
タスクのグループ化
タスクがグループ化出来るようにグループも作る。
タスクの挿入と追加
リストへの挿入、追加機能を作成する。また、入力フォームも動的フォームである必要がある。
認証機能
laravelの機能を使ったクッキーベースの認証を行う。認証情報自体はAPIで取得する。
データベース設計
tasksテーブル
id(primary) task_list_id(foreign) task order timestamps
task_listsテーブル
id(primary) group_id(foreign) user_id(foreign) importance urgency timestamps
groupsテーブル
id(primary) user_id(foreign) group
usersテーブル
id(primary) name email email_verified_at password remember_token created_at update_at
usersテーブルはlaravelのテンプレートで生成されるものを使用しています。このサービスの基本単位はリストであり、リストに1つ以上のタスクが存在します。挿入などのためにtasksテーブルはorderカラムを持っています。
工夫した点
・Container層の導入によるロジックの分離
・promiseを用いた非同期処理の制御をすることで、値を更新してから表示するようにタイミングを調整した
・TypeSctiptの恩恵を受けるためanyはほとんど使用しなかった
・コンポーネント志向を意識し、切り出せる部分は切り出して使いまわした
・styled-media-queryで作成した2つのブレイクポイントを使用しレスポンシブ対応にした
・ローディング時用のUIを用意
・入力フォームにて簡単なバリデーションを実施
・atomicデザインを使用した分かりやすいディレクトリ構造
・動的フォームの実装
改善が必要な点
・再レンダリングへの最適化がいまいち
・recoilに依存しすぎているので、その部分を抽象化したい
・SPAなのにMPAのような表示になっており、あまりSPAの良さを出せていない
おわりに
想像していた倍時間がかかりましたが、自分が思っている機能の半分くらいは実現できました。タスクの停止機能や、別の表示方法などやりたかったことはいっぱいあったのですが、期限内に終わらせることも大切だなと感じました。まだサービスとしてはバグが多すぎるので、これからどんどん改善していきたいと思います。