55. Server-side web frameworks
【所要時間】
3時間3分(2018年9月26,28,29日)
【概要】
Webアプリケーションフレームワークについて
【要約・学んだこと】
Overview
サーバーサイドウェブフレームワークス(ウェブアプリケーションフレームワークス)は、記述、保守、スケールウェブアプリケーションを簡単にするソフトウェアフレームワークスだ。これらは適切な処理のためのURLのルート化、データベースの相互作用、セッションやユーザー認証のサポート、出力フォーマット(HTML, JSON, XMLなど)、ウェブ攻撃からのセキュリティ向上などの、一般的なウェブ開発タスクを単純化するツールやライブラリを提供する。
What can a web framework do for you?
サーバーサイドウェブフレームワークは必ずしも使わなければいけないわけではないが、使うことを強く推奨する。これからウェブフレームワークでよく実装されている機能を紹介する。
Work directly with HTTP requests and responses
HTTPプロトコルを通じてウェブサービスとブラウザは通信する。サーバーはブラウザからのHTTPリクエストを待ち、HTTPレスポンスに情報を返す。ウェブルフレームワークはこれらのリクエストとレスポンスを働かせるためのサーバーサイドコードを作るためのシンタックスを簡単に書けるようにする。
下記の例はDjango(Python)ウェブフレームワークの動作の仕方を示している。”view” function(リクエストハンドラ)がリクエスト情報を含むHttpRequest objctを受け取るたびに、フォーマットされた出力(この場合string)をHttpResponse objetに返すように要求される。
# Django view function
from django.http import HttpResponse
def index(request):
# Get an HttpRequest (request)
# perform operations using information from the request.
# Return HttpResponse
return HttpResponse('Output string to return')
Route requests to the appropriate handler
多くのサイトは多数のリソースを提供し、別個のURLからアクセスできる。これらを1つの昨日で取り扱うのは維持するのが難しい。そこでウェブフレームワークはURLパターンを特定のハンドラ機能にマップする簡単なメカニズムを提供する。
このアプローチはメンテナンスでも利点がある。なぜなら下層コードの変更なしで、特定の特徴を届けるために使われるURLを変えることができるからだ。
フレームワークごとにマッピングのメカニズムは異なる。例えば、Flask(Python)ウェブフレームワークはデコレータで使うview機能にフレームワークを追加する。
@app.route("/")
def hello():
return "Hello World!"
一方Djangoは開発者がURLパターンとview機能間のURLマッピングリストを定義することを期待する。
urlpatterns = [
url(r'^$', views.index),
# example: /best/myteamname/5/
url(r'^(?P<team_name>\w.+?)/(?P<team_number>[0-9]+)/$', views.best),
]
Make it easy to access data in the request
データは様々な方法でHTTPリクエストにエンコードできる。サーバーからファイルやデータを取得するためのHTTP GET requestは、URL parameter、またはURL構造内で必要とされるデータにエンコードできる。サーバー上でリソースを更新するためのHTTP POSTは、リクエストのbody内にある”POST data”として更新情報を含む。HTTP requestは現在のセッションや、クライアントサイドクッキーのユーザーについての情報を含む。
ウェブフレームワークはこの情報にアクセスするための適切なプログラミング言語メカニズムを供給する。例えば、Djangoがすべてのview functionに渡すHttpRequestオブジェクトは、ターゲットURLにアクセスするためのメソッドとプロパティ、リクエストタイプ(HTTP GET)、GETまたはPOST parameter、クッキーとセッションデータなどを含む。
DjangoはURL mapperで”capture patterns”を定義することで、URLの構造内でエンコードした情報も渡すことができる。
Abstract and simplify database access
ウェブサイトはユーザーとシェアされる情報と、ユーザーについての情報を保存するためにデータベースを使用する。ウェブフレームワークはデータベースの読み込み、書き込み、質問、操作の削除を抽象化するデータベースレイヤをしばしば提供する。この抽象化したレイヤはObject-Relational Mapper(ORM)として参照される。
ORMには2つのメリットがある。
- 下層データベースを使っているコードを変える必要なしで、下層データベースを置き換えられる。これにより、開発者はは使用状況によって異なるデータベースの特徴を最適化することができる。
- 基本的なデータ検証がフレームワーク内で行える。これにより正しいタイプのデータベースフィールドに保存されているデータが、正しいフォーマット(e-mailアドレスなど)を持つか、悪意のあるものではないか(クラッカーはデータベースの記録を消すような悪意のある特定のパターンのコードを使うことがある)を簡単に、安全にチェックすることができる。
例えば、DjangoウェブフレームワークはORMを提供し、モデルとして記録構造を定義するために使用するobjectを参照する。モデルは保存されるフィールドタイプを指定する。これは格納される情報のフィールドレベルの検証を提供する。(eメールフィールドが正しいeメールアドレスのみ許可するなど)
フィールドの定義は最大サイズ、デフォルトvalue、リストオプションの選択、ドキュメント化のヘルプテキスト、フォームテキストのラベルなどがある。このモデルでは、下層データベースに関する情報は記載されていない。これは、コードとは別に変更される可能性がある構成設定でからだ。
下記のスニペットの最初のコードは、Team objectのシンプルなDjango modelを表している。これがキャラクターフィールドとしてチーム名、チームレベルを保管し、それぞれのレコードに格納する最大文字数を指定している。team_levelはchoice filedなので、表示される選択肢と、格納されるデータを、デフォルトvalueと共にマッピングもする。
#best/models.py
from django.db import models
class Team(models.Model):
team_name = models.CharField(max_length=40)
TEAM_LEVELS = (
('U09', 'Under 09s'),
('U10', 'Under 10s'),
('U11, 'Under 11s'),
... #list our other teams
)
team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
Djangoモデルはデータベースを検索するために簡単なquery APIを提供する。これは異なる基準を使い、一度にたくさんのフィールドとマッチさせることができる。(exact, case-insensitive, greater thanなど)そして複雑な式のサポートもできる。(たとえば”Fr”ではじまり”al”で終わるU11チームの検索を指定する)
2つ目のコードスニペットはU09チーム全てを表示するためのview function(リソースハンドラ)を表している。この場合、team_level fieldが正確に”U09"(この基準がどのようにfilter() functionに、field名を持つargumentとして渡されるか、2つの_でマッチタイプが分けられているかを注意する。:team_level__exact)を持つ記録全てをフィルターしたいと指定している。
#best/views.py
from django.shortcuts import render
from .models import Team
def youngest(request):
list_teams = Team.objects.filter(team_level__exact="U09")
context = {'youngest_teams': list_teams}
return render(request, 'best/index.html', context)
Rendering data
ウェブフレームワークはテンプレートシステムを供給する。これらがアウトプットドキュメントの構成を指定できるようにし、ページが作成されるときに加えられるデータのプレースホルダーを使う。テンプレートはよくHTMLを作るのに使うが、他のタイプのドキュメントを作るのにも使うことができる。
ウェブフレームワークはJSON, XMLを含む格納されたデータから他のフォーマットを作るのを簡単にするメカニズムをよく提供する。
例えば、Djangoテンプレートシステムは、”double-handlebars” シンタックスを使ったvariableを指定できるようにする。これはページがレンダーされるときにview functionからvalueが渡されることによって、置き換えられる。テンプレートシステムはexpressionのサポートをも提供する。(with syntax: {%expression %})。これはテンプレートがテンプレートに渡されたlist valueをiteratingするといった簡単な処理を実行することを可能にする。
Note: 他のテンプレートシステムは似たようなsyntaxを使う。Jinja2(Python)、handlebars(JavaScript)、moustache(JavaScript)など。
下記のコードスニペットはこれがどのように動くかを示している。前のセッションの”yongest team”の例を引き続き使う。HTML テンプレートはviewによってyongest_teamsと呼ばれるlist variableを渡される。HTMLスケルトンの内部には、youngest_teams variableが存在するかどうかを最初にチェックする式があり、それをfor loopで反復する。それぞれの反復テンプレートは、list itemのチームのteam_name valueを表示する。
#best/templates/best/index.html
<!DOCTYPE html>
<html lang="en">
<body>
{% if youngest_teams %}
<ul>
{% for team in youngest_teams %}
<li>{{ team.team_name }}</li>
{% endfor %}
</ul>
{% else %}
<p>No teams are available.</p>
{% endif %}
</body>
</html>
How to select a web framework
ほぼ全てのプログラミング言語にウェブフレームワークは存在する。
どれを使うか決める際に下記の要素を考えると良い。
- 学習意欲:
学習意欲はどれだけ下層プログラミング言語を知っているか、APIの一貫性、ドキュメントの質、コミュニティの規模や活発さによる。もし完全な未経験者ならDjangoを検討すると良い。(上記の基準からすると、最も学びやすい)。もしすでに開発チームにいるなら、そこで使われているものにすればよい。 - 生産性:
生産性はフレームワークについて知った後、どれだけ早く新しい機能を作れるかが基準となる。コードを書くこと、維持することどちらについてもだ。(古いものは壊れるので、新しい機能は書けない。)
生産性に影響する様々な要素は、学習意欲に似ている。ドキュメント、コミュニティ、経験などだ。
他には下記の要素が含まれる。
- フレームワークの目的、由来:
ウェブフレームワークによっては、元々特定のタイプの問題を解決するために作られ、同じような制約を持ったウェブアプリを作るのに適している。例えばDjangoは、ニュースペーパーウェブサイトの開発サポートのために作られたので、ブログや発行物に関するサイトによい。一方Flaskは、とても軽いウェブフレームワークで、埋め込みデバイス上で実行するアプリのために作られた。 - Opinionated vs unopinionated:
opinionated(独自のやり方に固執する)フレームワークは特定の問題を解決するためのベストな方法を推奨される。opinionatedフレームワークは、一般的な問題を解決しようとするときにより生産性が高まる傾向にある。なぜなら、正しい方向に導いてくれるからであるが、柔軟性がない場合もある。 - Batteries included vs. get it yourself:
ウェブフレームワークによっては、開発者が”デフォルト”だと考えうる全ての問題に対処するツールやライブラリを含むものがある。一方で、軽いウェブフレームワークは別々のライブラリから問題を解決するものを選んで使うことを期待しているものもある。(Djangoは前者で、Flaskは後者)
全てを含むフレームワークは必要なものが全て含まれているので簡単に始められ、よく統合化、ドキュメント化されていている可能性が高い。しかし、より小さいフレームワークが必要なものは全て持っていて、より拘束された環境で動作でき、学ぶもののセットが小さく簡単になる。 - フレームワークがいい実用環境を推奨するかどうか:
例えば、Model-View-Controllerアーキテクチャがコードを論理関数に分割するように促すフレムワークは、開発者が期待していないコードよりも、メンテナンス可能なコードとなるだろう。
同様に、フレームワークデザインはどれだけ簡単にテストやコードの再利用ができるかが大きなインパクトになりうる。
- フレームワークとプログラミング言語のパフォーマンス:
通常は”速さ”はこのセクションでは大きな要素にはならない。なぜならPythonのように比較的遅いランタイムでさえ、中程度のハードウェアで実行される中規模のサイトでは”十分”であるからだ。
C++やJavaScriptなどの他の言語でわかるスピードのメリットは、学習、メンテナンスコストで相殺されるかもしれない。 - cachingサポート:
ウェブサイトが成功して行くに連れて、ユーザーアクセスを受診している時のリクエスト数に対応できなくなった。cachingサポートを加えることを考える時だ。cachingはウェブリクエスト全て、もしくは一部を保管する場所の最適化のことなので、そのあとのリクエストを再計算する必要ない。cachしたリクエストを返すのは、一箇所で計算するよりもはるかに速い。cachingはコード内か、サーバー内(see reverse proxy)で実行することができる。ウェブフレームワークはキャッシュ化するコンテンツの定義のサポートを、様々なレベルで行う。 - スケール化:
ウェブサイトが成功すると、cachingのメリットがなくなり、vertical scalingの限界(よりパワフルなハードでアプリを実行する)に達することもある。この時点で、scale horizontally(いくつものサーバーやデータベースにサイトを分散して、負荷を分散する)もしくはscale “geographically”する必要がある。なぜなら、カスタマーによってはサーバーからと多く離れた所にいるからだ。選んだウェブフレームワークがサイトのスケール化がどれだけ簡単かを大きく分ける。 - ウェブセキュリティ:
ウェブフレームワークによっては、一般的なウェブ攻撃の対応のいいサポートを提供してくれる。たとえばDjangoは、HTMLテンプレートからのユーザーインプット全ての不適切な部分を削除するので、ユーザーがJavaScriptコードを書いても実行できない。
他のフレームワークでは同様の保護を提供するが、必ずしもデフォルトで使えるとは限らない。
他にもライセンス化、フレームワークの開発がアクティブか、といったたくさんの要素がある。
もしプログラミングのビギナーなら、”ease of learning”ナフレームワークを選ぶと良い。加えて、言語自体も簡単、ドキュメントやチュートリアルのクオリティが高く、新規ユーザーへのコミュニティのサポートが手厚いのが、価値のあるリソースとなる。
後の例は Django(Python) and Express (Node/JavaScript)で書かれている。主な理由は学びやすく、サポートが良いからだ。
Note:
Django (Python) and Express(Node/JavaScript)のメインページに行き、ドキュメントとコミュニティを見てみよう。どのようにURL routing、テンプレート、データベースやモデルをセットするかを見ることがで切る。また、直近でどれくらいの質問が投稿されたか、返信があったか、アクティブコミュニティがあるかを見ることができる。
A few good web frameworks?
いくつかの特定のウェブフレームワークにフォーカスしてみよう。
下記のサーバーサイドフレームワークは、記述時点で最も人気なものたちだ。それらは全て、オープンソース、アクティブに開発中、コミュニティがドキュメントを熱心に作っていて、ディスカッションボードのユーザーを助け、多くのウェブサイトに使われているという、必要な条件が揃っている。
Django (Python)
Djangoは、迅速な開発、クリーンで実利的なデザインをするのを推奨するハイレベルPythonウェブフレームワークだ。ウェブ開発の面倒を大事にしており、アプリの記述にフォーカスできる。フリーでオープンソースだ。
Djangoは”Batteries included”哲学に従っており、大抵の開発者が欲しいと思うであろう”out of the box”全てを提供する。なぜなら全てが含まれていて、お互いに作用し、一貫した設計原理に従い、拡張性と最新ドキュメントを持つ。素早く、安全で、スケーラブルだ。Pythonに基づき、Djangoのコードは読みやすく、維持しやすい。
Disqus, Instagram, Knight Foundation, MozillaなどがDjangoを使っている。
Flask (Python)
Flask はPythonのマイクロフレームワークだ。
ミニマリストであるが、シリアスなout of the boxウェブサイトを作ることができる。ディベロップメントサーバーとデバッガーを含み、Jinja2 テンプレート、セキュアクッキー、 unit testing 、RESTful request dispatchingのサポートを含む。良いドキュメントとアクティブコミュニティがある。
Flaskは小さく、リソースに制限のあるシステムのウェブサービスを必要としている開発者に特に人気だ。( Raspberry Pi, Drone controllers のウェブサーバーの実行など)
Express (Node.js/JavaScript)
Expressは速く、unopinionatedで柔軟性があり、Node.jsのための最小限のフレームワークだ(nodeはJavaScriptをブラウザレスで実行するための環境)。ウェブやモバイルアプリの強固な特徴のあるセットを提供し、有益なHTTP ユーティリティメソッドと、 middlewareを提供する。
ExpressはクライアントサイドJavaScriptウェブプログラマーがサーバーサイド開発に統合するのを簡単にするので人気だ。部分的にはリソース効率も良い。(下層node環境は、新しいウェブリクエスト毎に別々のプロセスを生成するのではなく、スレッド内でライトウェイトなマルチタスキングを使う。)
Expressはミニマリストウェブフレームワークなので、使用したいであろう全てのコンポーネントを組み込むわけではない。(例えばデータベースへのアクセスとユーザーやセッションのサポートは独立したライブラリを通じて提供される。)たくさんの素晴らしい独立コンポーネントがあるが、ときより目的によってどれが最適なのかを判断するのが難しい。
多くのサーバーサイド、フルスタックフレームワークはExpressに基づいている。Feathers, ItemsAPI, KeystoneJS, Kraken, LEAN-STACK, LoopBack, MEAN, and Sails などだ。
Uber, Accenture, IBMなどがExpressを使っている。
Ruby on Rails (Ruby)
Rails (通常は“Ruby on Rails”のこと)は、Ruby programming言語のために書かれたフレームワークだ。
RailsはDjangoの哲学に近い。routing URL、データベースからのデータアクセス、テンプレートからHTMLの作成、JSONやXMLとしてのデータフォーマットのスタンダードメカニズムを提供する。DRY (“dont repeat yourself” 可能な限りコードは使い回す)、MVC(model-view-controller)などのようにデザインパターンを使うことを推奨する。
設計上の決定、言語の性質など多くの違いはある。
Railsは Basecamp, GitHub, Shopify, Airbnb, Twitch, SoundCloud, Hulu, Zendesk, Square, Highrise などで使われている。
ASP.NET
ASP.NETはモダンウェブアプリやサービスを構築するためにMicrosoftによって開発されたウェブフレームワークだ。ASP.NETを使うことで、HTML、CSS、JavaScriptに基づいたWebサイトを素早く作ることができる。また、たくさんの人によって使われるようにそれらをスケールし、Web APIs、データを超えた書式、リアルタイムコミュニケーションといった、より複雑な機能を簡単に加えることができる。
ASP.NETの違いの1つは、Common Language Runtime (CLR)で構築され、.NETにサポートされている言語(C#, Visual Basicなど)ならば、どれでも使うことができる。多くのMicrosoft製品のように、素晴らしいツール(また、無料)、開発者コミュニティ、いいドキュメントなどの利益を使うことができる。
ASP.NETはMicrosoft, Xbox.com, Stack Overflowなどで使われている。
Mojolicious (Perl)
Mojoliciousは Perlプログラミング言語による次世代ウェブフレームワークだ。
初期のウェブでは、多くの人々がPerlを学んだ。なぜなら CGIとよばれる素晴らしいPerl libraryがあったからだ。言語についてあまり知らなくてもはじめやすく、十分強力だった。Mojoliciousは最先端技術を使用してこのアイデアを実装している。
Mojoliciousに提供されているいくつかの特徴は、 単一のファイルプロトタイプを構造化されたMVCウェブアプリケーションに拡張する、リアルタイムのウェブフレームワークだ。RESTful routes, プラグイン、コマンド、Perlish templates、交渉内容、セッション管理、検証フォーム、テストフレームワーク、静的ファイルサーバー、BGI/PSGI検出、ファーストクラスUnicode supportなどがある。
IPv6, TLS, SNI, IDNA, HTTP/SOCKS5 proxy, UNIX domain socket, Comet (long polling), keep-alive, connection pooling, timeout, cookie, multipart and gzip compression supportによって、フルスタックHTTPとWebSocketクライアント/サーバーを実装する。
【わからなかったこと】
【感想】
ウェブフレームワークはたくさんの種類がある。