# Moodle程序编写准则

任何合作的项目都需要一致性和稳定性才能保持它的强壮。

编写这些准则的目的是为所有的Moodle代码提供一个努力的目标。有一些比较老的已经存在的代码在极少的方面尚未达标，但它们最终将会被修正。所有新的代码都必须尽可能地遵守这些准则。

## 一般规定

1. 所有代码文件应当使用 .php 作为扩展名。
2. 所有模板文件应当使用 .html 作为扩展名。
3. 所有文本文件应当使用Unix风格的文本格式(多数的文本编辑器都有这个选项)。
4. 所有php标记都必须是“完整”标记，譬如<?php ?> ... 而不是如<? ?>的“短”标记。
5. 所有已经存在的版权声明应当被保留。如果有必要，你可以加入自己的。
6. 每个文件都应当包含主config.php文件。
7. 每个文件都应当检查用户的身份是否正确，可以使用函数require_login()和isadmin()、isteacher()、iscreator()或者isstudent()。
8. 所有访问数据库的操作都应当使用lib/datalib.php中的函数――这样可以兼容更多的数据库服务器。所有的事情都应当是可以用这些函数来完成的，如果遇到必须要写SQL代码的情况，请记住这些代码应当是跨平台的，且仅仅对你代码中的特定函数(通常在一个lib.php文件中)有效，且代码中用注释进行明确说明。
9. 不要建立和使用标准全局变量$CFG、$SESSION、$THEME和$USER之外的全局变量。
10. 所有变量都应当被初始化或者至少在使用前用isset()或empty()等函数进行检测。
11. 所有字符串都应当可翻译――在"lang/en"目录中创建新的文本文件，字符串应当使用简洁的英文小写名称，并通过函数get_string()或print_string()来取得。
12. 所有帮助文件应当可翻译――在"en/help"目录中创建文本文件并且通过helpbutton()函数来调用它们。

    如果需要上传一个帮助文件：

    - 对于小的修改，旧的翻译文件仍然可以继续使用时，可以直接进行修改，但你应当通知translation@moodle.org
    - 对于大的修改，应当创建新的文件，新文件的文件名是在原文件名的末尾添加一个数字，并在以后逐渐增加(如filename2.html)，这样翻译人员就可以方便地知道文件有了一个新的版本。很显然，新的代码和帮助索引文件都必须修改以指向新版本的文件。
13. 从浏览器发来的信息(以GET或POST形式发送)都应用了magic_quotes(无论PHP的设置如何)，因此直接将它们插入到数据库中是安全的。所有其它的原始数据(来自文件或数据库的)都必须在插入数据库前使用addslashes()进行预处理。
14. 重要的：Moodle中所有的文本，特别是用户提供的文本，都必须使用format_text()函数来输出。这样就可以确保文本已经正确地过滤。

## 编码风格

我知道，如果你已经习惯了一种编码风格而我却让你改变它是有一点讨厌的，但比较而言，这比日后所有人都需要去搞清混合风格的Moodle代码要好一些。对于人们使用的任何编码风格都有很多支持和反对的意见，但现在正在使用的风格已经存在了，因此请坚持下去。

1. 缩进应当是4个连续的空格。绝对不要使用制表符。
2. 变量名应当是容易理解、有含义的小写英文单词。如果确实需要两个或以上的单词，请把它们连在一起，但要保持名称尽可能短。对于数组对象，请使用复数名称。

   好的: $quiz
   好的: $errorstring
   好的: $assignments (用于数组)
   好的: $i (仅用于小型循环)
   坏的: $Quiz
   坏的: $aReallyLongVariableNameWithoutAGoodReason
   坏的: $error_string

3. 常量应当总是大写的，并总是以模块的名称作为前缀。单词之间应当用下划线分隔。

   define("FORUM_MODE_FLATOLDEST", 1);

4. 函数名称应当是简单的英文小写单词，且总是以模块名作为前缀以防止模块之间的冲突。单词之间以下划线分隔。变量如果可能应当总有合理的缺省值。注意在函数名和其后的括号之间没有空格。

   function forum_set_display_mode($mode=0) {
   global $USER, $CFG;
   if ($mode) {
   $USER->mode = $mode;
   } else if (empty($USER->mode)) {
   $USER->mode = $CFG->forum_displaymode;
   }
   }

5. 语句块必须总是使用大括号(即便是只有一行)。Moodle使用如下风格:

   if ($quiz->attempts) {
   if ($numattempts > $quiz->attempts) {
   error($strtoomanyattempts, "view.php?id=$cm->id");
   }
   }

6. 字符串应当尽可能用单引号定义以提高速度。

   $var = 'some text without any variables';
   $var = "with special characters like a new line n";
   $var = 'a very, very long string with a '.$single.' variable in it';
   $var = "some $text with $many variables $within it";

7. 实用的注释应当尽可能填写，用以解释代码流程和函数与变量的功能。
   - 每个函数和类都应该使用流行的phpDoc格式编写，以便自动生成代码文档。
   - 内嵌注释应使用 // 风格，并且整齐布局，使其能融入代码中并和代码对齐。

   /**
   * The description should be first, with asterisks laid out exactly
   * like this example. If you want to refer to a another function,
   * do it like this: {@link clean_param()}. Then, add descriptions
   * for each parameter as follows.
   *
   * @param int $postid The PHP type is followed by the variable name
   * @param array $scale The PHP type is followed by the variable name
   * @param array $ratings The PHP type is followed by the variable name
   * @return mixed
   */
   function forum_get_ratings_mean($postid, $scale, $ratings=NULL) {
   if (!$ratings) {
   $ratings = array(); // Initialize the empty array
   if ($rates = get_records("forum_ratings", "post", $postid)) {
   // Process each rating in turn
   foreach ($rates as $rate) {
   ....etc

8. 换行可以被大方地使用——把东西分散开看起来会比较清楚。一般情况下，在花括号和普通命令之间应当有一个换行符，但在花括号和变量或函数之间可以没有换行符:

   foreach ($objects as $key => $thing) {
   process($thing);
   }
   if ($x == $y) {
   $a = $b;
   } else if ($x == $z) {
   $a = $c;
   } else {
   $a = $d;
   }

## 数据库结构

1. 每个表格都必须有一个自增的id字段(INT10)作为主键。
2. 包含着模块中数据实例的主表格必须和模块同名(譬如widget)，并且至少包含如下字段:
   - id - 如上一条所述
   - course - 每个实例所属的课程id
   - name - 每个实例的完整名称
3. 与模块相关的其它表格的命名规则是：如果它包含的信息是关于“things”的，则它的名字应当是widget_things(注意采用复数形式)。
4. 字段名称应当简短，与变量名的规则相同。
5. 在可能的情况下，包含着对其它表格(如widget)引用的字段应当命名为widgetid。(注意这是个新约定，有一些老的表格并未遵守)
6. 布尔字段应当使用小整数类型(如INT4)并存储为0或1，这样就可以在需要时扩展它。
7. 多数的表格应当有一个timemodified字段(INT10)，并用PHP的time()函数取得的当前时间戳来更新它。

Moodle帮助文档

Version: $Id$