『プログラミングASP.NET MVC 第3版』を読んだ

プログラミングMicrosoft ASP.NET MVC 第3版ASP.NET MVC 5 対応版 (マイクロソフト公式解説書)

ASP MVC 5の解説書。初歩的な解説も載っていますが、それ以上に「ASP MVCを使って良いアプリケーションを作るにはどうすればよいか」ということを詳しく書いてあります。

以下、目次

■第1部 ASP.NET MVCの基礎
第1章 ASP.NET MVCのコントローラー
第2章 ASP.NET MVCのビュー
第3章 モデルバインディングアーキテクチャ
第4章 入力フォーム
■第2部 ASP.MVCのソフトウェアデザイン
第5章 ASP.NET MVCアプリケーションの機能
第6章 アプリケーションのセキュリティ
第7章 ASP.NET MVCコントローラーの設計上の注意点
第8章 ASP.NET MVCのコントローラーのカスタマイズ
第9章 ASP.NET MVCでのテストとテスタビリティ
第10章 ASP.NET Web APIエグゼクティブガイド
■第3部 モバイルクライアント
第11章 効果的なJavaScript
第12章 モバイル対応のWebサイトの作成
第13章 マルチデバイスサイトの構築

500ページ長と大きめの本ですが、本書の中でも力を入れて読むべきなのは、第2部「ASP.MVCのソフトウェアデザイン」です。
特に、第7章「ASP.NET MVCコントローラーの設計上の注意点」には、さまざまな設計上のヒントが散りばめられています。

たとえば、MVCのControllerは、その名の通りの「Controller(さまざまなオブジェクトを統合して管理する責務)」ではなく、「Coordinator(さまざまなワーカーサービスの調整を行う責務)」として実装したほうが、シンプルに実装できる、といった指摘です。

もう1つ、個人的に気になったテクニックが、ビューモデルです。ビューモデルの概念は、WPFなどでは当たり前に用いられているようですが、WebのMVCの世界ではそれほど一般的ではありません。しかし、ビューモデルを使うことで、DBを操作するためのモデルクラスと、ビューに表示するデータを保持するだけのビューモデルクラスを分離することができます。このような分離は、単純なアプリケーションでは手間がかかるだけでメリットは薄いでしょうが、データベースのデータを画面上に表示するための整形処理等が必要な場合には、ビューモデルを活用することで、個々のクラスの実装を簡潔に保つことができます。

ASP MVCの入門者が最初に読む本としては適していませんが、2冊めに読む本としては良いと思います。

この本の著者(Dino Esposito氏)の本は良さそうだなと思ったので、以下の書籍も購入しました(ちょうど、Kidleで50%ポイント還元やってたので)。

.NETのエンタープライズアプリケーションアーキテクチャ第2版 .NETを例にしたアプリケーション設計原則

『Web API: The Good Parts』を読んだ

Web API: The Good Parts

最近はWeb APIの開発ばかりやってますが、設計方法については『Webを支える技術』を読んだ程度でした。
Web API設計の基本はRESTなので、『Webを支える技術』はとてもためになりますが、もう少し実践よりの本も、ということで『Web API: The Good Parts』を読んでみました。

実践よりとはいっても、『Web API: The Good Parts』には具体的なWeb APIの実装は出てきません。
それよりも一段上の、「Web APIをどう設計すべきか」という点に焦点が絞られています。

また、「Good Parts」シリーズらしく、著者の独自の観点で練り上げられたベストプラクティスが網羅されています。
なお、出版は2014年ということで、gRPCのような新しめの概念には触れられていません。

Web APIチェックリスト

本書で一番良いと思ったのは、巻末の「Web APIチェックリスト」です。
ここには、本書で紹介されているベストプラクティスのうち、特に重要なものがリストアップされています。

一例を挙げると以下のような項目です。

  • URIが短く入力しやすくなっているか
  • URIが人間が読んで理解できるようになっているか

このリストをそのまま使ってもいいですし、自分たちでAPIの設計指針を定める場合にも、このリストをベースに作れば楽ができそうです。

標準を尊重する

本書の基本的な哲学は以下の二文で表されます。

  • 仕様が決まっているものに関しては仕様に従う
  • 仕様が存在していないものに関してはデファクトスタンダードに従う

「HTTPの仕様を活かしてWeb APIを作る」ということですね。
設計に迷ったときはまず仕様、仕様がないときはデファクトスタンダードを調べることが大切です。

具体例に基づいた解説

フィールド名をキャメルケースにするかスネークケースにするか、といった、標準が存在せず設計に迷う場面では、Twitter、Facebook等の大手Webサービスを調査して「デファクトスタンダード」を探っています。
この調査結果が載っているのもありがたいところ。

