「コーディングスタイル (Dev docs)」の版間の差分
Toshihiro KITA (トーク | 投稿記録) |
Toshihiro KITA (トーク | 投稿記録) (→関連項目) |
||
(同じ利用者による、間の14版が非表示) | |||
1,257行目: | 1,257行目: | ||
例外タイプの完全なリストを取得するには、 'class +\w+_exception +extends'という正規表現を検索するか、あなたのIDEにmoodle_exceptionのすべてのサブクラスをリストアップするように依頼してください。 | 例外タイプの完全なリストを取得するには、 'class +\w+_exception +extends'という正規表現を検索するか、あなたのIDEにmoodle_exceptionのすべてのサブクラスをリストアップするように依頼してください。 | ||
適切な場合は、自分のコードで使用するためにmoodle_exceptionの新しいサブクラスを作成する必要があります。 | |||
いくつかの注目すべき例外タイプ: | |||
; moodle_exception : | ; moodle_exception : Moodleの例外の基本クラス。より特定のタイプが適切でない場合に使用します。 | ||
; coding_exception : | ; coding_exception : 開発者のミスが原因と思われる場合にスローされます。プラグインとやり取りするコアコードによって頻繁にスローされます。このタイプの例外をスローする場合は、エラーメッセージがプラグインの作者に役立つようにし、彼らが自分のコードを修正する方法を知ることができるようにしてください。 | ||
; dml_exception ( | ; dml_exception (およびサブクラス) : データベースクエリが失敗したときにスローされます。 | ||
; file_exception : | ; file_exception : File APIによってスローされます。 | ||
== | ==危険な関数や構造体== | ||
PHPには、深刻なセキュリティ問題の原因となることが非常に多いとされている、問題のある機能が複数含まれています。 | |||
# | # ''eval()'' 関数を使用しないでください。ただし、言語パックに関しては(将来的に解決されることを前提に)例外です。 | ||
# | # ''preg_replace()'' 関数を /e 修飾子とともに使用しないでください。PHPの予期しない実行を防止するために、コールバックを使用してください。 | ||
# | # バッククォートを使用してシェルコマンドを実行しないでください。 | ||
# | # ''goto'' 文、演算子、またはラベルを使用しないでください。代わりに他のプログラミング技法を使用して実行フローを制御してください。 | ||
== | ==コーディングスタイルの修正についての方針== | ||
このコーディングスタイルガイドが定義され、合意される前に、多くのコードがすでに書かれていました。明らかに、そのようなコードはまったくコーディングスタイルに従っていません。新しいコードについては '''従うことを強制します''' が、以前のコードの状態については過剰に心配していません。 | |||
いずれの場合でも、(進行中であり、重要でない) 移行を正規化するために、方針問題 (MDL-43233) が作成され、合意が得られました。そして、コーディングスタイルのみの変更に適用するルールは以下の通りです: | |||
# | # 実際の問題内で関連するコーディングスタイルの変更 (同じ行、メソッド/関数内の変数、隣接するコメントなど) は許可されます。 | ||
# | # 実際の問題内で関連しないコーディングスタイルの変更(他のメソッド、ブロックのコード、コメントなど)は、マスターにのみ、別のコミットで許可されます。 | ||
# | # コーディングスタイルのみの問題は、各サイクルの最初の2か月間に限り、マスターにのみ受け入れられます。 | ||
== | == Gitのコミット == | ||
クリアで分かりやすいコミットを作成することは、オープンソースのコード作成の重要な側面であり、コミット履歴は開発者間のコミュニケーションの重要な部分です。適切なコミットを作成するために時間をかけ、gitのツールを使用することが重要です。 | |||
Gitのコミットは以下のようにする必要があります: | |||
* | * コードが完璧に書かれた初回のような、完全で整理されたバージョンの履歴を表すこと。 | ||
* | * 変更に関連するMDL-xxxxの問題番号を含めること。 | ||
* | * 適切な場合にはCODE AREAを含めること。(Code areaとは、この変更が影響するMoodleの領域の短い名前です。コンポーネント名であっても構いませんが、そうである必要はありません。ここでの対象はコンピュータではなく人間であることに注意してください。コンポーネント名の省略形がより読みやすくて識別可能である場合は、そちらを使用してください。) | ||
* | * 以下の形式でフォーマットすること: | ||
<pre> | <pre> | ||
MDL-xxxx CODE AREA: | MDL-xxxx CODE AREA: 短い要約(72文字の制限) | ||
2行目には空白行を挿入し、必要に応じて無制限の詳細な説明を続けます。このセクションには、変更の動機や以前の動作との対比が含まれる場合があります。 | |||
</pre> | </pre> | ||
Gitのコミットには、以下のようなものは含めないでください: | |||
* 統合前に見つかったバグの修正内容 | |||
* 1つの問題に対して同じコード行の多数の別々の修正を含める | |||
* 論理的に1つのセットとして扱うべき変更を、恣意的に分割する | |||
詳細については、[[コミットチートシート (Dev docs)|コミットチートシート]]を参照してください。 | |||
== クレジット == | |||
# | このドキュメントは以下のソースから引用されています: | ||
# | |||
# | # オリジナルの[https://docs.moodle.org/en/index.php?title=Development:Coding&oldid=976 コーディングガイドライン]ページ | ||
# [http://framework.zend.com/manual/en/coding-standard.html Zendのガイドライン] | |||
# 全てのMoodleコア開発者からのフィードバック | |||
==関連項目== | ==関連項目== | ||
* [[Javascript/ | * [[Javascript/コーディングスタイル (Dev docs)|Javascript コーディングスタイル]] | ||
* [[ | * [[CSSコーディングスタイル (Dev docs)|CSS コーディングスタイル]] | ||
* [[ | * [[SQLコーディングスタイル (Dev docs)|SQLコーディングスタイル]] | ||
* [[ | * [[コーディング (Dev docs)|コーディング]] | ||
* [[CodeSniffer]] | * [[CodeSniffer (Dev docs)|CodeSniffer]] | ||
* [https://moodle.org/plugins/local_codechecker | * [https://moodle.org/plugins/local_codechecker コードチェッカープラグイン] | ||
* [[ | * [[アクセシビリティ (Dev docs)#Moodle関連のアクセシビリティコーディングガイドライン|アクセシビリティコーディングガイドライン]] | ||
[[カテゴリ:コーディングガイドライン|コーディングスタイル]] | [[カテゴリ:コーディングガイドライン|コーディングスタイル]] | ||
[[en:development:Coding style]] | [[en:development:Coding style]] |
2023年4月27日 (木) 07:11時点における最新版
重要:
このページの内容は更新され、新しいMoodle Developer Resourcesに移行されました。このページに含まれる情報は、もはや最新であるとみなされるべきではありません。 このページを新サイトで閲覧する そして より多くのコンテンツを新サイトに移行するために協力する というのはいかがでしょうか! |
(このページは現在翻訳中です。)
概要
範囲
この文書では、Moodleのコードを扱う開発者向けに、コードのレイアウトのメカニズムと、Moodleで採用した選択肢についての スタイル ガイドラインについて説明します。この仕様の目的は、異なる著者によるコードをスキャンする際の認知的な摩擦を減らすことです。それは、PHPコードをフォーマットするための共有されたルールや期待事項を列挙することによって実現されます。
特に指定がない限り、このコーディングスタイル文書は、順番に PSR-12、そしてPSR-1に従います 。
de-facto Moodle standard* が文書化されていない場合は、適切な MDLSITE の問題を提起し、そのスタンダードをこのコーディングスタイルガイドに記載するか、PSRの勧告を代わりに採用するようにしてください。
* "de-facto Moodle standard" とは、Moodleで一般的かつ典型的に使用されるコーディングスタイルを指します。
ゴール
どんな開発プロジェクトにおいても、一貫性のあるコーディングスタイルは重要であり、特に多数の開発者が関わる場合には必要不可欠です。標準的なスタイルを採用することで、コードをより読みやすく理解しやすくすることができ、全体的な品質を向上させることができます。
私たちが目指す抽象的な目標:
- シンプリシティ
- 読みやすさ
- ツールの使いやすさ、例えば、IDEツールやメソッド、クラス、定数名の自動補完をサポートするメソッドシグネチャ、定数、パターンの使用。
上記の目標を考慮する場合、各状況に応じて状況を検討し、様々なトレードオフをバランスさせる必要があります。
既存のMoodleのコードの多くが、これらのガイドラインに従っていない可能性があることに注意してください。私たちはそれを見つけ次第、このコードをアップグレードし続けています。
何かを実行するためにMoodle APIを使用する詳細については、コーディングガイドラインを参照してください。
便利なツール
このガイドに従うコードの記述に役立つ、いくつかの異なるツールがあります。
- コードチェッカー(eclipse/phpstormと統合)
- https://moodle.org/plugins/view.php?plugin=local_codechecker
- Moodle PHPdocチェッカー
- https://moodle.org/plugins/local_moodlecheck
両方のツールを使用して、書いているコードをチェックすることは価値があります。両方とも若干異なるチェックを実行するためです。 両方のチェッカーをパスできるようにすると、あなたの作品を審査する人々と友好的になるための良い道を歩んでいます。
ファイルフォーマット
PHPタグ
常に "long" PHPタグを使用してください。ただし、余分な空白を回避するため、ファイルの最後に閉じるタグを含めないでください。
<?php
require('config.php');
インデント
タブ文字を使用せず、インデントは 4つのスペースを使用してください。新しいタブ文字がソースコードに挿入されないように、エディタをタブをスペースとして扱うように設定する必要があります。
メインスクリプトレベルをインデントしないでください:
良い例:
<?php
require('config.php');
$a = required_param('a', PARAM_INT);
if ($a > 10) {
call_some_error($a);
} else {
do_something_with($a);
}
悪い例:
<?php
require('config.php');
$a = required_param('a', PARAM_INT);
if ($a > 10) {
call_some_error($a);
} else {
do_something_with($a);
}
SQLクエリは、SQLコーディングスタイルを参照して特別なインデントを使用します。
最大行長
最も重要な点は可読性です。
132文字を目指すことが望ましく、180文字を超えることは推奨されません。
例外は /lang ディレクトリ内の文字列ファイルで、行 $string['id'] = 'value'; の値は引用符で囲まれた1つの文字列として定義する必要があります(連結演算子、heredoc構文、newdoc構文は使用しない)。これにより、これらの文字列ファイルがPHPコードとして解釈されずに解析および処理できるようになります。
行の折り返し
行を折り返す場合、次のルールが一般的に適用されます。
- 通常は4つのスペースでインデントします。
- 制御文の条件や関数/クラス宣言といった折り返し行は、制御文や関数/クラスの本体と視覚的に区別できるように、4つのスペースでインデントします。
以下のセクションの例を参照してください。
制御構造の折り返し
while ($fileinfolevel && $params['component'] === 'user'
&& $params['filearea'] === 'private') {
$fileinfolevel = $fileinfolevel->get_parent();
$params = $fileinfolevel->get_params();
}
if文の条件式の折り返し
特別なことは何もなく、制御構造体の規則が適用されます。
if (($userenrol->timestart && $userenrol->timestart < $limit) ||
(!$userenrol->timestart && $userenrol->timecreated < $limit)) {
return false;
}
ただし、1つの制御構造に複数の条件がある場合は、条件式の評価に使用するためのヘルパー変数を設定して、可読性を向上させてください。
$iscourseorcategoryitem = ($element['object']->is_course_item() || $element['object']->is_category_item());
$usesscaleorvalue = in_array($element['object']->gradetype, [GRADE_TYPE_SCALE, GRADE_TYPE_VALUE]);
if ($iscourseorcategoryitem && $usesscaleorvalue) {
// 条件式がより簡単に見直しと理解ができるようになります。
}
次の例と比較してください。
// 以下は避けるべきです。
if (($element['object']->is_course_item() || $element['object']->is_category_item())
&& ($element['object']->gradetype == GRADE_TYPE_SCALE
|| $element['object']->gradetype == GRADE_TYPE_VALUE)) {
// 条件が複雑で長い行は、適切にインデントされていても非推奨です。
}
クラス宣言の折り返し
class foo implements bar, baz, qux, quux, quuz, corge, grault,
garply, waldo, fred, plugh, xyzzy, thud {
// クラス本体は4つのスペースでインデントされます。
}
また、読みやすくするために、実装されたインターフェースをそれぞれ1行にまとめて提供することもできます:
class provider implements
// これらの行は、クラス本体と視覚的に区別するために、8つのスペースでインデントされます。
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\provider,
\core_privacy\local\request\core_userlist_provider {
// クラス本体は4つのスペースでインデントされます。
}
関数シグネチャの折り返し
/**
* ...
*/
protected function component_class_callback_failed(\Throwable $e, string $component, string $interface,
string $methodname, array $params) {
global $CFG, $DB;
if ($this->observer) {
// ...
}
}
関数呼び出しのパラメータの折り返し
通常、パラメータは1行に収まるようになっています。1行に収まらないほど長くなる場合や、読みやすくなる場合は、空白を4つ入れてインデントします。
do_something($param1, $param2, null, null,
$param5, null, true);
配列の折り返し
特別なことはなく、一般的なルールが再び適用されます。折り返し行を4つのスペースでインデントします。
$plugininfo['preferences'][$plugin] = ['id' => $plugin, 'link' => $pref_url,
'string' => $modulenamestr];
多くの場合、各項目を1行にまとめた以下のようなスタイルが、コードをより読みやすくします。
$plugininfo['preferences'][$plugin] = [
'id' => $plugin,
'link' => $pref_url,
'string' => $modulenamestr,
];
最後の項目には末尾のカンマが残っていることに注意してください。これは、後で項目リストを拡張してよりきれいな差分を得ることができるようにするためです。同じ理由で、代入演算子も揃えない方がよいでしょう。
関数のパラメータとして渡される配列の折り返し
これは、上記のいくつかの例を組み合わせたものに過ぎません。
$url = new moodle_url('/course/loginas.php', [
'id' => $course->id,
'sesskey' => sesskey(),
]);
行の終端部
- すべての行は、Unixの改行文字(LF、10進数10、16進数 0x0A)で終了する必要があります。
- キャリッジリターン(CR、10進数13、16進数 0x0D)は単独または LF と一緒に使用してはいけません。
- 行末に空白文字(スペースやタブ)を入れてはいけません。
- ファイルの最後には余分な空白行があってはならず、すべてのファイルは1つの LF 文字で終わる必要があります。
注意: これはPSR-12の規約と一致しています。
命名規則
ファイル名
ファイル名は :
- 全て英語であること
- できるだけ短くすること
- 小文字のみを使用すること
- .php、.html、.js、.css、.xmlのいずかで終わること
クラス
クラス名は必ず小文字の英単語で、アンダースコアで区切ってください:
class some_custom_class {
function class_method() {
echo 'foo';
}
}
コンストラクタがパラメータを必要としない場合でも、新しいインスタンスを作成するときは常に()を使用します。
$instance = new some_custom_class();
例えば、$DB->insert_recordでデータベースに挿入するデータを準備するときなど、特定のクラスのないプレーンなオブジェクトが欲しいときは、PHP標準クラス stdClass を使用する必要があります。 例:
$row = new stdClass();
$row->id = $id;
$row->field = 'something';
$DB->insert_record('table', $row);
Moodle 2.0以前では、私たちはstdClassを拡張したクラス object を定義し、new object() を使用していました; これは現在非推奨です。代わりに stdClass を使用してください。
関数および手法
関数名は単純な英語の小文字の単語で、プラグイン間の衝突を避けるために Frankenstyle のプレフィックスとプラグイン名で始まるようにします。単語はアンダースコアで区切られる必要があります。
冗長性が奨励されます: 関数名は、理解を深めるために、できるだけ具体的に説明することが望ましいです。
PHPでは、すべての新しいコードに対して、タイプヒントと戻り値の宣言の使用が可能なすべての場所で要求されています。既存の非準拠なコードを拡張するコードや、利用できないものを実装するコードなど、必要な除外項目があるものとします。プログレッシブ・アプローチが適用されます。
関数名と次の(括弧)の間にスペースがないことに注意してください。また、Nullable文字(クエスチョンマーク - ?)とパラメータやリターンタイプの間、関数の閉じ括弧とコロンの間にも空白がありません。
function report_participation_get_overviews(string $action, ?int userid): ?array {
// 実際のファンクションコードはここに入ります。
}
ただし、レガシーな理由でプラグイン名のみをプレフィックスとして使用している活動モジュールは例外です。
function forum_set_display_mode($mode = 0) {
global $USER, $CFG;
// 実際のファンクションコードはここに入ります。
}
関数パラメータ
パラメーターは常に単純な小文字の英単語($initialvalueのように複数の場合もあります)であり、可能な場合は常に適切なデフォルト値を持つべきです。
このようにデフォルト値が必要ない場合は、"false" の代わりに "null" をデフォルト値として使用します。
public function foo($required, $optional = null)
ただし、オプションのパラメータが boolean であり、その論理的なデフォルト値が true または false である場合は、true または false を使用しても構いません。
変数
変数名は常に読みやすく、意味がある小文字の英単語でなければなりません。もし1つ以上の単語が必要な場合は、連結して書くことができますが、できるだけ短く保つようにしてください。オブジェクトの配列には、複数形 の名前を使用してください。そして、変数名には、常に 肯定的 な言葉を使うようにしてください。(例えば、prevent や disable ではなく、allow や enable などです。
GOOD: $quiz GOOD: $errorstring GOOD: $assignments (for an array of objects) GOOD: $i (but only in little loops) GOOD: $allowfilelocking = false
BAD: $Quiz BAD: $camelCase BAD: $aReallyLongVariableNameWithoutAGoodReason BAD: $error_string BAD: $preventfilelocking = true
Moodleのコアグローバル変数は、大文字の変数 (例 $CFG、$SESSION、$USER、$COURSE、$SITE、$PAGE、$DBおよび$THEME) を使用して識別します。 これ以上作らないでください!
定数
定数は常に大文字で、常に Frankenstyle のプレフィックスとプラグイン名で始まります(レガシーな理由からモジュール名のみで活動する場合)。単語はアンダースコアで区切ってください。
define('BLOCK_COURSE_OVERVIEW_SHOWCATEGORIES_NONE', '0');
define('FORUM_MODE_FLATOLDEST', 1);
ブーリアンおよびヌル値
true、false、nullは小文字を使用してください。
名前空間
Moodleの新しいクラスには、正式な名前空間が必要です。ただし、以下の例外があります:
- 既存の非名前空間クラスを名前空間に移動させる必要はありません; また
- クラスを読み込むための既存のメカニズムが存在し、そのメカニズムが名前空間クラスの使用をサポートしていない場合、クラス名に既存の Frankenstyle プレフィックスを使用することが許可されます。
クラス名に対するクラス名のFrankenstyleプレフィックスの使用は非推奨であり、上記の例外においてのみ使用されるべきである。
良い例:
namespace mod_forum;
class example {
}
namespace mod_forum\external;
class example {
}
namespace core_user;
class example {}
悪い例 (非推奨):
class mod_forum_example {
}
class mod_forum_external_example {
}
class core_user_example {
}
名前空間の使用は、以下のルールに従う必要があります:
- 名前空間に属するクラスは、プラグイン内のクラスディレクトリ(例:mod/forum/classes)または、コアコードの場合は lib/classes または subsystemdir/classesに作成する必要があります。
- すべての名前空間に属するクラスのクラス名とファイル名は、クラスの自動読み込みルールに従う必要があります。新しいコードには、形式的なPHP名前空間の使用が必要です。
- ファイルあたり1つの名前空間宣言を使用する必要があります。
良い例:
<? // これは mod/porridge/classes/local/equipment/spoon.php のファイルです。
namespace mod_porridge\local\equipment;
class spoon {
// ここにあなたのコード。
}
// ファイルの終了。
悪い例:
namespace mod_porridge\local\equipment;
class spoon {
// ここにあなたのコード。
}
namespace mod_porridge\local\procedures; // ここで名前空間を変更しているため、変更しないでください。
class eat {
// ここにもう1つのコード。
}
// ファイルの終了。
名前空間宣言は、ドックブロックで先行することができます。
クラスの命名は、名前空間の各レベルの名前にも適用されます。
名前空間宣言は、ファイル内で最初の非コメント行でなければならず、1つの空白行に続いて(オプションで)1行に1つの "use" ステートメントが続き、さらに1つの空白行が続きます。
"use" ステートメントは、コード内で長い名前空間を繰り返し使うのを避けるために使用する必要があります。
"use" ステートメントを使用して、名前空間全体をインポートしないでください。個々のクラスだけをインポートしてください。
衝突を解決するために絶対に必要でない限り、名前を付けてインポートしないでください("use XXX as YYY;")。
良い例:
use mod_porridge\local\equipment\spoon; // 1行につき1つのクラスです。
use mod_porridge\local\equipment\bowl; // 1行につき1つのクラスです。
悪い例:
use mod_porridge\local\equipment\spoon, mod_porridge\local\equipment\bowl; // 1行に複数のクラスがあります。
use mod_porridge\local; // 名前空間全体をインポートします。
use core; // 名前空間全体をインポートします。
use mod_breakfast; // 名前空間全体をインポートします。
use mod_porridge\local\equipment\spoon as silverspoon; // 名前を付けてインポートする理由がありません。
__NAMESPACE__のマジック定数を使用しないでください。
名前空間宣言以外の場所で "namespace" キーワードを使用しないでください。
悪い例:
$obj = new namespace\Another();
ブラケットで囲まれた "namespace" ブロックを使用しないでください。
悪い例:
namespace {
// グローバルスコープ。
}
名前空間は、"classes" のサブフォルダに存在するクラスにのみ使用する必要があります。
新しいクラスの場合 - 名前空間を決定する際には、最大の詳細レベルを使用する必要があります。
良い例:
namespace xxxx\yyyy; // xxxx はコンポーネント、 yyyy はAPIです。
class zzzz {
}
"namespace" および "use" ステートメントで先頭にバックスラッシュ(\)を使用しないでください。
名前空間付きのコードから呼び出されるグローバル関数には、先頭にバックスラッシュ(\)を使用しないでください。現在のスコープの外側のクラスは、先頭にバックスラッシュを使用するか、"use" キーワードでインポートされます。詳細については、PHPマニュアルを参照してください。
良い例:
namespace mod_breakfast\local;
use moodle_url;
echo get_string('goodmorning', 'mod_breakfast'); // グローバル関数の先頭にバックスラッシュがありません。
$url = new moodle_url(...); // "use" で名前空間にインポートしているので、先頭のバックスラッシュは必要ありません。
$tasks = \core\task\manager::get_all_scheduled_tasks(); // ここでは先頭にスラッシュが必要です。
$a = new \stdClass(); // ここでは先頭にスラッシュが必要です。
悪い例:
namespace \mod_breakfast; // 先頭のバックスラッシュはあってはいけません。
use \core\task\manager; // 先頭のバックスラッシュはあってはいけません。
\get_string('xxxx', 'yyyy'); // 先頭のバックスラッシュはあってはいけません。
名前空間の構成要素
以下のような完全修飾名でクラスが示されている場合:
"\<level1>\<level2>\<level3>\...\<classname>"
各名前空間のレベルには許容される要素について明確な規則があります。最初のレベルだけが必須です。クラスがコアAPIを実装する場合や、プラグイン管理者がプラグイン内の名前空間を分けてクラスを整理する場合は、ネストされた名前空間が使用されます。詳細はlevel2に関する規則を参照してください。
レベル1のルール
最初のレベルは、次のいずれかでなければなりません:
- 完全なコンポーネント名(例:"\mod_forum")。プラグインで名前空間を使用するすべてのクラスは、このレベル1の名前空間に含まれている必要があります。
または
- すべてのコアAPIに対して "\core" を使用してください。
レベル2のルール
第2レベルは、使用される場合、次のいずれかでなければなりません:
- コアAPIの短い名前(https://docs.moodle.org/dev/API で定義されている必要があります)。この名前空間のクラスは、APIを実装または使用する必要があります。
または
- コンポーネント内の他のクラスをさらに整理したい場合は、"\local" を使用します(ほとんどのコンポーネントでは、ルートレベル1の名前空間のみにすべての独自のクラスを持つことで十分であることに注意してください)。
レベル3のルール
レベル3名前空間として使用できるものを制限するルールはありません。このため、プラグインやアドオンがレベル3の名前空間として使用することができます。 の名前空間は、他のプラグインやapiと衝突する可能性がなく、現在も、そしてこれからも、ずっと続くでしょう。
**/testsディレクトリ内の名前空間
(MDLSITE-4800で合意)
- ユニットテストでは、名前空間の利用を強く推奨します。
- 名前空間を使用する場合、テストクラスの名前空間は、テスト対象のコードの名前空間と一致させる必要があります。
- テストクラスは、テスト対象のクラスから名前をとり、`_test.php` を接尾辞としてつける必要があります。
- テストクラスの第 1 レベルの名前空間は、それが属するコンポーネントと一致 しなければなりません 。
- サブの名前空間は許可されますが、上記のレベル2および3の一般的な名前空間のルールに厳密に従う必要があります。常に、対象となるコードの名前空間と可能な限り一致させるようにします。
- サブディレクトリの構造は、名前空間の構造と一致しなければなりませんが、代わりに `tests` ディレクトリに配置されます。
注意:テストの自動読み込みはサポートされていません(ただし、テストから標準クラスを自動読み込みすることは可能です)。
例
良い例:
// 入れ子になった名前空間を使用しない場合のプラグイン固有の名前空間(一般的な)
// 名前空間の場所:mod/breakfast/classes/
// テストの場所:mod/breakfast/tests/
namespace mod_breakfast;
// 入れ子になった名前空間を使用する場合のプラグイン固有の名前空間
// 名前空間の場所:mod/breakfast/classes/local/
// テストの場所:mod/breakfast/tests/local/
namespace mod_breakfast\local;
// さらに組織化された入れ子になった名前空間を使用する場合のプラグイン固有の名前空間
// 名前空間の場所:mod/breakfast/classes/local/utils/
// テストの場所:mod/breakfast/tests/local/utils/
namespace mod_breakfast\local\utils;
// コアAPIを実装するためのプラグインの名前空間
// 名前空間の場所:mod/breakfast/classes/event/
// テストの場所:mod/breakfast/tests/event/
namespace mod_breakfast\event;
悪い例:
namespace mymodule; // レベル1のルールに違反 - 無効なコンポーネント名
namespace mod_breakfast\myutilities; // レベル2のルールに違反 - 無効なコアAPI名
namespace mod_forum\test; // 技術的には正しいですが("test" は有効なAPIです) - これは許容できません
// なぜなら、テストの名前空間はコードの名前空間と一致する必要があるためです
// 通常、コンポーネントに "test" という名前のものは存在しないため、これはカバーされるべきではありません
// レベル2がカバーされた後にのみ、それを使用することができます
文字列
現在のPHPバージョンでは、文字列のパフォーマンスは問題にならないため、文字列の主な基準は可読性です。
シングルクォーテーション
文字列がリテラルである場合や、ダブルクォーテーションが多く含まれる場合(HTMLなど)、常にシングルクォーテーションを使用してください。
$a = 'Example string';
echo '<span class="'.s($class).'"></span>';
$html = '<a href="http://something" title="something">Link</a>';
ダブルクォーテーション
これらは、Moodleではあまり役に立ちません。プレーンな変数や多くのシングルクォーテーションを含める必要がある場合、ダブルクォーテーションを使用してください。
echo "<span>$string</span>";
$statement = "You aren't serious!";
複雑なSQLクエリは、必ずダブルクォーテーションで囲む必要があります。
$sql = "SELECT e.*, ue.userid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = 'self' AND e.customint2 > 0)
JOIN {user} u ON u.id = ue.userid
WHERE :now - u.lastaccess > e.customint2";
変数の置換
変数の置換には、次のいずれかの形式を使用できます:
$greeting = "Hello $name, welcome back!";
$greeting = "Hello {$name}, welcome back!";
文字列の結合
文字列は "." 演算子を使用して結合する必要があります。
$longstring = $several . $short . 'strings';
行が長い場合は、可読性を向上させるために、ステートメントを複数の行に分割してください。この場合、各行の最後に "ドット" を置いてください。
$string = 'This is a very long and stupid string because ' . $editorname .
" couldn't think of a better example at the time.";
演算子 "." は、上記の例に示されるように、どちらの側にもスペースを入れずに使用することもできます。開発者が好む方法を使用してください。
言語文字列
大文字と小文字
言語文字列は "Always look like this(このように常に見える)"、"Never Like This Example(このように決して見えない)" のように書くべきです。
大文字は、次の場合にのみ使用する必要があります:
- 文章の先頭で始まる場合、または
- Moodle のような固有名詞で始まる場合。
構造
文字列は UI の連結を想定して設計されていないため、他の言語で問題が発生する可能性があります。各文字列は単独で機能する必要があります。
悪い例:
$string['overduehandling'] = 'When time expires'; $string['overduehandlingautosubmit'] = 'the attempt is submitted automatically'; $string['overduehandlinggraceperiod'] = 'there is a grace period in which to submit the attempt, but not answer more questions'; $string['overduehandlingautoabandon'] = 'that is it. The attempt must be submitted before time expires, or it is not counted';
良い例:
$string['overduehandling'] = 'Time expiry behaviour'; $string['overduehandlingautosubmit'] = 'Unfinished attempts will be auto-submitted immediately'; $string['overduehandlinggraceperiod'] = 'Unfinished attempts have a short grace period to be submitted for grading'; $string['overduehandlingautoabandon'] = 'Unfinished attempts are immediately discarded';
空白
言語文字列には、前後にスペースを含めたり、依存したりしないでください。そのような文字列は、AMOS翻訳ツールで翻訳することが容易ではありません。
配列
数値インデックス付きの配列
配列を宣言する際には、可読性を向上させるため、各カンマ区切りの後にスペースを追加する必要があります。
$myarray = [1, 2, 3, 'Stuff', 'Here'];
複数行のインデックス配列も問題ありませんが、次の各行も前述のように4つのスペースのインデントで埋め込みます:
$myarray = [1, 2, 3, 'Stuff', 'Here',
$a, $b, $c, 56.44, $d, 500];
上記の例は以下のように書くこともできます:
(後で項目のリストを拡張するためのクリーンな diff を作成するため、最後の行にカンマがあることに注意してください)
$myarray = [
1, 2, 3, 'Stuff', 'Here',
$a, $b, $c, 56.44, $d, 500,
];
いずれにしても、1行の要素数に関係なく、括弧と改行のバランスをとる必要があります。
連想配列
可読性が向上する場合は、複数行に分割して使用してください。例:
$myarray = [
'firstkey' => 'firstvalue',
'secondkey' => 'secondvalue',
];
クラス
クラス宣言
- クラスはMoodleの命名規則に従って命名する必要があります。
- クラスは、自動読み込みや名前空間の利点を得るために、それぞれの "component/classes" ディレクトリの下に置かなければなりません。そこから先は、そんな贅沢なことはできません。
- 各PHPファイルには、クラス(またはインターフェース、トレイトなど)が1つだけ含まれます。ただし、複数のアーティファクトファイルが許可されていた古いAPIの一部である場合を除きます。
- ブレースは必ずクラス名の横の行に書いてください。
- すべてのクラスは、PHPDocumentor の標準に準拠したドキュメントブロックを持つ必要があります。
- クラス内のすべてのコードは、4つのスペースでインデントされなければなりません。
- クラスファイルに追加のコード("サイドエフェクト")を配置することは、自動読み込みで提供されないアーティファクト("classes" ディレクトリ以外から取得した古いクラスやライブラリで、Moodleのブートストラップによって読み込まれなかったもの)を必要とする場合にのみ許可されます。そのような場合には、MOODLE_INTERNALチェックの使用が必要になります。
- 一例:
/**
* Short description for class.
*
* Long description for class (if any)...
*
* @package mod_mymodule
* @copyright 2008 Kim Bloggs
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sample_class {
// クラスの全てのコンテンツは
// スペース4つ分インデントされる必要があります。
}
クラス PHPDoc スタイルは、このドキュメントの ドキュメントおよびコメント/クラス セクションでより詳しく定義されていることに注意してください。
クラスのメンバ変数
メンバ変数は、Moodleの変数命名規則に従って命名する必要があります。
クラスで宣言された変数は、クラスの先頭で、メソッドの宣言の上に記載しなければなりません。
var構成は許可されていません。メンバ変数は常に、private, protected, public のいずれかの修飾子を使用して可視性を宣言します。メンバ変数を public として直接アクセスすることは許可されていますが、アクセサメソッド(set/get)を優先することが推奨されています。
関数とメソッド
関数とメソッドの宣言
関数は、Moodleの関数命名規則に従って名前を付ける必要があります。
クラス内のメソッドは、常に private、protected、または public の修飾子を使用して可視性を宣言する必要があります。
クラスと同様に、波括弧は常に関数名と同じ行に書く必要があります。
引数の開き括弧と関数名の間にスペースを入れてはいけません。
返り値は、括弧で囲まれていてはいけません。これは可読性を損なうだけでなく、後で参照による返り値に変更された場合にコードが壊れる可能性があります。
返り値は1つのデータ型でなければなりません。複数の返り値型を持つことは推奨されません。
/**
* ここにドキュメンテーションブロックを記述します
*/
class sample_class {
/**
* ここにドキュメンテーションブロックを記述します
*/
public function sample_function() {
// 関数の中身はすべて
// スペース4つ分インデントされる必要があります。
return true;
}
}
関数とメソッドの使用
関数の引数は、コンマ区切りの後に1つのスペースを開けるようにしてください。
three_arguments(1, 2, 3);
マジックメソッド
マジックメソッドは強く非推奨であり、使用する際には正当性が必要です。注意: 怠惰さは正当な理由とはなりません。
(背景についてはMDL-52634を参照してください)
制御文
一般的に、行間などに十分なスペースを使って、明瞭さを追加するようにしてください。
If/else文
中括弧の制御文の前後にはスペースを入れ、中括弧内の演算子はスペースで区切ります。 論理的なグループ化を改善する場合は、内部の括弧を使用してください。
4つのスペースでインデントしてください。
elseif は使用しないでください!
ブロックが1行であっても(PHPが必要としなくても)、常に中括弧を使用してください。ブロックの開始中括弧は、対応するステートメントまたは宣言と同じ行に配置されます。
if ($x == $y) {
$a = $b;
} else if ($x == $z) {
$a = $c;
} else {
$a = $d;
}
Switch文
中括弧の制御文の前後にはスペースを入れ、中括弧内の演算子はスペースで区切ります。論理的なグループ化を改善する場合は、内部の括弧を使用してください。
常に4つのスペースでインデントしてください。各case文の下のコンテンツはさらに4つのスペースでインデントする必要があります。
switch ($something) {
case 1:
break;
case 2:
break;
default:
break;
}
Foreach文
前述のように、次のようにスペースを使用します:
foreach ($objects as $key => $thing) {
process($thing);
}
三項演算子
三項演算子は、短く, 理解しやすい文に限定して使用することができます。文が一文で理解できない場合は、if文を代わりに使用してください。
演算子の周りに空白を使用して、操作がどこで実行されているかを明確にする必要があります。
良い例:
$username = isset($user->username) ? $user->username : ''; **
$users = is_array($users) ? $users : [$users];
悪い例:
$toload = (empty($CFG->navshowallcourses))?self::LOAD_ROOT_CATEGORIES:self::LOAD_ALL_CATEGORIES;
$coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextrasum') ? 'aggregationcoefextrasum' : 'aggregationcoef';
** 注意:PHP 7.0以降、多くの "isset()" 三項演算子は、新しい省略記法 null coalescing operator を使用するように変更できます。つまり、上記は以下と同じです。
$username = $user->username ?? '';
Require / include
ブラウザ経由でアクセスされる各ファイルは、まずメインのconfig.phpファイルをインクルードすることから始める必要があります。
require(__DIR__ . '/../../config.php');
その他のinclude/requireは、__DIR__で始まるパスまたは$CFG->dirrootまたは$CFG->libdirで始まる絶対パスを使用する必要があります。"../" で始まる相対的なインクルードは、PHPでは時々奇妙な動作をするため、使用しないでください。CLIスクリプトでは、"../" で始まる相対的なconfig.phpパスを使用しないでください。
一般的な使用において、ライブラリファイルについては、require_onceを使用する必要があります(これは常に上記のように'require'を使用する必要があるconfig.phpとは異なります)。例:
require_once(__DIR__ . '/locallib.php');
require_once($CFG->libdir . '/filelib.php');
インクルードは、通常はファイルの先頭または必要な場合にのみ、関数/メソッドの内部で行うべきです。ファイルの途中でinclude/requireを使用すると、グローバルスコープでのセキュリティの監査が非常に困難になります。
他のすべてのスクリプトにおいて、インポートされたサードパーティのライブラリおよび side-effects*(つまり、単一のクラス定義、インターフェイス、またはトレイト)のないファイルを除き、誤って設定された本番サーバでエラーメッセージを公開する可能性がある直接実行を防止するために、以下のコードをファイルの先頭で使用する必要があります。
defined('MOODLE_INTERNAL') || die();
*side-effects: a) 名前空間と使用文 b) 名前空間定数 c) strict_types宣言(宣言全般)以外のグローバルスコープコード。
ファイル内に副作用があるかどうかの存在または不在は、コードレベルで上記のように説明されるようにのみ影響します。特に言及されない限り、コーディングスタイルの他の部分では考慮すべきではありません。
ドキュメンテーションとコメント
コードのドキュメンテーションは、関数や変数の目的やコードのフローを説明します。実用的な場合には、必ず使用してください。
PHPDoc
Moodleは、ファイル、クラス、および関数を文書化するために、できるだけ「標準的な」PHPDocフォーマットに従います。これにより、Moodle開発者がNetbeansやEclipseのようなIDEを適切に使用できるようになり、Webドキュメンテーションを自動的に生成することもできます。
PHPDocには、異なる場所(ファイル、クラス、関数)で使用できるいくつかのタグがあります。Moodleでは、それらを使用するためのいくつかの特別なルールがあり、それに従う必要があります。
型
以下のタグ (@param, @return...) のいくつかは、有効なPHPの型とその説明を指定する必要があります。以下のものが許可されています:
- PHPのプリミティブ型:int、bool、stringなど
- PHPの複雑な型:array、stdClass (Array、objectではない)
- PHPのクラス:完全な名前または相対的な(現在の名前空間に対する)クラス名
- true、false、null (常に小文字)
- static: 子クラス/呼び出し側のクラスの新しいインスタンスを返すメソッドに使用します。
- self: 親クラス/呼び出されたクラスの新しいインスタンスを返すメソッドに使用します。
- $this: クラスの現在のインスタンスを返すメソッドに使用します。
- void: 明示的に空の "return" ステートメントを持つメソッドに使用します。
また、これらの型を使用する際には、いくつかの基本的なルールがあります:
- 短い型名を使用します (booleanではなくbool、integerではなくintなど)。
- 特定の型の配列として表現される場合、より簡単で情報量の少ない "array" の代わりにtype[]として文書化することを強くお勧めします (例:int[]またはstdClass[]など)。
- 複数の異なる型が可能な場合、縦棒 (パイプ) で区切る必要があります (例:@return int|falseなど)。
- すべてのプリミティブおよびキーワードは小文字で記述します。複雑な型とクラスの場合は、元のものと同じ大文字と小文字を使用します。
タグ
@copyright
これらには、オリジナルファイルの作成者である年と著作権保有者が含まれます。既存のファイルではこれらを変更しないでください!
@copyright 2008 Kim Bloggs
@license
これらは GPL v3+ を使用し、以下の形式を使用する必要があります:
@license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 以降
@param
変数名の後ろにハイフンや何か特別な文字を入れないでください。スペースだけを使用してください。
@param type $name 説明。
@return
関数に戻り値がある場合は、@returnタグは必須ですが、戻り値がない場合は省略できます。
説明部分はオプションです。関数がシンプルで戻り値について説明されている場合は、省略することができます。
@return type 説明。
@var
@varタグは、クラスのプロパティをドキュメント化するために使用されます。
@var type 説明。
例外的に、利用可能なtypesのいずれも返された値を定義しない場合、メソッドの本文内で型ヒントを提供するインライン@var phpdocsを返された型に許可されています。濫用しないでください!
@uses
関数がdieまたはexitを使用する場合は、このタグをドックブロックに追加して、開発者がこの関数がページを終了できることを知るのに役立ててください。
@uses exit
@access
アクセスは、要素のアクセス制御を指定するために使用できます。
- メソッド定義が既にアクセス制御を指定していない場合にのみ使用する必要があります。
- 関数の場合、publicアクセスを指定することは冗長であるため、避けるべきです。
@access private
@package
@packageタグは、正しいFrankenstyleコンポーネント名でphpファイルにラベルを付けるために常に使用する必要があります。詳細なルールはそのページで説明されていますが、要約すると次のとおりです。
- ファイルが任意のコンポーネントプラグインの一部である場合は、プラグインコンポーネント名(例:mod_quiz または gradereport_xls )を使用します。
- ファイルがコアサブシステムの一部である場合、get_core_subsystems()で定義された名前がxxxxであることになります(たとえば、core_enrol または core_group )。
- サブシステムの一部でないコアの選択された数少ないファイル(lib/moodlelib.phpなど)の場合は、単に core というパッケージとして存在します。
- 各ファイルは1つのパッケージのみに属することができます。
(@subpackageにはまったく標準がありません。@package内で好きなように使用できます。)
@package gradereport_xls
@category
私たちは、@categoryを使用して、コアAPIの一部であるパブリッククラス、関数、またはファイル、あるいはコアAPIの良い例の実装を示すためにのみ使用します。値は、コアAPIページのいずれかの値である必要があります。
@category preferences
@since
Moodleのコアライブラリに新しいクラスや関数を追加する場合(または既存のクラスに新しいメソッドを追加する場合)、@sinceタグを使用して、その追加されたMoodleのバージョンを文書化します。例:
@since Moodle 2.1
@see
関連する別の要素(include、class、function、define、method、variable)をユーザに参照させたい場合は、URLではなく@seeタグを使用することができます。
@see some_other_function()
このタグは、phpdocコメント内でもインラインで使用できます。
/** * この関数は{@see get_string()}を使用して通貨名を取得します... * .....
@link
外部のURLにユーザを参照させたい場合は、関連要素ではなく@linkを使用します。
@link https://docs.moodle.org/dev/Core_APIs
このタグは、phpdocコメント内でもインラインで使用できます。
/** * 下記の実装の詳細については、{@link https://docs.moodle.org/dev/Core_APIs} にアクセスし、読んでください... * .....
@deprecated (および@todo)
古いAPIを廃止する場合は、@deprecatedタグを使用して、どのバージョンのMoodleで廃止されたかを文書化し、できる限り@todoと@seeを追加してください。関連するMDLの問題を必ず記載してください。例えば:
/**
* ...
* @deprecated since Moodle 2.0 MDL-12345 - please do not use this function any more.
* @todo MDL-22334 This will be deleted in Moodle 2.2.
* @see class_name::new_function()
*/
開発者がコードを更新する必要がある場合は、デバッグメッセージを繰り返して表示するために、debugging('...', DEBUG_DEVELOPER);呼び出しを追加することも検討してください。古い関数を全くサポートできなくなった場合は、coding_exceptionをスローする必要がある場合もあります。各種オプションの例については、lib/deprecatedlib.phpを参照してください。
@throws
このタグは有効であり、オプションで使用することができます。メソッドまたは関数が例外をスローすることを示すために使用されます。これにより、開発者がそのような関数からの例外を処理する必要があることを知ることができます。
その他の特定のタグ
グローバルではなく、特定の文脈でのみ許可されているタグがあります。より具体的には、以下のようになります:
- @Given、@When、@Thenは、behatステップ定義内でのみ使用できます。
- @covers、@coversDefaultClass、@coversNothing、@usesは、ユニットテスト内でカバレッジをより細かく制御するために使用します。
- @dataProviderと@testWithは、ユニットテスト内で、例と期待値を提供するために使用されます。
- @dependsは、テスト間の依存関係を表現するために使用されます。各プロデューサが返したデータがコンシューマに渡されます。詳細については、@depends examples を参照してください。
- @groupは、PHPUnit MoodleDocsのガイドラインに従い、ユニットテストを簡単にグループ化するために使用されます。
- @requiresは、ユニットテストの要件を指定し、満たされない場合はスキップします。詳細については、@requires usages を参照してください。
- @runTestsInSeparateProcessesと@runInSeparateProcessは、個々のテストまたはテストケースを独立して実行するために使用されます。厳密に必要な場合にのみ使用してください。
ファイル
PHPコードを含むすべてのファイルは、PHPオープンタグの後に空行を挿入せず、トップに完全なGPL著作権声明を含める必要があります。その下には、以下の情報を含む別個のドックブロックが必要です:
- ファイルの簡単な一行の説明
- ファイルの詳細な説明
- @packageタグ (必須)
- @categoryタグ (ファイル内のすべてがコアAPIの関連である場合にのみ必要)
- @copyright (必須)
- @license (必須)
1つのアーティファクトだけを含むファイルの場合、そのアーティファクト(クラス、インターフェース、トレイトなど)が文書化されている限り、ファイルのphpdocブロックはオプションです。この場合については、以下の "クラス" のセクションを読んでください。
<?php
// このファイルはMoodleの一部です - https://moodle.org/
//
// Moodleはフリーソフトウェアであり、あなたはそれを再配布したり、
// 改変することができます。
// これはGNU General Public Licenseに従って公開されています。
// ライセンスのバージョンは、バージョン3、あるいは
// (あなたの選択により)それ以降のバージョンを使用することができます。
//
// Moodleは、役に立つことを願って配布されていますが、
// すべての保証を含めて、明示的にも黙示的にも何の保証もありません。
// 詳細については、GNU General Public Licenseを参照してください。
//
// あなたは、Moodleと共にGNU General Public Licenseのコピーを受け取るはずです。
// もし受け取っていなければ、<https://www.gnu.org/licenses/>を参照してください。
/**
* これはファイルの簡単な一行の説明です。
*
* あなたはファイルのかなり長い説明も持つことができ、
* 複数の行にまたがることもできます。
*
* @package mod_mymodule
* @category backup
* @copyright 2008 Kim Bloggs
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3またはそれ以降
*/
クラス
すべてのクラスは以下のような完全なドックブロックを持つ必要があります。
/**
* クラスの短い説明。
*
* クラスの長い説明 (ある場合)。
*
* @package mod_mymodule
* @category backup
* @copyright 2008 Kim Bloggs
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 またはそれ以降のバージョン
*/
class policy_issue {
1つのアーティファクト (クラス、インターフェース、トレイトなど) のみを含むファイルについて、特に classes ディレクトリ内のすべてのファイル、および他の場所にある条件を満たす任意のファイルについては、クラスの phpdoc ブロックだけで十分です。ファイルの phpdoc ブロックは、クラスに優先度を与えるため、すべての効果においてオプションと見なされます。
上記の例に示されるように、@package、@copyright、@license タグ(およびオプションの @category タグ)は、常にファイルに存在する必要があります(どのドックブロックにあっても、すべて一緒に)。
プロパティ
すべてのプロパティには、次の最小情報を持つドックブロックが必要です。
class example {
/** @var string この変数は何かを行います */
protected $something;
}
または
class example {
/**
* この変数は何かを行い、複数行にまたがる非常に長い説明があります
* @var string
*/
protected $something;
}
DocBlockテンプレートを使用しないでください。代わりに、次の例のように、すべてのプロパティを明示的に文書化してください。
class zebra {
/** @var int 白いストライプの数 */
protected $whitestripes = 0;
/** @var int 黒いストライプの数 */
protected $blackstripes = 0;
/** @var int 赤いストライプの数 */
protected $redstripes = 0;
}
定数
クラス定数は、次の方法で文書化する必要があります:
class sam {
/**
* Samが良い気分のときに使用されます。
*/
const MOOD_GOOD = 0;
}
関数
すべての関数とメソッドには、次のように完全なドックブロックが必要です。
/**
* 説明は最初に記述し、この例のようにアスタリスクを正確に並べます。
* 別の関数を参照する場合は、以下のように@seeを使用してください。
* MoodleのWeb上のドキュメントへのリンクが役立つ場合は、以下のように@linkを使用するか、
* またはインラインで{@link https://docs.moodle.org/dev/something}のように使用できます。
* その後、各パラメータと戻り値について次のように説明を追加します。
*
* @see clean_param()
* @param int $postid PHPのタイプに続いて変数名を記述します
* @param array $scale PHPのタイプに続いて変数名を記述します
* @param array $ratings PHPのタイプに続いて変数名を記述します
* @return bool 成功または失敗を示すステータス
*/
@paramおよび/または@return行から明らかであると思われる場合でも、説明を含める必要があります。
親メソッドの意味を変更せず、同じ引数/戻り値を維持するオーバーライドされたメソッドについては、この場合はコメントを完全に省略する必要があります。@inheritdocまたは@seeタグの使用は、完全なドックブロックの代わりに明示的に禁止されています。
定義
すべての定義は、以下の方法でドキュメント化する必要があります:
/**
* PARAM_INT - 整数のみ、数字のみを想定する場合に使用します。
*/
define('PARAM_INT', 'int');
/**
PARAM_ALPHANUM - 数字と文字のみを想定します。
*/
define('PARAM_ALPHANUM', 'alphanum');
インラインコメント
インラインコメントは、"// "(2つのスラッシュ+空白)スタイルを使用する必要があります。そのコメントがコードに収まり、整然と並ぶように配置します。コメントの最初の行は大文字で始まり(または数字、または '...')、適切な句読点文字で終わる必要があります。許可される最後の文字は、'.'、'?'、'!'のいずれかです。
function forum_get_ratings_mean($postid, $scale, $ratings = null) {
if (!$ratings) {
$ratings = []; // 空の配列を初期化します。
$rates = $DB->get_records('forum_ratings', ['post' => $postid)];
// ... そして、それぞれの評価を処理します。
foreach ($rates as $rate) {
do_something_with($rate);
}
// 片付けが必要か?
if (!empty($rates))
ここで42の別の処理が行われます!
finsh_up();
}
良い例:
// このコードの説明をするコメント。
悪い例:
/* このコードの説明をするコメント。*/
# このコードの説明をするコメント。
// このコードの説明をするコメント(大文字と句読点なし)。
もしコメントがMDLの問題に関連している場合は、適切なMDL-12345をコメントに含めてください。これにより、決定や議論を追跡することがより簡単になります。
TODOを使用する
特に、後で取り組む必要のある問題がまだそのコードに存在することを知っている場合には、TODOとMDLコードを使用してそれをマークすることが重要です。例えば:
// TODO MDL-12345 これは機能するが、ややハック的であり、将来的に改訂する必要がある。
ほとんど完了している大きなタスクがあり、いくつかのTODOが残っている場合は、大きなタスクを完了したとマークしたい場合は、各TODOのために新しいトラッカータスクを作成し、TODOのコメントを新しい問題番号に指し示すように変更する必要があります。
"TODO チェック" を行う便利なレポートツールがあります。管理者専用で、ウェブ経由で lib/tests/other/todochecker.php で利用できます。
最後に、あなたのTODO(また、@todosも、非推奨プロセスの一部でない限り、それらは別に扱われます)で使われているMDL-l2345を "Review TODOs Epic" に加えることを忘れないでください : MDL-47779 (問題を見るにはログインが必要です)
CVS キーワード
Moodle 2.0 からは、$Id$ のような CVS キーワードの使用を完全に停止しています。
例外処理
エラーの報告には、特にライブラリコードにおいて、例外を使用してください。
例外を投げることは、print_error() を呼び出すこととほぼ同じ効果がありますが、より柔軟性があります。例えば、呼び出し元は例外をキャッチして、何らかの方法で処理することができます。また、ユニットテストを書くこともより簡単になります。
2021年以降、print_error() を廃止し、代わりに moodle_exception() をスローすることが合意されたため、注意してください。
キャッチされていない例外は、問題をユーザに報告するために適切な print_error の呼び出しをトリガーします。"エラーコード" として表される例外は、最終的なユーザに表示するために翻訳されます。
通常のコードフローに例外を乱用しないでください。例外は、異常な状況でのみ使用する必要があります。
例外クラス
カスタム例外クラスのセットを持っています。ベースクラスはmoodle_exceptionです。new moodle_exception(...)に渡す引数は、print_errorに渡す引数と非常に似ていることに気づくでしょう。特定の種類のエラーに対してより具体的なサブクラスがあります。
例外タイプの完全なリストを取得するには、 'class +\w+_exception +extends'という正規表現を検索するか、あなたのIDEにmoodle_exceptionのすべてのサブクラスをリストアップするように依頼してください。
適切な場合は、自分のコードで使用するためにmoodle_exceptionの新しいサブクラスを作成する必要があります。
いくつかの注目すべき例外タイプ:
- moodle_exception
- Moodleの例外の基本クラス。より特定のタイプが適切でない場合に使用します。
- coding_exception
- 開発者のミスが原因と思われる場合にスローされます。プラグインとやり取りするコアコードによって頻繁にスローされます。このタイプの例外をスローする場合は、エラーメッセージがプラグインの作者に役立つようにし、彼らが自分のコードを修正する方法を知ることができるようにしてください。
- dml_exception (およびサブクラス)
- データベースクエリが失敗したときにスローされます。
- file_exception
- File APIによってスローされます。
危険な関数や構造体
PHPには、深刻なセキュリティ問題の原因となることが非常に多いとされている、問題のある機能が複数含まれています。
- eval() 関数を使用しないでください。ただし、言語パックに関しては(将来的に解決されることを前提に)例外です。
- preg_replace() 関数を /e 修飾子とともに使用しないでください。PHPの予期しない実行を防止するために、コールバックを使用してください。
- バッククォートを使用してシェルコマンドを実行しないでください。
- goto 文、演算子、またはラベルを使用しないでください。代わりに他のプログラミング技法を使用して実行フローを制御してください。
コーディングスタイルの修正についての方針
このコーディングスタイルガイドが定義され、合意される前に、多くのコードがすでに書かれていました。明らかに、そのようなコードはまったくコーディングスタイルに従っていません。新しいコードについては 従うことを強制します が、以前のコードの状態については過剰に心配していません。
いずれの場合でも、(進行中であり、重要でない) 移行を正規化するために、方針問題 (MDL-43233) が作成され、合意が得られました。そして、コーディングスタイルのみの変更に適用するルールは以下の通りです:
- 実際の問題内で関連するコーディングスタイルの変更 (同じ行、メソッド/関数内の変数、隣接するコメントなど) は許可されます。
- 実際の問題内で関連しないコーディングスタイルの変更(他のメソッド、ブロックのコード、コメントなど)は、マスターにのみ、別のコミットで許可されます。
- コーディングスタイルのみの問題は、各サイクルの最初の2か月間に限り、マスターにのみ受け入れられます。
Gitのコミット
クリアで分かりやすいコミットを作成することは、オープンソースのコード作成の重要な側面であり、コミット履歴は開発者間のコミュニケーションの重要な部分です。適切なコミットを作成するために時間をかけ、gitのツールを使用することが重要です。
Gitのコミットは以下のようにする必要があります:
- コードが完璧に書かれた初回のような、完全で整理されたバージョンの履歴を表すこと。
- 変更に関連するMDL-xxxxの問題番号を含めること。
- 適切な場合にはCODE AREAを含めること。(Code areaとは、この変更が影響するMoodleの領域の短い名前です。コンポーネント名であっても構いませんが、そうである必要はありません。ここでの対象はコンピュータではなく人間であることに注意してください。コンポーネント名の省略形がより読みやすくて識別可能である場合は、そちらを使用してください。)
- 以下の形式でフォーマットすること:
MDL-xxxx CODE AREA: 短い要約(72文字の制限) 2行目には空白行を挿入し、必要に応じて無制限の詳細な説明を続けます。このセクションには、変更の動機や以前の動作との対比が含まれる場合があります。
Gitのコミットには、以下のようなものは含めないでください:
- 統合前に見つかったバグの修正内容
- 1つの問題に対して同じコード行の多数の別々の修正を含める
- 論理的に1つのセットとして扱うべき変更を、恣意的に分割する
詳細については、コミットチートシートを参照してください。
クレジット
このドキュメントは以下のソースから引用されています:
- オリジナルのコーディングガイドラインページ
- Zendのガイドライン
- 全てのMoodleコア開発者からのフィードバック