はじめに

Webアプリ『ララ屋の質問箱』を作ろう! 設計編 

前回は実際の現場で使われるチーム開発環境をDockerを利用して構築しました。
今回はこれをベースにアプリの開発過程を講義していきます。

チーム開発用でも個人開発は当然できますので利用していきましょう。
設計といっても特別難しく考える必要はありません。

要は自身がユーザー(利用者)になったつもりで発想していくのが肝心です。
たくさんの要望が出てくるでしょう。
考えられる限りの発想が出たら、あとは削ぎ落としです。

必要の無い部分や重複する部分を削除して、大雑把でよいので機能要件を煮詰めていきます。
企業でのチーム開発する上で最も重視されるのはクライアント(依頼者)の要望です。
また不特定のユーザー(来訪者)をターゲットにするのであれば、ユーザーの利便性も無視できません。

設計段階では様々な要件と言う名の”縛り”が出てきますのでエンジニアにはそれに応えるコーディングが求められます。
読者の皆さんにはクライアントになったつもり、ユーザーになったつもりで講座を進めていって下さい。

エンジニアは当然あなたです。

開発手法の選択

QiitaやStackOverflowを模倣するつもりは無いですが、今回の”お題”はララ屋ですからlaravelに特化した質問アプリです。
ザックリと最低機能を考えると”質問できる”・”回答できる”になるでしょう。
ここからスタートして順に肉付けしていきましょう。

アジャイル開発とウォーターフォール開発

開発手法の選択肢としてアジャイルとウォーターフォールの2種類が主に挙げられます。

昨今ではアジャイル開発が主流を占めていますが、どちらの手法もクライアントの要望が選択肢となる可能性が高いので制作側で勝手にこの手法で製作しますとは言えないのが現状です。

ウォーターフォール開発

ウォーターフォール開発ではクライアントからソフトウエア(アプリ等)の作成を受注する段階でその機能を全て決めてしまいます。
設計(ワイヤー等)、実装(コーディング)、テストという工程でそれぞれ担当するエンジニアがドキュメントを作成して次の工程を担当するエンジニアにバトンタッチします。

初心者に解りづらい解説になってはいけませんので少し噛み砕いて解説します。
まずは設計(ワイヤー等)と言いました。
この時点はクライアントからの要望がとても多く入ってきます。
この工程を担当する方には設計以上に営業能力が問われます。

アプリの見栄えやユーザーが疑問に思う点が無いか? クライアントに納得してもらえるか? を加味しながら画面の配置や機能欄を細かく決めていきます。

ワイヤーは画面の区画のことです。
blogサイトなどWordPressを使ったものを例にすると解りやすいですが、headerやfooterなどの区画に分けて共通する部分やそうでない部分に分けることです。
いずれ解説することになりますが、laravelにはbladeという秘密兵器がありますからお楽しみに。

コーディングの説明は必要ないかと思いますが、機能を実現する段階になります。
初めてアプリを利用する方がログインが必要であればその前にユーザー登録機能が必要になるでしょう。
そのような流れを実現するのが実装段階です。

テストは読んで字の如くです。
設計→実装と進んで完成間近のソフトウエアにバグがないか? おかしな挙動をしないか? 設計通りに動くか?を実際に動かしてテストします。
テストに合格できなければイテレーション(反復)しますので、開発期間が延長してしまいます。

重要な相違点はクライアントの要求の変更・仕様の追加は開発前に行う必要があるところです。
以上がウォーターフォール開発の簡単な説明になります。

アジャイル開発

アジャイルという言葉の意味は”機敏”・”素早い”ということですが、この命名は開発期間の短縮から付けられました。
イテレーション(反復)を繰り返すことによって機能の追加実装とテストを繰り返し、完成へと成長させていくのが特徴です。

移り気なクライアントの要望に応えるにはうってつけの開発手法かもしれません。
開発途中で機能の追加などの要望には柔軟に対応できそうです。

しかしここには難点があります。
それは開発メンバーの技量とチームワーク及びコミュニケーション能力が必要になります。
イテレーションの周期は企業によって違いがありますが、1週間から1ヶ月程度で繰り返していき、プロデュースサー(管理者)またはチームリーダーが開発終了を見極めた時点で完了します。

余談ですが例え話をお聞きください。
webサーバーで有名なApacheの語源ですが、アメリカ先住民族で部族の名称であるアパッチ族から取った名前ではありません。

最初は機能が限定された小さなサーバープログラムだったのですが、マークアップ言語(HTML)などやTCP/IP機能が発達していった事に追従するように機能は追加されていきました。

結果a Pache 追加機能をまるで衣服に継ぎ接ぎのパッチを当てるように成長した様をそのままサーバーアプリケーションに命名したのです。

言ってしまえばアジャイル開発の元祖と呼べるかもしれません。

アジャイル開発の中にも細分化すればFDDやXPに分けられますが、この章では割愛します。