REST LEVELとHATEOAS

「どのくらいまでRESTに準拠しているか」を示すREST LEVELという概念があります。

  • REST LEVEL0 – HTTPを使っている
  • REST LEVEL1 – リソース概念の導入
  • REST LEVEL2 – HTTPの動詞の導入
  • REST LEVEL3 – HATEOASの概念の導入

本書は、現在多くのWeb APIで採用されている「REST LEVEL 2」に対応しており、「REST LEVEL 3」において導入されるHATEOASは導入していません。
HATEOASに関しては、本書の執筆時には「時期尚早」であったと思われますが、HALというHATEOASのための仕様と、その実装のためのライブラリも整備されてきているので、2017年現在は「採用を検討する」くらいのフェーズにはなっていると思います。

まとめ

これからREST APIを開発する人にはとても参考になる書籍だと思います。
gRPCのようにRESTの代替となる技術も出てきているので、RESTさえ知っていればOK、という状況ではなくなってきていますが、今でも主流はRESTでしょう。
ということでオススメです。

『ASP.NET MVCプログラミング入門』を読んだ

ASP.NET MVCプログラミング入門 (マイクロソフト関連書)

本書のタイトルは『ASP.NET MVCプログラミング入門』ですが、実際に扱っているフレームワークは「ASP.NET Core」です。

従来のASP.NETと、ASP.NET Coreの違いはわかりづらいですが、以下の表が参考になります。

ASP.NETとASP.NET Coreの相違点
名前 ASP.NET4.6 ASP.NET Core 1.0
正式対応OS Windowsのみ Mac/Linux/Windows
対応プラットフォーム .NET Frameworkのみ .NET Framework/.NET Core
IISへの依存
MVC/WebAPI/WebPages機能 ○(別クラス) ○(統合済み)
WebForm機能 ×
WebService機能(asmxやWCF) ×
オープンソース開発 ×

出典: ASP.NET Coreの概要を理解してセットアップしよう

ASP.NET Coreの特徴は、(1) オープンソースである (2) クロスプラットフォームで動作する の2点です。
また、ASP.NETには、いくつかのサブフレームワークがありますが、Web Formという、従来のASP.NETの中核を成していたフレームワークはASP.NET Coreには含まれません。
ASP.NET Coreの中心は、MVCという比較的新しいフレームワークです。

ASP.NET Coreが出たからといって、従来のASP.NETがすぐに廃止されるわけではなく、両者は並行して開発されていくようです。

ASP.NET Core雑感

『ASP.NET MVCプログラミング入門』を参考に、ASP.NET CoreのMVCとWeb APIを軽く触ってみました。
私が仕事で主に使っているのはPHPのWebアプリケーションフレームワーク(Symfony, Laravel, Phalcon等)で、その他にある程度時間をかけて学習したフレームワークとしてはRuby On Railsがあります。
ASP.NET CoreのMVCは、これらのフレームワークと非常によく似た作りになっています。
以下は、dotnet new -t webコマンドで作成した直後のMVCアプリケーションのディレクトリ構成です。

ルート直下にControllers, Modles, Viewsが存在するという、わかりやすいディレクトリ構造になっています。

コントローラー

コントローラーは以下のような感じです。

C#らしさを感じるのは、非同期のアクションが簡単に書ける点です。

↑で注目すべきは、メソッドのシグネチャにasyncキーワードがついている点です。
_signInManager.PasswordSignInAsync()は非同期処理なので、いつ結果が返ってくるかわかりません。
そこで、このアクション自体を非同期にして、結果が帰ってきたタイミングでレスポンスを返せるようにしています。

PHPやRailsだと同期処理が当たり前だったので、カジュアルに非同期処理が使えるのはすごいなーという感じがします。

モデル

ASP.NET MVCでは、Entity FrameworkというORマッパーを使用します。
(ASP.NET Core用のものはEntity Framework Coreという別ライブラリですが、基本的なアーキテクチャやAPIは同じはず)

Entity Frameworkは、Data Mapperパターンに基づいたORマッパーです。
特徴は、データベースのテーブルに対応するクラスを、特定のクラスを継承しないPlainなクラスとして実装する点です。

↑のようなクラスから生成されたオブジェクトに保存されたデータを、DbContextというレイヤーを介してデータベースのpersonテーブルに永続化します。

Webアプリケーションフレームワークの世界では、Active Recordパターンに基づいたORMが多いですが、Data Mapperに基づいたORMも根強い人気があります。
JavaのHibernateが代表格ですが、その他の言語でもPHPのDoctrine、PythonのSQLAlchemyといった実装があります。

