はじめに
C# / .NET Core で Web アプリケーション開発をしています。
Web アプリ開発に初めて取り組むメンバからは、
「何が分からないのかが分からない」
「用語が多くて全体像がつかめない」
という声をよく聞きます。
この記事では、そういったメンバに実際に伝えている
Web アプリ開発の考え方や全体像をまとめました。
概念的な話が中心なので、他言語・他フレームワークで Web 開発を行う方にも参考になる部分があると思います![]()
概念的な話
※1 ざっくり解説です、正しい知識は徐々に学んでください
※2(プロになるためのWeb技術入門を読んでくれていれば十分と思います)
前提
- デスクトップアプリ開発と、まるっきり違うと構える必要はないです
- DBへの接続や更新などは同一で、異なるのはクライアント側の開発ぐらいです
- Webサーバへのルーティングなど細かいことはフレームワークがしてくれます
- 技術用語も多いですが、徐々に覚えていけば問題なしです
クライアント(=ブラウザ)とWebサーバ
- クライアント役はブラウザで、画面はhtmlで構成されています
- ブラウザはurlを通してWebサーバの関数を呼び出してファイルを受けてます
- 受けるファイルがhtmlであれば表示して、csvなどであればダウンロードしてます
- ブラウザからサーバへをリクエスト、逆をレスポンスと表現することが多いです
HTTP
- クライアントとWebサーバの送受信はhttpというプロトコルで定められてます
- ヘッダとボディに分かれていて、なんやかんや送受信しています
- ステータスコードという数値で通信自体の種別振分けをしていて、
200(ok)、302(リダイレクト)、404(not found)とかが該当します
※ひとまず上のものだけ捉えておけばOKです
GETとPOST
- クライアントからのリクエストの種別が色々あります
-
GET,POST,PUT,DELETEなどありますが、GETとPOSTだけでOKです -
GETは「参照だけを目的としたリクエスト」です -
POSTは「サーバ側の状態が変わる可能性があるリクエスト」です -
GETのリクエストでは毎回同じ結果が得られるという捉え方がGoodです - ブラウザのURLを叩いて接続するときは
GETのリクエストです
html, javascript(js), css
- htmlで画面は構成されています
- javascriptは画面の動きを出すために使用しています
サーバとの通信やhtmlの編集も出来るので、fatなjsも見かけます - cssはhtmlのお化粧をしています
設定が難しいので躓きがちなイメージです
formタグ, inputのtype='submit', name='**'
- サーバへのリクエストは、
formタグ利用 か js利用 に分かれるイメージです -
formタグで囲われている範囲が送信内容グループです - 送信ボタンは type='submit' が書かれている
inputタグを探しましょう - 送信項目は
inputタグで name がある項目をキーバリュー形式で送ります - 配列として複数項目送るときは、name='xxx[]' とすればOKです
- 送信先は
formタグのmethod='**'やaction='**'を探しましょう
ない場合は type='submit' があるinputタグ内を見てみましょう
それでも見つからない場合は同一URLにアクセスしています
Ajax
- formタグを利用してサーバと通信すると画面遷移が発生します
- 発生させないためにはAjaxという非同期通信を実装する必要があります
- ユーザにも優しく、サーバ設計も美しくなりますがコードが増します
※formタグを利用した実装の方が易しいため初めはオススメします
CSS
- htmlのデザインをリッチにするためには
style='**'をhtmlに設定します
が再利用性がないのと、htmlの可読性が一気に下がります
そのため、.cssファイルにしてインポートする形式を取ります
※jsも同様でscriptタグで書けますが、.jsファイルにしてインポートします - どのタグに対してデザインを適用するかの指定方法がいくつかあります
id,class, タグ自体, 他…、自力で作ると大抵は破綻します - 任意の
classを付与してデザインを適用させる仕組みを用いるのが簡単で
多くのフレームワークがあります(asp.net core の規定は Bootstrapです) - CSSフレームワークもデザインの設計思想を学ぶと使い勝手が増します
(BEM、OOCSS、SMACSS、FLOCSS、…)
テンプレートエンジン
- Webサーバからhtmlを返すときにDBから取得した値を入れ込むことが多いです
htmlの構造は変わらず中身だけ変えたいときに使う仕組みです - .net core では razorという仕組みでhtml内にC#のコードを書きます
- 拡張子が
htmlではなくcshtmlとなり、他言語でもhtmlを文字っているはずです
MVC
- サーバ側の設計としてMVCという
Model,View,Controllerで責務を分けます -
Controllerはクライアントからリクエストの受信とレスポンスの送信をします
Controller内のpublicメソッドをアクションと表現して数だけURLの入り口です -
Viewは画面表示を担当してhtml部分が該当します -
ModelはWebアプリケーション上に表現する概念をDTOとして表現します
デバッグの仕方
- リクエストがサーバに届いてからは普段の開発環境でデバッグできます
- クライアント側はブラウザの開発モードでデバッグします
※F12キーで表示されるブラウザが大半です - ブラウザがキャッシュしていて最新コードでないことも多々あります
そんなときはブラウザキャッシュなしで更新する手順を調べましょう
cookie、セッション
- httpはステートレス、状態を持たないプロトコルです
そのため連続性のある通信、ログインなどの実装のために工夫が必要です - 例えば
cookieという仕組みでは、ブラウザがキーバリュー形式で値を保持して
ログイン時にサーバが発行した値をブラウザが毎回送信することで自己を証明します
作るときの注意点
クライアントの都合をサーバに持ち込まない
クライアント、サーバも独立して存在できます。
(フレームワークを使用して開発すると意識しづらいかもしれませんが)
Webサーバへのリクエストをhtmlで作成してアプリケーションではなく、
デスクトップアプリで開発することも可能であるため、依存させたくないです。
そのためアクションの引数にはhtmlなどを意識した作りにするのは避けましょう。
層を意識する
Webアプリケーション開発するときの登場人物をイメージすると、
Webクライアント(ブラウザ) → Webサーバ → データベース
の流れでデータにアクセスする場面が大半と思います。
このとき変数名や関数名が外向きに意識したものとしないようにしましょう。
特にControllerは画面がどうだとかは知らない前提です
検証の層を意識する
検証するタイミングがいくつかあります、html、Controller、Model、データベース。
必ず避けたいのはhtmlの検証しかしない場面、html内のinputタグにminやmaxを記載してもF12キーでhtmlを変更したり自前でhttpリクエストを送付できるので検証としては働きません。html内の検証はユーザインターフェースを向上させる飾りとして捉えましょう。
Controllerで検証したいのはログイン状況やユーザ権限です、Web特有の検証をここでは実装しましょう。DBのエンティティとは別でModelを作成している場合に検証すべきはWebアプリケーション特有の確認です。例えばユーザ作成の時に確認用パスワードで、データベースが気にすることではなくアプリケーション特有の検証項目はModelの層で実装しましょう。Controllerとの切り分けが難しいですが、クライアントとの通信における検証はController、入力項目自体の検証はModelと捉えるのが1つの基準です。
データベース登録の前後で検証すべきはテーブルの定義やエンティティとしての在り方です、Webアプリケーションの都合を含めないように気を配りましょう。
例えば、ユーザ登録を考えた場合、
-
html
→ 入力必須・文字数制限など(UX向上のため) -
Controller
→ ログイン済みか、権限があるか -
Model
→ パスワードと確認用パスワードが一致しているか -
データベース
→ NOT NULL 制約や一意制約
といったように、同じ「検証」でも役割が異なります。
Controller
Controllerはリクエストの入口が表現されて、出口の分岐と何がいくつあるのかを示すことが責務です。ここにデータベースから取得した値をフォーマットして、詰め替えてなど書かれていると、あっという間に処理が膨らみ見通しの悪いControllerが完成します。またURLをまとめていくと、初めに分岐をして別々の処理が書かれている場面も多いです。例えば、新規登録、更新、削除が1つのPOSTアクションとしてまとまっているRegisterアクション。Webアプリケーションで実装すべきユースケースを考えて、URLを別々にすることで分岐は不正なリクエストを弾くほどでシンプルなControllerのアクションが完成します。
具体例
例えば、1つのアクションで「登録・更新・削除」を分岐させるのではなく、
- POST /users/create
- POST /users/update
- POST /users/delete
のように、URL自体を分けることでControllerの責務はシンプルになります。
最後に
Web アプリケーションは、クライアント・サーバ・データベースと複数の要素が関わるため、最初は難しく感じやすい分野です。
ですが、
「どこまでが誰の責務なのか」
「どの層で何を考えるべきか」
を意識するだけで、設計や実装の見通しは大きく良くなります。
この記事が、Web アプリ開発に取り組む際の全体像を掴む手助けになれば幸いです。