設計思想¶
このドキュメントでは、 Django の開発者たちがフレームワークの構築に取り入れ ている根本的な設計思想についていくつか解説します。それによって、 Django の これまでの経緯に説明を与えつつ、将来への指針にしたいと思います。
概要¶
疎結合¶
Django スタックの基本的な目標は、疎結合と高い凝集度 を実現することです。フレームワークの各レイヤーは絶対に必要でない限り、相手をお互いに「知る」べきではありません。
たとえば、テンプレートシステムはウェブリクエストに関して、データベースレイヤーはデータの表示に関して、ビューシステムはプログラマーが使用しているテンプレートシステムがどんなものか、何も知りません。
Django は利便性のためにフルスタックとなってはいますが、スタックのどのコンポーネントも、可能な限り独立させてあります。
短いコード¶
Django のアプリはボイラープレートを書かなくて済むようにできるだけ短いコードになるようにされています。Django は、たとえばイントロスペクションなどの Python の動的な性質を最大限に生かすようになっています。
素早い開発¶
21世紀のWebフレームワークに重要なことは、Web開発の様々な側面を高速で行えるようになっていることです。Django は驚くほど素早いWeb開発を可能としています。
同じことを繰り返さない (DRY)¶
多大に区別される概念やデータ構造は、ただ1箇所のみに存在するべきです。冗長性は悪であり、正規化は善です。
フレームワークは、合理的な範囲内で可能な限り少ないものからできる限り多くのものを推測するべきです。
暗黙よりもはっきり示した方がいい (Explicit is better than implicit)¶
これは、PEP 20 にリストアップされた Python の核となる原則の1つです。つまり、Django は「魔法」を使いすぎてはならないということです。魔法を使っても良いのは、それを本当に使うべき理由があるとき、他の方法では到達できない非常に大きな利便性があるときだけです。ある機能の使い方を学ぶ開発者を混乱させるような方法で実装してはいけません。
一貫性¶
フレームワークはあらゆるレベルで一貫性を持たなければなりません。一貫性は、低レベル (採用する Python のコーディングスタイル) から高レベル (Django の使い方) までのあらゆる点で保たれなければなりません。
モデル¶
暗黙よりもはっきり示した方がいい (Explicit is better than implicit)¶
フィールド名のみに基づいてフィールドの振る舞いが決まるべきではありません。そのようにしてしまうと、システム全体に対する深い知識が必要となり、誤りの原因となりやすいです。その代わりに、キーワード引数や、場合によってはフィールドの型によって振る舞いが変わるようにします。
関連するドメインのロジックをすべて含める¶
モジュールは、マーティン・ファウラーの Active Record のデザインパターンに従い、「オブジェクト」のすべての側面をカプセル化する必要がります。
その理由は、モジュール (人間に読みやすい名前や、デフォルトの順序のオプションなど) について、モデルと情報の両方が表現するデータはモデルクラスで定義されており、与えられたモデルを理解するのに必要なすべての情報はモデルの 中に 存在するべきだからです。
データベース API¶
データベース API の主要な目的は、次のとおりです。
SQL の効率性¶
SQLステートメントはなるべく少ない回数実行されるべきで、またステートメントは内部で最適化されるべきです。
フレームワークが舞台裏で黙って保存するのではなく、開発者が明示的に save()
を呼び出す必要があるのはこのためです。
これは select_related()
QuerySet
メソッドが存在していることの理由でもあります。このメソッドは、「関係する全てのオブジェクト」を選択というよくあるケースでの効率上昇オプションです。
無愛想で、強力な構文¶
データベース API はできる限り小さい構文で、豊かで表現力のあるステートメントを書けるべきです。そして、それは他のモジュールや補助オブジェクトのインポートに頼るべきではありません。
結合処理は、必要なときに、舞台裏で自動的に行われるべきです。
全てのオブジェクトはシステム全域の全ての関係するオブジェクトにアクセスできるべきです。このアクセスは両方向にできるべきです。
必要なときに簡単に選べる生QPLという選択肢¶
データベースAPIは単なるショートカットであり、必ずしも機能のすべてを網羅するものではないことに留意してください。フレームワークはカスタムSQL文を簡単に書けるようにしておくべきです -- 構文全体、あるいはAPIを呼び出すカスタムパラメータとしての独自の WHERE
節など。
URL デザイン¶
疎結合¶
Djangoアプリケーションに含まれるURLは、基礎となるPythonコードと結合させるべきではありません。Pythonの関数名にURLを結びつけるのは最悪の行為です。
これらに関連して、DjangoのURLシステムは、同じアプリケーションであっても異なるコンテキストによってURLが異なるものになることを許容すべきです。例えば、ストーリーに関するページを /stories/
に配置し、別のページでは /news/
を使うかもしれません。
無限の柔軟性¶
URLは可能な限り柔軟性を持たせています。考えうる URL デザインが利用できます。
ベストプラクティスの推奨¶
フレームワークは、開発者が醜いURLよりもきれいなURLをデザインするのと同じくらい(あるいはそれ以上に)簡単であるべきです。
WebページのURLにファイル拡張子を含めるのは避けるべきです。
URLのビネット式カンマは絶対に使わないでください。
正確なURL¶
技術的には、 foo.com/bar
と foo.com/bar/
は相異なるURLであり、検索エンジンのロボット(やWebトラフィックの解析ツール)はこれらを異なるページとして扱います。DjangoはできるだけURLを標準化し、検索エンジンロボットが混乱しないようにすべきです。
これが APPEND_SLASH
設定の理由です。
テンプレートシステム¶
ロジックのプレゼンテーションからの分離¶
私達は、テンプレートシステムはプレゼンテーションとプレゼンテーション関係のロジックを制御するためのツールであり、それ以上のものではないと考えています。 その本分をこえた機能をテンプレートシステムに求めるべきではありません。
冗長性の排除¶
大多数の動的な Web サイトでは、ヘッダやフッタ、ナビゲーションバーといった部分のデザインをサイト全体で共通にしています。 Django テンプレートシステムは、 こうしたサイトの構成要素を一箇所に保存しやすくし、重複したコードを削除する必要があります。
これが テンプレートの継承 の背後にある思想です。
HTML と疎結合であれ¶
テンプレートシステムは、ただ単に HTML だけを出力するように設計されてはいません。他のテキストベースのフォーマットや、単純なプレインテキストも同じように上手く生成できるように作られています。
テンプレート言語として、XML を使うべきではない¶
テンプレートをパースするのに XML エンジンを使ってしまうと、テンプレートの編集に全く新しいヒューマンエラーの世界を作り出してしまい、結果として、テンプレート処理に受け入れられないようなレベルの困難を生み出してしまうでしょう。
ページデザイナの有能さを前提にする¶
必ずしも Dreamweaver のような WYSIWYG エディタでうまく表示できるように テンプレートシステムを設計する必要はありません。そのような要求は制限が厳しすぎ、本来あるべきすっきりした構文を実現できなくなります。 Django では 直接 HTML を編集する作業に慣れたテンプレート作者を想定しています。
ホワイトスペースを明示的に扱う¶
テンプレートシステムは、ホワイトスペースに対して変わった処理を行うべきではありません。もしテンプレートにホワイトスペースが書かれていれば、他の文字と同じように扱って、それをそのまま表示するべきです。テンプレートタグの外に書かれたすべてのホワイトスペースは、そのまま表示するべきです。
新しいプログラミング言語を開発しない¶
私たちの目的は、新しいプログラミング言語を開発することではありません。本当の目的は、プログラミング言語が持つような機能を必要十分なだけ使えるようにすることです。たとえば、条件分岐やループといったもので、これらはプレゼンテーションに関連する決定を下すときに大切になります。 Django テンプレート言語 (Django Template Language; DTL) は、複雑なロジックを使わずにこの目的を達成するために作られました。
安全性とセキュリティ¶
テンプレートシステムは、コマンドの実行やデータベースレコードの削除を行うような、悪意のあるコードの挿入ができないようになっていなければなりません。
これが、テンプレートシステムが任意の Python コードの実行を許さないようにできているもう一つの理由です。
拡張性¶
テンプレートシステムは、高度なテンプレート作者によるテクノロジの拡張に配慮せねばなりません。
これが、カスタムテンプレートタグとフィルタの背後にある思想です。
ビュー¶
シンプルであること¶
ビューは、Python の関数を書くのと同じくらい簡単に書けるべきです。開発者は、ふつうに関数を書くときと同じように、クラスからインスタンスを作ったりせずにビューが書けるべきです。
request オブジェクトを使うこと¶
ビューはリクエストオブジェクトにアクセスします。リクエストオブジェクトとは、 現在のリクエストに関するメタデータを入れるオブジェクトです。ビューはこのオブジェクトをグローバル変数経由でアクセスするのではなく、引数として直接受け取るようにすべきです。それにより、「偽の」リクエストオブジェクトを渡してビューを簡単かつクリーンにテストできるようになります。
疎結合¶
ビューは、開発者がどのテンプレートシステムを使用しているか意識せずに使えるべきです。もっと言えば、テンプレートシステム自体を使っているかどうかも気にせずに使えるようにするべきです。
GET と POST を区別¶
GET と POST は区別します。開発者は明示的に一方を他方と区別して明示的に使用するべきです。フレームワークは、GET と POST データを分かりやすく区別できるようにしなければなりません。
キャッシュフレームワーク¶
Django の キャッシュフレームワーク の主な目的は次の点にあります。
短いコード¶
キャッシュは可能な限り高速でなければならない。したがって、キャッシュバックエンドを包んでいるフレームワークのコード (特に get()
操作) はすべて、極限まで短くするべきである。
一貫性¶
キャッシュ API は、バックエントが違っていても一貫したインターフェイスを提供するべきである。
拡張性¶
キャッシュ API は、開発者のニーズにもとづいて、アプリケーションレベルで拡張可能であるべきである (例としては キャッシュキーの変換 がある)。