『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フレームワーク

『基本からしっかり学ぶSymfony2入門』を読んだ

基本からしっかり学ぶ Symfony2入門

本書は、PHPフレームワークSymfonyの入門書。

Symfonyとは

Symfonyは、PHP製のWebアプリケーション・フレームワーク。PHPのフレームワークの中でも、PHPコミュニティに対する影響力の大きさという点で特筆に値する。コンポーネントの疎結合化とDIコンテナによるコンポーネントの統合、Composerによる各コンポーネントの管理など、PHP 5.3以降のPHPフレームワークの多くで取り入れられている要素は、Symfonyに端を発している(※)。

※:Symfonyが採用している設計思想はSymfonyオリジナルのものではないけれど、Symfonyはこれらの設計思想に基づいたコンポーネントを使いやすい形で提供することで、コミュニティに影響を与えている。

また、コンポーネント単位の再利用が可能であることから、Drupal等のCMSや、コマンドラインツール、さらにはSymfonyコンポーネントの上に作ったフレームワーク(Laravel)まで、Symfonyコンポーネントを利用したプロダクトも多数登場している。

Symfonyの難しさ

Symfonyは、上述したように、影響力の大きさや、コンポーネント単位での再利用のしやすさ等の良さがある一方で、重量級のフルスタックフレームワークにありがちな、機能が多いがゆえの難しさもある。

Symfonyのドキュメントはかなり充実しているが、元々の機能が多い上、柔軟性を高めるために複雑になっている機能もあり(特にSecurityコンポーネント)、初心者が簡単に使い始められるようにはなっていない。

自分としては、Symfonyを学ぶ最短ルートは以下のようになると思っている。

  1. The Symfony Bookを通読する
  2. Symfony Best Practicesを通読する

これらの分量を合わせると約250ページ程度で、フレームワークの入門資料としては適度な分量のように思える。ただ、日本人の開発者にとって問題なのは、これらのドキュメントが全て英語で書かれていることである。日本語ドキュメントは存在するが、対応バージョンが古いのが難点。少なくとも、ドキュメントを読んで理解できる程度の英語力が無いのであれば、Symfonyを採用すべきではない。悩ましいのは、たとえ英語が読める人でも、日本語を読むのに比べると英語を読む速度はかなり落ちるということ。

入門段階から英語力が必須になる点が、Symfonyを学ぶ上での大きな課題だと感じていたところに、『基本からしっかり学ぶSymfony2入門』が出た。

『基本からしっかり学ぶSymfony2入門』の概要

『基本からしっかり学ぶSymfony2入門』は、日本語で書かれた、Symfony 2.7の入門書。主著者の後藤 秀宣(@hidenorigoto)氏は、知る人ぞ知る日本Symfonyユーザ会のグル(導師)。そんな後藤さんの本ということで、事前の期待度は高かったのだけど、期待は裏切られなかった。

対応バージョンについて

Symfonyはつい先日2.8と3.0が出たばかりなので、「2.7なんて古いバージョンじゃん!」と思うかもしれないが、Symfonyの最近のバージョンは安定してきているので、2.7と3.0では、メジャーバージョンアップとしてふつうイメージするほどの違いはない。そうはいっても、3.0では一部のディレクトリ構造が変わっていたりするので(app/consoleがbin/consoleに移動する等)、本書の「写経」をする場合は、2.7の利用をおすすめする。

なお、Symfony 2.7はLTS(Long Term Support)と呼ばれるバージョンであり、そのサポートは2018年5月まで続く。本書の「賞味期限」も、同じくらいは持つのでは、と思っている。

構成

Symfony製のWebアプリケーションの作成を通して、Symfonyの使い方を学べるようになっている。Symfony公式ドキュメントにはWebアプリケーションを作るようなチュートリアルが存在せず、非公式の「ブログチュートリアル」の類も、対応バージョンが古いという問題を抱えているものが多かった。

その点、本書は2.7という十分に新しいバージョンで、丁寧なチュートリアルが行われている。

項目の面からも、初心者がまず知るべきトピックは網羅されている。

  • ルーティングとアクション
  • テンプレートエンジンTwig
  • ORマッパーDoctrine
  • ログイン機能
  • Form
  • 外部プラグイン(SymfonyではBundleと呼ぶ)
  • DIコンテナ(Symfonyではサービスコンテナと呼ぶ)
  • 設定ファイル
  • コンソールアプリケーション
  • ユニットテスト・機能テスト

内容

詳しさでは、The Symfony Bookには一歩譲るし、Symfony Best Practicesの内容が全て網羅されているわけでもない。そういう意味で、公式ドキュメントの代替になるわけではない。

しかし、公式ドキュメントの通読に比べて、本書は圧倒的に速く読める。それでいて、Symfonyを使いはじめるのに必要な点はきっちり網羅されているので、Symfony入門の敷居を劇的に引き下げている。

自分がSymfonyを学び始めた今年の7月頃に、この本が出ていれば…と思わざるをえない。これからSymfonyを学ぼうとしている人には、本書を強くおすすめする。

Windowsフォームを丁寧に学べる本(ただしC#既修者に限る) – 書評:『10日でおぼえるC#入門教室』

10日でおぼえるC#入門教室 (10日でおぼえるシリーズ)

本書はC#とWindowsフォームの入門書。Windowsフォームというのは、Windowsデスクトップアプリを作るための技術の1つ。もう1つ新しい技術としてWPF(Windows Presentation Foundation)があり、実はWindowsフォームは既に新規機能の追加は(公式には宣言されていないが、事実上)停止している。

では、Windowsフォームを学ぶ必要がないのか、というとそうでもなく、Windowsフォーム製の既存資産を流用するにはWindowsフォームの知識が必要だったりする。

本書はWindowsフォームでGUIを作る→GUIを制御するC#コードを書くというレッスンの繰り返しで学習していくスタイルになっている。C#のコードの部分はそれなりに解説があるけれど、『スラスラわかるC#』のように、言語仕様だけに的を絞って解説している本に比べると、ややわかりづらい点は否めない。

また、内容的にも、単に言語仕様を解説するだけでなく、適切なクラス設計へのリファクタリングや、堅牢なアプリケーションを作るためのユニットテストの書き方などが含まれている。ユニットテストの書き方などはとてもありがたいが、C#入門の1冊目でここまでやるのは結構つらいのでは。

『スラスラわかるC#』の書評でも書いたけど、1冊目は言語仕様に的を絞った本を読んで、本書のようなGUIの作り方を解説している本は2冊目以降に読むのがおすすめ。

Amazonのレビューを見ると、「難しい」という意見が多いが、C#の基礎を身に着けてからだと、「Windowsフォームの操作の説明が丁寧でわかりやすかった」という印象が強い。ただ、確かにコード部分はレイアウトの問題もあって、若干読みづらい。あと、これはC#の標準的なスタイルなのかわからないが、フィールドを定義するより先にそのフィールドを操作しているメソッドが結構あって、C#の言語仕様的にはOKなんだけど、読みづらいコードだなあと感じる。

レッスンごとに新しくプロジェクトを作る、というスタイルは、必然的に操作に慣れることになるのでとてもよかった。

C#の入門書としてはおすすめできないが、Windowsフォームの入門書としては(他にライバルがいないというのもあるけど)おすすめ。