とある日のちびまろ
ちびまろはWeb開発者として働いてから約5年、テストを2年、開発に関わって約3年経ちます。
経験を軽く話すと、既存システムの保守運用をメインで担当し、ごくたまに新規機能の実装を行ってきました。
ちびまろの同僚「ねぇちびまろ、君はこのままでいいと思ってるの?」
ちびまろ「思ってない!!」
ちびまろ「もっと最新技術に触れて、もっと誰かのために役に立てるもの作りたい!なによりもお金が欲しい!」
ちびまろ「フレームワーク使って開発したい!(少しは楽したい...)」
ちびまろの同僚「じゃあやるしかないな!」
ここ数ヶ月AIも出てきているのにこのままの技術力で良いのかと感じていたため、まずは比較的簡単だと言われているTodoアプリを設計から実装まで行おうと決めました。
世の中に出さない場合、大雑把にわけて3つの工程があります。
1. 設計
- 何のシステムを作るか考える
- そのシステムにはどんな機能があるのか考える
2. 実装(コーディング)
- 設計で決めた内容をコードに起こしていく
3. テスト
- 実装した機能を一つ一つちゃんと動くか確認する
ひとまずこれらの工程についてふわっとしたイメージのままで行動しようとすると何したらいいか分からないという状況に陥ってしまいます。
「読むことはできるけど、実装はできない」という状況です。(私がそうでした)
今回扱う技術は以下の通りです。
バックエンド
- PHP
- Laravel
フロントエンド
- Blade
- TailwindCSSv
今回は少しでもハードルを下げるためChatGPTにも助けてもらいながら進めました。
ちびまろ「ChatGPT最高。」
ちびまろの同僚「てかそもそも、何でTodoアプリ作るの?」
0→1初心者は「Todoアプリ」がおすすめってホント?
結論から言うと、おすすめって意味ではホントです!(異論は受け付ける😇)
Todoアプリを作成する工程で、Webアプリの基本、CRUD機能の実装を諸々行えます。
- C「作成(Create)」
- R「読み出し(Read)」
- U「更新(Update)」
- D「削除(Delete)」
もちろん天才でない限り、1回作っただけで覚えることはできませんが、「お〜だいたいこんな感じか〜」って感覚を味わうことができます。
この「お〜」という感覚は本当に大切です!
この感覚を味わうことで、自信をつけることができ、モチベーションにも繋がります。
必ずしも「Todoアプリ」を作成する必要はありませんが、世にサンプルとなるものが沢山あふれているので機能を参考にすることで、考えるべきことがかなり激減して楽になります。
つまり、ハードルを下げることができます!
そう!コーディングだけに集中ができるのです!
ちびまろ「最初からハードルをあげるとしんどいよね〜」
ちびまろ「モチベーション続かずに後々嫌にもなってくるんだよね〜」
肩の力を抜いて、焦らず1歩ずつ着実に確実に進んでいきましょう。
chatGPTを使って作るアプリの一覧を提案してもらった
最初は調子に乗って100本ノック!などと考えていましたが、ちょっと時間的にも余力的にも無理だと思ったので、その中の一部だけ抜粋して載せます。(Todoアプリ以外を作るかどうかは悩んでます)
要件定義〜実装(一部コードのみ)まで全て記録に残していこうと思います。
私も学びながら進めているため、間違いなどがあればコメントにて指摘・アドバイスなどくれると嬉しいです!
要件定義
要件定義はシステム開発の最初に行われる工程です。
設計をするためにはまずどんなものを作るのかを考える必要があります。
そのために必要なのが要件定義です。
要件定義で内容を詰めずにいると、実装の途中で大幅な修正が入ることになります。
最終的に納期に間に合わないということになりかねません。
〜とある日のちびまろ〜
ちびまろ「わぉ!この機能お客さんが求めていた機能と違うらしいよ!」
ちびまろの同僚「ほんとに?!じゃあ設計からやり直しになるよね?!」
ちびまろの同僚「やめてくれー!!( ̄^ ̄゜)グスン」
最悪の場合、システムの土台ごと設計し直すようなことになります。
要件定義の目的
クリアな目標の設定
- 何を作るのか、どのような問題を解決するのかを明確にする
ステークホルダーの期待の一致
- 開発者、ユーザー、関連部門など、関わるすべての人々の期待を一致させる
開発工程の基盤作り
- 後の設計や実装フェーズでの方針や基準を確立する
要件定義の種類
要点定義は大きく分けて2種類あります。
1.機能要件
システムが持つべき機能や振る舞いを定義します。
サービスやタスクなど、システムが「何をするか」に関する要件です。
例
- ユーザーはログインとログアウトができる
- 管理者はユーザーアカウントを作成・削除できる
- システムは商品の在庫情報を表示する
- ユーザーはカートに商品を追加・削除できる
2.非機能要件
システムがどのような品質属性を持つべきか。
つまり「どのように機能するか」に関する要件を指します。
これはシステムのパフォーマンス、信頼性、セキュリティなどの特性に関連します。
例
- システムの応答時間は2秒以内であること
- 99.9%の稼働率を確保する
- ユーザーデータは暗号化して保存する
- システムは1万人の同時アクセスに耐えられる
機能の洗い出し
早速Todoアプリを作る上で必要な機能を洗い出します。
ログイン機能
- ユーザーID、パスワードの登録を可能とする
- メールアドレスの登録は不要
- タスクを作成すると、ユーザに紐づいたデータが作成される
- パスワードの条件は以下の通り
- 8文字以上。大文字・小文字・数字それぞれ最低1文字含むこと。
タスク一覧表示機能
- ログインユーザに紐づくタスクを表示する
- ステータスが未完了かつ、登録日が古いもの順に表示させる
タスク登録機能
- 保持するデータ
- タスクのタイトル
- タスクの詳細
- タスクのステータス
- 未着手
- 着手中
- 保留
- 完了
- 期限
- 期日が1日以内の物は赤字表示もあり?
タスク詳細表示機能
- タイトルに関する詳細なタスク内容を表示する
- タイトルのリンクを押下すると詳細画面に飛ぶ
タスク編集機能
- タイトル・詳細・期日の編集を行うことができる
※ステータスは編集ボタンを押下せずとも常時編集可能とする
タスク削除機能
- 間違えて登録したタスクや、不要となったタスクを削除する
- ページネーション機能
- 10件単位とする
画面構成
機能の洗い出しをして必要な機能は以下の7つになりました。
- ユーザーログイン機能
- ユーザー登録機能
- Todo一覧表示機能
- Todo登録機能
- Todo詳細表示機能
- Todo編集機能
- Todo削除機能
DB設計
今回必要なDBは2つ
- 登録されたユーザー情報を保管するテーブル
- Usersテーブル
- ユーザーが作成したタスク情報を保管するテーブル
- Todosテーブル
必要なデータ・データ型・文字数・制約
それぞれのテーブル構成は以下のようにしました。
ユーザーに対して複数のタスクを紐付ける(一対多の関係)ため、todosテーブルに外部キーを担うuser_id
を追加しています。
usersテーブルのid
とtodosテーブルのuser_id
を紐づけることで、誰が追加したタスクかを判断するようにしています。
気になった方は「DB リレーションシップ」でググってみてください。
usersテーブル
todosテーブル
フローチャートの作成
機能別のプロセスを整理するためにフローチャートの作成はとても良い手段だと考えています。
頭の中で考えるより図解して整理することで、足りない機能があることに気付くこともあります。
簡易的ですがdraw.ioを使ってそれぞれの画面でのフローチャートを作りました。
画面設計
デザインはどうにも苦手で😅
ここはハードルを下げるために一旦諦めて潔くテンプレートサイトにお世話になりました!
実装
テンプレートを使い、自分の要望とは合致しないボタンやレイアウトは変更する形で対応しました!
フォーム系の画面
フォームが実装されている画面は全て同じこちらのテンプレートを使用しました。
ユーザー登録画面
- 「I accept the Terms and Conditions」の削除
ログイン画面
まだ実装はしきれてなく、余裕がある時に実装しようかと考えている機能が2つあります。
- Remember me
- Forgot your password?
それぞれ自動ログイン機能と、パスワードリセット機能です。
応用に近い機能だと感じたため、画面には残しましたがロジックの実装は後々という感じで考えています。
Todo登録機能
以下4つの内容を登録できるような画面を作成しました。
- タスクのタイトル
- タスクの詳細情報
- 期限日
- 状況
Todo編集機能
登録されたデータのidをリンクの/edit
前に渡すことによって、紐づくデータを取得して初期表示の際にフォームに自動的に入るようにしています。
http://127.0.0.1:8000/todos/1/edit
この編集機能を実装するときは本当に色々つまづきました。
詳細は後述します。
Todo詳細表示機能
本来であれば実装の必要はなかったのですが、どうしてもshow
メソッドを使ってみたかったので実装することにしました。
Todo一覧表示機能
こちらのテンプレートを元に一部カスタマイズしました。
カスタマイズ項目
- 検索窓の削除
- Actionsボタンの削除
- Filterの削除
ちなみに右側の「・・・」を押すと以下の画面(赤枠)が展開されます。
苦労したところ
今回Todoアプリを作る上でつまづいたところがいくつかあったので紹介します!
詳細画面でのステータス表示
登録されたステータスを取得し、デフォルトで表示されるようselected
をつける処理をどうしようかと迷いました。
何とかスマートな実装方法にしようと考えたところ以下のように落ち着きました。
「if($todos->status == '?')だったら selectedをつける」というロジックを各ステータスに書いています。
Todo編集機能
ちびまろ「だめだ〜、フォームの内容を変更して更新ボタン押しても全然反映されない...」
ちびまろ「なんでだろ〜」
〜色々試行錯誤〜
ちびまろ「見た感じルーティングの設定もあってるはず...」
ちびまろ「見た感じformのactionリンクもあってるはず...」
ちびまろ「あれ?ルーティングのRoute::??
の??
の部分を間違えてる?!」
Route::post('/todos/{id}', [TodoController::class, 'update'])->name('todos.update');
↓
Route::put('/todos/{id}', [TodoController::class, 'update'])->name('todos.update');
ちびまろ「よし!これでいけるはずだ!」
〜結果は変わらず〜
などと2時間ほど格闘した結果、ルーティングのパラメータ名が原因でした。
ルーティングのパラメータ名とupdate
メソッドの第二引数の変数名($todos)を一致させる必要があります。
今回の場合、第二引数の$todos
と合わせる必要があります。
コントローラー
public function update(Request $request, Todo $todos): RedirectResponse
ルーティング
Route::put('/todos/{id}', [TodoController::class, 'update'])->name('todos.update');
↓putメソッドの第1引数のパラメーターをtodos
に変更後↓
Route::put('/todos/{todos}', [TodoController::class, 'update'])->name('todos.update');
こうすることで、更新処理が上手く走るようになりました!
ちびまろ「きたーーーーー!!!!」
ちびまろ「この壁を突破した感覚があるからプログラミングは辞められない!」
P.S.
Xで教えていただきましたが、Route Model Bindingという機能があるそうです!
まだざっくりとしか理解できてないので割愛させていただきますが、気になった方は是非調べてみてください。
最後に
最後まで読んでいただきありがとうございました。
他のTodoアプリを参考にしたものの、0から何かを作る経験を積むことができて少し自信に繋がりました。
設計時点では色々アイデアは思いつきましたが、期日を1ヶ月と決めていたため、最低限の機能のみ実装しました。
1回作成しただけでは慣れないので、CRUD機能を用いた何かしらのシステムをまた作成しようと考えています。
ちびまろ「はてさて、次は何作ろうか?」