個人的には、Doctrineの使用経験があったため、Entity Frameworkは馴染みやすく感じました。

ビュー

Razorテンプレートエンジンというものを使用します。コードは以下のようになります。

自動エスケープやパーシャルテンプレート等、テンプレートエンジンにほしいものは大体入っています。

ビューテンプレートの内部ではC#のコードを書けます。
変数の定義のほか、DB問い合わせやファイル読み込みが可能です。
ビューにドメインロジックが入り込まないよう注意が必要です。

ルーティング

デフォルトでは、 /コントローラー名/アクション名 というルーティングになります。
ルーティングを独自定義する方法はいくつかありますが、個人的には属性を使用する方法が気に入りました。

↑のように、コントローラーのクラスやメソッドに対して属性を設定することでルーティングを行います。
Symfonyフレームワークにアノテーションルーティングという同様の仕組みがあり、アクションとルーティングの対応関係がわかりやすくて良かったので、同様の機能が提供されているのはいいなーと思います。

雑感まとめ

Microsoftのフレームワークということで、エンタープライズ的な、機能が山盛りで複雑なフレームワークを予想していたのですが、ASP.NET Coreの基本的な作りはかなりシンプルです。
MVCアーキテクチャのフレームワークを1つでも使ったことがあれば、ASP.NET Coreはすぐに使えるようになると思います。

書籍の感想