開発手法の説明はこれぐらいにして今回はアジャイル開発の方法で設計していきます。
とは言っても基本的に個人開発ですし、クライアント兼ユーザーですから特にこだわる必要もないので、必要な場面で振り返りながら進めていこうと思います。


基本的なQ&A機能と最低限の要件を設定して初期アプリを作り、後に必要と思う機能を追加発展させていく事にします。
このプロジェクトのクライアントは筆者とこの講義に関心を寄せてくださり、コメントしてくださる読者です。
そしてユーザーもデプロイするまでは同じです。
デプロイ先はレンタルサーバーに取得しているドメイン名で現実に使えるようにするつもりです。
無料会員登録をしていただければこのサイトでコメントは自由にできますので気が向いたらしてみて下さい。

要件の抽出

大雑把に基本的に必要と思われる機能を羅列してみます。

・ ユーザー登録機能
・ ログイン機能
・ ユーザーが任意で決めたIDとパスワードでログインできる機能
・ 質問機能(画像投稿機能もプラス)
・ 回答機能
・ 質問及び回答の閲覧機能(全てのユーザー)
・ 質問と回答は同じ画面で紐付け表示する機能
・ 質問と回答の削除機能(投稿ユーザーのみに限定)
・ ログアウト機能
・ パスワード再発行機能
・ 退会機能

大まかではありますが、初期はこの程度の要件で完了しておきます。
機能の追加は1次完成後のイテレーションで行います。

画面のプロトタイプ

 

ログインと新規登録のための一つ目のプロトタイプ画面を作ってみました。
デザイン性はまだ考慮しておりませんので、実に殺風景ですが、ひとまずこれを利用しようと思います。

他にも要件抽出のところで出てきました内容によって必要な画面の設計をしていきますが、表示が冗長的になってしまいますので、実装時に一つ一つ画面の紹介やコードなどを示しながら解説していきます。

 

 

 

プロトタイプ画面ですが実際に画面設計するにあたってはbladeの使い方なども含めて解説していきますので、ここでは簡単な紹介のみに留めておきます。

データベース設計

前回にlaravelのデフォルトで作成されているmigrationファイルを用いてユーザーテーブル、パスワードリセット、失敗ジョブ、とアクセストークンの各テーブルを作成していますので、質問箱のテーブルは質問テーブル・回答テーブルと画像を扱うので画像テーブルが必要です。

他にも必要になるテーブルがあるかもしれませんが、ひとまずこの3つのテーブルを作成していきます。
laravelなどのフレームワークの多くは”設定より規約”を重視しています。
特にファイル名など命名規則を守ることは重要です。
命名規則にはアッパーキャメルケース、ロワーキャメルケースやスネークケースなどがあり、また単数形か複数形かにも指定がある場合があります。

この規約を守る事によって様々な恩恵に預かることができます。
フレームワークを使わずにスクラッチで同じような機能を持たせようとするとある実行ファイルがあるとしてそれに必要な別のファイルの情報を紐付けしないといけない場合があります。
laravelでは規約を守る事によってそのようなことを自動的におこなってくれます。

ここでは逐次規約を守らなければいけない部分は説明を入れるようにしますので、安心して進めて下さい。

今回はテーブルを作るのでテーブル名の命名規則です。
* スネークケースと複数形及び小文字

failed_jobs
users

このような感じです。
これから作るテーブル名はquestions(質問)、answers(回答)とpictures(画像投稿)にします。

では以下のコマンドを実行して下さい。
まずはlaravel-de-webコンテナに入ります。

docker container exec -it laravel-de-web bash

次はstudyフォルダにカレントディレクトリを変更します。

cd study

artisanコマンドでmigrationファイルを生成します。

php artisan make:migration create_questions_table 


これで/database/migratiosフォルダに以下のようなテーブルを作るためのファイルが生成されているのが確認できます。

続けてanswersも作ってしまいましょう。

php artisan make:migration create_answers_table 

次に続けてpicturesも作ります。

php artisan make:migration create_pictures_table 

これで3つのmigrationファイルが作成できましたので、中身を記述していきましょう。

questions_table.phpファイルの記述

 

変更箇所のみを表示しておきます。

 

 public function up()
    {
        Schema::create('questions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->string('title', 100)->nullable(false);
            $table->string('body', 255)->nullable(false);
            $table->datetime('created')->nullable(false);
            $table->timestamps();
        });
    }