対象読者は「ASP.NET(ないしWindowsプラットフォームの開発)経験者で、ASP.NET MVC未経験」かなと思います。
Visual Studioを使ったことがない人がいきなり読むと、少しつらそうな部分があります。
(まあ、Visual Studioを使ったことがない≒C#経験が無い なので、そういう読者は先にC#とVisual Studioを覚えたほうがいいんでしょうが)

解説はかなり丁寧なので、C#の構文がわかっている人ならそれほど苦労せず読めると思います。

一点、残念だったのは、本書のほとんどの部分で、開発環境がWindowsを前提としている点。
Visual Studio 2015 Community + SQL Server 2014という組み合わせになっています。

付録としてLinuxでの開発環境構築方法は載っていますが、全体を通してWindows/Linux/Macのいずれでも実行可能な方法を載せてほしかったですね。
Visual Studio Code + SQLite/MySQL/PostgreSQLのいずれか という組み合わせならクロスプラットフォームで動くはずなので。

余談: Visual Studio Codeについて

Visual Studio CodeのC#拡張はすごいですね。
IntelliSenseに関してはVisual Studioと同程度に動作します。つまり、強力ということです。
フロントエンド技術のサポートはVisual Studio Codeの方が優れている部分もあるので、ASP.NET Coreで開発するなら、Windows + Visual Studioという組み合わせでなくてもやっていけそうな感じがします。

『レガシーソフトウェア改善ガイド』を読んだ

レガシーソフトウェア改善ガイド

本書『レガシーソフトウェア改善ガイド』は、タイトルの通り、「レガシー」なソフトウェアをいかにして改善していくか、というテーマの本です。

「レガシー」というと、『レガシーコード改善ガイド(下記書籍)』が思い浮かぶ方もいると思いますが、本書は『レガシーコード改善ガイド』の補完的な位置づけの本であるとみることもできます。

レガシーコード改善ガイド

ちなみに、上記2冊はいずれも翔泳社から出ているので、タイトル、装丁ともにシリーズものっぽい感じですが、『レガシーコード改善ガイド』の原書はWorking Effectively With Legacy Code、『レガシーソフトウェア改善ガイド』の原書はRe-engineering Legacy Softwareであり、出版社も異なります。

レガシーなソフトウェアとは

『レガシーコード改善ガイド』では、「テストがないコードはレガシーコードだ」という明快な定義にもとづいて、テストの困難なコードをいかにしてテスト可能にしていくか、ということを、非常に詳しく説明しています。コードの改善という観点からは、『レガシーコード改善ガイド』の内容は今でも十分に通用するものといっていいでしょう。

一方で、「コードさえ良ければそれでいいの?」という問題もあります。Webアプリケーションの開発では、開発環境の構築や、運用環境のメンテナンス等、コード以外にも気にかけるべき要素が多数存在します。

『レガシーソフトウェア改善ガイド』では、コードと、それをとりまく環境も含めた全体を「ソフトウェア」と定義しています。「レガシーなソフトウェア」とは、保守しづらいソフトウェアのことです。たとえば、開発環境の構築に何日もかかったり、本番環境の設定が文書化もコード化もされていないようなWebアプリケーションは、「レガシー」であるといえます。

本書の良いところ

各章の概要については、コードがレガシーになる原因のほとんどは、人間に関係している~『レガシーソフトウェア改善ガイド』よりに載っているまとめが良くできているので、こちらの参照をおすすめします。

個人的に印象に残ったのは、レガシーなプロジェクトに携わる開発者のモチベーションマネジマントに言及している点です。はじめに、レガシーなコードベースに対峙することは気が滅入る作業だと認めた上で、その処方箋を記載しています。第一歩としては、静的解析ツールによってコードの品質を定量化し、その変化を記録する、というものがあります。改善の状況が数値として見えるので、良いアイデアだと思います(ただし、保守フェーズに入っているプロジェクトはコードの変更量自体が少ないので、かえって気が滅入る恐れもあります…)。

具体的なリファクタリングのテクニックは『レガシーコード改善ガイド』に譲りますが、本書にもいくつかの改善例が記載されています。

また、コードのリファクタリングだけでなく、コードが動作するためのインフラ構築方法の改善(Ansible等の構成管理ツールの使用)、開発環境構築方法の改善(Vagrant + Ansible)、ドキュメンテーションの改善(READMEを書こう)等も紹介されています。

さらに、技術一辺倒な視点ではなく、「リファクタリングやリライトをするには、マネジメント層(ビジネス側)と折り合いを付ける必要がある」等の、実際の業務の中で改善を進めるための知見が述べられています。

『レガシーコード改善ガイド』には載っていないけれど、重要なことを、主にWeb開発の視点から記載した書籍といえます。

訳文について

こなれていて読みやすい訳文ですが、若干違和感のある訳語も見られます。
たとえば、Immutable Infrastructureは「不変の基盤」と訳されていますが、他でこのような訳を見たことがありません。一般には、訳さずそのまま使うか、カタカナ化して使うことが多いでしょう。
とはいえ、読者の方で補完可能な程度の瑕疵なので、それほど問題にはなりません。

まとめ

『レガシーソフトウェア改善ガイド』は、レガシーなプロジェクトに立ち向かう方法論を解説した書籍です。『レガシーコード改善ガイド』と比較して、より概説的で、ページ数も少ないです。

どちらを読もうか迷っている場合は、『レガシーソフトウェア改善ガイド』で総論を押さえてから、『レガシーコード改善ガイド』でコードの改善方法をみっちり学ぶ、という順番がオススメです。

『Laravelリファレンス』を読んだ/Laravel雑感

入手自体はかなり早かったんですが、サンプルコードを試す機会を逸していてレビューが遅れました。。。

Laravelとは

Laravelは、2016年現在、最も人気のあるPHPフレームワークといってよいと思います。個人的には、Laravelの特徴は以下の3点だと思ってます。

(1) 高機能なフルスタックフレームワーク

PHPには、「フルスタック」を標榜するフレームワークがいくつもありますが、その中でもLaravelは高機能な部類に入ります。Symfonyという、それ自体高機能なフレームワークのコンポーネントを、さらに拡張するような作りになっています。私は現在は主にSymfonyを使用していますが、「この機能Symfonyにもほしい!」というものが結構あります。

(2) 変化の速さ

Laravelは変化の速いフレームワークです。メジャーバージョンの遷移は以下のようになっていて、メジャーバージョンが上がる毎に大きな設計変更が行われています(出典:https://ja.wikipedia.org/wiki/Laravel)。

  • Laravel 1: 2011年6月
  • Laravel 2: 2011年11月
  • Laravel 3: 2012年2月
  • Laravel 4: 2013年5月
  • Laravel 5: 2015年2月

Laravel 5.1では、初のLTS(Long Term Support)となり、3年間のサポートが提供されることが決まりました。しかし、SymfonyのLTSとは異なり、LTSでも機能追加が行われていたりします。また、現在の最新版は5.2です。

(3) エッジなターゲット

Laravelは、「そのバージョンがリリースされた時点で公式サポートされているPHP」を、動作対象バージョンの指標にしているようです。Laravel 5.1ではPHP 5.5.9以上が対象になっています。また、Laravelに最適されたPHP開発環境のHomesteadは、v0.4.0以降ではPHP 7.0がインストールされています。

Laravelリファレンスについて

Laravelリファレンスは、その名の通り「リファレンス」という色合いが強いです。以下が目次ですが、初心者向けは1章と2章です。8章はチュートリアル形式ですが、Laravelの基本機能を触ってみるというよりは、Laravelの機能を活かしつつ、最近採用が増えているレイヤードアーキテクチャの実践をやってみよう、といった応用的な内容です。

Chap.01 Laravelの概要
Chap.02 Laravelの基本
Chap.03 データベース
Chap.04 フレームワークの機能
Chap.05 フレームワークの拡張
Chap.06 テスト
Chap.07 実践的なアプリケーション構築
Chap.08 Laravelの実践

タイトルに「リファレンス」とあるとおり、通読する本というよりは、ざっと目を通して、後で必要になった時に調べる本だと思います。Laravelにどんな機能があるか眺めるには便利です。

また、サンプルコードも全てgithubで公開されています。第8章のサンプルコードなどは、書籍の方では解説が割愛されている部分でも工夫を凝らした実装がされていたりするので、一度眺めてみると良いと思います。

Laravelの優れた機能

個人的に気に入ったLaravelの機能をいくつか挙げていこうと思います。

マイグレーション

データベース定義をPHPソースコードで記述することができます。コードで記述されていることから、ロールバックが容易です。個人的に、DB定義はMySQL WorkbenchでER図を書いて、このER図に基いてSQLを作ることが多いです。この形式は、ドキュメント(ER図)からDB定義ができるという点では非常に便利ですが、ソースコードでDB定義が管理できることには別の便利さがあります。

Secure by defaultなクエリビルダ

これはSymfonyのORM(Doctrine)のクエリビルダとの比較になるのですが、LaravelのORM(Eloquent)は、より安全に書けるようになっています。

Doctrineのクエリビルダで単純にクエリを書くと以下のようになります。

この書き方には、潜在的なSQLインジェクションの脆弱性があります。eq()メソッドの第2引数の値はエスケープされず、プリペアードステートメントも使われないため、$nameにSQL文が入っていた場合はそのクエリが実行される可能性があります(Doctrineのソースコード)。

Doctrineでの正しい書き方は以下のようになります。この書き方だとプリペアードステートメントが使われます。

これに対して、Eloquentは以下の書き方でプリペアードステートメントが使われます。何も注意しなくても、デフォルトで安全に使えるようになっています。

FormRequestによるバリデーション

LaravelにはFormRequestという仕組みがあります。これは、コントローラーの手前でバリデーションを行う仕組みです。
FormRequestでは、各アクションに応じて、IlluminateFoundationHttpFormRequestクラスを拡張したクラスを作成します(titleを必須・最大文字数255、bodyを必須に設定)。

このEntryStoreRequestを使ったコントローラーの実装は以下のようになります。

バリデーションルールに合致していないリクエストが送られてきた場合、FormRequestが自動的にエラーのレスポンスを返します。バリデーションとエラー通知の責務をコントローラーから分離することができます。

Laravelのイマイチなポイント:メタプログラミングの多用

上述したように、Laravelには優れた機能が多くありますが、Laravelでは気持ちよくコードが書けないと感じることも多いです。その理由は、メタプログラミングの多用にあります。

Laravelの特徴の一つであるFacadeを使うと、以下のような記述ができます。

Config::get()は静的メソッド呼び出しですが、Configというクラスが存在するわけではありません。config/app.phpに以下のような設定がされています。

この設定に基いて、PHPのclass_alias関数によって「Config」というクラスの実体がIlluminateSupportFacadesConfigであると定義されています。このクラスからさらにサービスコンテナへの問合せが行われ、最終的にIlluminateConfigRepository::get()メソッドが呼び出されます。

このように複雑なメタプログラミングが使用されていることから、静的解析を主に用いているIDEとの相性は良くありません。ide-helperプラグインを用いて、クラス定義を静的に書き出すことでFacadeなどはIDEの補完が効くようになりますが、それでも限界はあります。以下は『Laravelリファレンス』8章のサンプルコードをPhpStormで開いているところのスクリーンショットですが、orderBy()に未定義メソッドの警告が出ています。

laravel_orderBy

ここで使用されているIlluminateDatabaseEloquentBuilder::where()は自分自身を返しますが、IlluminateDatabaseEloquentBuilderは自分が持っていないメソッド名が呼び出されると、__call()メソッド内部でIlluminate/Database/Query/Builderの機能を呼び出します。Illuminate/Database/Query/BuilderがorderBy()を持っているので、これが呼び出される、という流れになっています。

このように、頻繁に使用するメソッドでも補完が効かないことがあるのは地味につらいところです。

まとめ

『Laravelリファレンス』について、というよりはLaravelについての方が話が膨らんでしまいましたが、『Laravel』リファレンスはLaravel 5を使い始めるにあたって、まず手元に置いておきたい1冊だと思います。分厚い本ですが、リファレンス的に使うことを考えると、紙の方が良いと思います。

Laravel リファレンス[Ver.5.1 LTS 対応] Web職人好みの新世代PHPフレームワーク