それでは説明に入ります。
Schema::create(‘questions’, function (Blueprint $table)はスキーマファサードでクリエイトメソッドを実行するように自動生成されています。
ファサード(Facade)とはクラス(class)をインスタンス化しなくてもメソッドを実行できる機能を言います。
Schema::createの部分が該当します。
このような記述方法ができるためコードを書く手間が大幅に軽減されます。

5行目にuse Illuminate\Support\Facades\Schema;の記述がScheme(スキーマ)クラスを使う宣言をしています。
この中でトップディレクトリにIlluminateとありますが、このディレクトリのある場所は
vender > laravel > framework > src > Illuminate
にあります。
laravelに内蔵される多くの機能が記述されていますので、暇な時に眺めてみて下さい。

create( )メソッドの第1引数にはテーブル名になっており、入れ子で関数の宣言とBlueprintのインスタンスである$tableを元にテーブル内に作成するカラム名やその属性を記述しています。

id( )とtimestamps( )は自動生成されていますのでこのまま使っています。
このように自動生成部分があると記述方法のヒントになるので助かりますね。

記述形式は 型の指定(’カラム名’)->制約 です。

integer(‘question_id’)->unsigned();
integer型で(’カラム名’)->整数に符号をつけない( );というようになってます。

foreignId(‘user_id’)->references(‘id’)->on(‘users’)->onDelete(‘cascade’);
外部キー型(’カラム名’)->参考にするのは(’id’)->それはユーザーテーブルのid ->ユーザーテーブルからidが削除されたら同時に削除する。
この部分は外部キー制約といって入れるキーの値に制限をかけるものでユーザー固有のIDはユーザーテーブルで作られたIDに統一して識別するのに有効です。

$table->foreignId(‘user_id’)->constrained(); でも良いと思います。
laravel7以降はこのエイリアスが使えるそうです。

$table->string(‘title’, 100)->nullable(false);
文字列型(’テーブル名はtitle’, 文字数の指定は100まで)->nullable(偽);
となっています。

->nullable(偽);の部分は以前のlaravelのバージョンではNOT NULLのようにSQL文を追加していたのですが、現在では指定方法が簡単にできるようになりました。
今回は空欄を許さないという記述になっています。

nullable( )のようにすると空を許す事になります。
質問のタイトルと内容となるbodyが空では悪戯も容易ですのでこのようにしました。


* UUIDパッケージを利用している場合にはforeignId型を使うとエラーになりますので注意して下さい。

一度下記のコマンドを実行してみましょう。

php artisan migrate

実行が完了しましたらphpMyAdminで確認してみましょう。

 

クエッションズテーブルやアンサーズテーブルとピクチャーズその中にカラムが作成されています。
クエッションズテーブルには追記したカラムが作成されているのが確認できます。

answers_table.phpの記述

最初の $table->id();と最後の $table->timestamps();の間が追記部分です。

public function up()
    {
        Schema::create('answers', function (Blueprint $table) {
            $table->id();
            $table->integer('question_id')->unsigned()->nullable(false);
            $table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->string('body', 255)->nullable(false);
            $table->datetime('created')->nullable(false);
            $table->timestamps();
        });
    }

記述方法は前述の記述説明のとおりです。

またマイグレート(migrate)しますが、先ほどと同じコマンドを実行すると”Nothing to migrate.”マイグレートするものはありませんと出てしまいます。
これは前回のマイグレートをキャッシュ(記憶)しているからです。
それでは以下のコマンドを実行して下さい。

php artisan migrate:refresh

ではアンサーズテーブルのカラムをみてみましょう。

ひとまずアンサーズテーブルは完了です。

pictures_tableの記述

追記部分は

$table->foreignId(‘user_id’)->references(‘id’)->on(‘users’)->onDelete(‘cascade’);
$table->string(‘image_name’, 100)->nulable();
$table->string(‘image_title’, 100)->nulable();

になります。

 public function up()
    {
        Schema::create('pictures', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->string('image_name', 100)->nulable();
            $table->string('image_title', 100)->nulable();
            $table->timestamps();
        });
    }

再びマイグレーションを行なってデータベースを確認してみて下さい。

これで前段階の設計編を終わります。
特別作業工程でこのような順番でなければならないというものはありません。
企業やチームであれば工程に規則や担当者がありますが、ここでは基本個人開発ですからその辺りは柔軟にやっていこうと思います。

次回は画面設計を行いますのでよろしくお願いします。
お疲れ様でした。

 



ABOUT US
チョッキー
ハーレーとアウトドアが大好きで、日本の文化・伝統をこよなく愛する 男性です。サイト作成・PHP・Java・JavaScriptのプログラミングとweb ライティングを副業に、日々楽しんでいます。 1980年代にUnix.osに興味を持ち、linuxの開発にも少しばかり関わりました。 昨今のIT世界の進化を享受して頂き、少しでも誰かの役に立てればと奮闘しています。 このサイトはワードプレス を利用し、PHP言語でカスタマイズしており、私の趣味で公開しています。 閲覧には会員登録が必要ですが、全て無料ですので安心して閲覧してくください。  座右の銘は”座って半畳、寝て一畳” 所詮人間などそんなもんでしょうというところです。年齢や性別・学歴など不問。一緒に悩み・励まし・歩む、その様な仲間が増えることを願ってます。                           
%d人のブロガーが「いいね」をつけました。