코딩 지침

MoodleDocs

무들 코딩 지침

어떠한 협동적 프로젝트든 견고하게 오래 지속되기 위해서는 일관성과 안정성이 필요합니다.

여기에서 제공되는 지침은 무들 코드가 추구하는 목적을 달성하기위해 제시하는 것들입니다. 사실 어떤 영역에 있는 기존의 오래된 코드들은 구닥다리지만, 결국 새롭게 수정되어 다시 태어날 것입니다. 모든 새로운 코드들은 가능한한 이러한 표준에 가까와져 궁극적으로는 하나로 융합될 것입니다.

일반적 규칙

  1. 모든 코드의 파일은 .php 확장자를 사용한다.
  2. 모든 템플릿 파일은 .html 확장자를 사용한다.
  3. 모든 문서 파일은 유닉스 문서 유형(대부분의 문서편집기는 이 옵션을 가지고 있다)을 사용한다.
  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) 새 파일를 만들어야하고, 그래야만 번역자들이 쉽게 파일의 새 버전임을 알 수 있게 된다. 새 코드와 도움말 색인 파일은 확실하게 새로운 파일이 나오는 시점에 같이 변경되어야 하기 때문이다.
  1. 브라우저에서 (GET 또는 POST 명령에 의해) 유입되는 자료들은 자동적으로 (PHP의 설정에 관계없이) magic_quotes 로 처리되어 안전하게 바로 데이터베이스에 입력시킬 수 있다. 그 외의(파일 혹은 데이터베이스로부터 오는) 다른 모든 가공되지 않은 자료들은 데이터베이스에 첨가하기 전에 반드시 addslashes()를 통과할 수 있어야 한다.
  2. 중요 : 무들 안의 모든 문서들, 특히 사용자로부터 입력되는 문서는 format_text()함수를 이용하여 출력되어야만 한다. 이렇게 함으로서 문서가 올바르고 검증된 문서로서 확인받을 수 있다.

코딩 스타일

만일 여러분이 다른 것에 익숙하다면, 여러분의 스타일을 바꾼다는 것이 다소 성가신 일이 될 것이라는 것을 알고 있지만, 무들을 개발하는 서로 다른많은 사람이 나중에 서로 다른 스타일 때문에 격을 성가심을 생각해 본다면 뭔가 균형을 잡아야 할 필요가 있을 것이다. 사실 명백히 사람들이 쓰고 있는 좋고 나쁜 스타일들이 있지만, 현재의 무들 코딩 스타일은 존재하고 있으며, 즐겨 이를 엄수할 필요가 있다.

  • 들여쓰기는 스페이스 네개를 연달아 쓴다. 결코 탭을 쓰면 안된다.
  • 변수명은 언제나 읽기 쉬워야 하며, 의미있는 영어 소문자로 쓴다. 부득이 한 단어 이상의 연결된 단어를 써야할 경우, 가능한한 짧게 쓴다. 일련의 대상의 나열은 복수형을 쓴다.

좋음: $quiz
좋음: $errorstring
좋음: $assignments (일련의 대상의 나열)
좋음: $i (단순한 반복의 경우만)

나쁨: $Quiz
나쁨: $aReallyLongVariableNameWithoutAGoodReason
나쁨: $error_string

  • 상수들은 항상 대문자로 쓰며, 또 항상 모듈의 명칭으로 시작한다. 이들 단어들은 반드시 밑줄로 연결한다.

define("FORUM_MODE_FLATOLDEST", 1);

  • 함수명은 반드시 소문자로된 단순한 영어단어로 쓰되, 다른 모듈과의 충돌을 피하기 위해 모듈의 명칭으로 시작한다. 또한 단어들은 밑줄로 구분한다. 파라메터들은 가급적 상식적 기본값을 가져야 한다. 함수명이후에 나오는 문자들(괄호) 사이에는 공백이 있어서는 안된다는 점을 유념하라.

function forum_set_display_mode($mode=) {
global
$USER, $CFG;

if (
$mode) {
$USER->mode = $mode;
} else if (empty(
$USER->mode)) {
$USER->mode = $CFG->forum_displaymode;
}
}

  • 블록은 (단 한줄이라도) 항상 대괄호(curly braces)로 닫혀져야 한다. 무들은 다음과 같은 스타일로 사용한다.

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

  • 문자열 은 속도를 향상시키기 위해 가급적 홑따음표를 사용한다.

$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";

  • 주석(Comments)은 프로그램의 흐름과 각 함수나 변수를 설명하기 위해 실질적인 면에서 충실히 작성되어야만 한다.
    • 모든 함수(그리고 클래스)는 대중적인 phpDoc format을 써야만 한다. 그래야만 프로그램의 문서화가 자동적으로 이루어질 수 있다.
    • 코드 내부에서의 주석은 // 스타일로 쓰며, 말끔하게 놓아서 코드와 잘 일치하게 하여야 한다.

/**
* 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

  • 공백은 자유롭게 써도 좋다. 명확하게 보이게 하기 위하여 다소 공백을 늘이는 것에 대해 염려할 필요는 없다. 일반적으로 정상적 진술과 괄호 사이에는 하나의 공백이 있어야 하지만, 함수 혹은 변수와 괄호 사이에는 공백이 있어서는 안된다.

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)의 id 필드의 준거를 포함하는 컬럼은 widgetid라고 명명되어야 한다. (이러한 규정은 새로운 것이며 기존의 옛 테이블에서는 별로 쓰이지 않던 것임에 유의하라)
  6. 부울대수 필드(Boolean fields)는 0 또는 1을 포함하는 작은 정수 필드(예: INT4)로 정의되어야 하고 필요한 경우 추후 확장에 대비할 수 있도록 허용해야 한다.
  7. 대개의 테이블들은 timemodified 필드(INT10)를 가지고 있어서 PHP의 time() 함수로 얻어진 현재의 타임스템프로 갱신되는 것을 수용할 수 있어야 한다.

보안 문제(와 URL 데이터 및 폼 핸들링)

  1. 'register_globals'를 신뢰하지 말아라. 모든 변수들은 모든 코드 파일 내에서 적절히 초기화되어야만 한다. 변수가 어디에 속하는지 확실해야만 한다.
  2. 비록 빈 것이라 할지라도 모든 행렬과 객체는 초기화해야 한다. $a = array() 혹은 $obj = new stdClass();.
  3. optional_variable() 함수를 쓰지 말고 대신 optional_param()를 써라. 바라는 데이터 유형에 알맞는 PARAM_XXXX 값을 골라라. 변수에 적합한 임의 값을 설정하고 이를 점검하기 위해 set_default()함수를 이용하라.
  4. require_variable() 함수를 사용하지 말고 대신 required_param() 함수를 이용하라. 바라는 데이터 유형에 알맞는 PARAM_XXXX 값을 선택하라.
  5. 조심해서 data_submitted() 를 사용하라. 데이터는 사용하기 전에 반드시 오류를 제거해야 한다.
  6. $_GET, $_POST 또는 $_REQUEST는 사용하지 말아라. 여러분의 필요에 따라 적절한 required_param() 혹은 optional_param()를 사용하라.
  7. 작동을 점검하기 위해 if (isset($_GET['something'])) 과 같이 쓰지 마라. 대신 $something = optional_param( 'something',-1,PARAM_INT ) 을 입력하고 if ($something>=0) {... 처럼 써서 원하는 결과가 나오는지를 점검하라.
  8. 언제든 찾기 쉽게 모든 required_param(), optional_param() 그리고 변수의 초기값들은 각 파일의 처음에 모아 두어야 한다.
  9. 공격자들로부터 폼 핸들링 루틴을 보호하기 위하여 'sesskey' 메카니즘을 사용하라. 다음은 그 사용 예이다. 폼이 만들어 졌을 때는 <input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" /> 을 포함시키고, 폼의 작동 점검을 할 때는 if (!confirm_sesskey()) {error('Bad Session Key');} 를 쓴다.
  10. 모든 파일의 명칭은 clean_filename() 함수를 써서 '깨끗이' 만들어야 하며, required_param() 혹은 optional_param() 를 적절하게 쓰지 않았다면 이를 통과하지 못할 것이다.
  11. 데이터베이스에서 읽힌 어떤 데이터라도 다시 기록되기 위해서는 그 전에 addslashes()를 통과해야 한다. 모든 데이터 객체는 한 번씩 addslashes_object()를 거쳐야 한다.
  12. 어디서든 가능하다면, 데이터베이스에 저장될 데이터는 POST 데이터로 입력되어야 하며(method="POST"의 형태로), 반대의 경우는 GET 데이터로 URL 로부터 입력받아야 한다.
  13. 되도록이면 $_SERVER로 부터 데이터를 사용하지 말아라. 이는 이식성 문제(portability issues)를 가지고 있다.
  14. 만일 다른 어떤 곳에서도 점검된 바가 없다면, 데이터베이스에 기록된 모든 자료는 자료 유형에 따라 적합한 PARAM_XXXX를 사용하여clean_param()를 통과할 수 있도록 확실히 해 두어야 한다.
  15. 만일 여러분 스스로 SQL코드를 작성해야 한다면 오류가 없도록 철저하게 점검하라. 특별히 값(values)에 따옴표 치는 것에 유의하라. Possible SQL 'injection' exploit.
  16. 사용되는 파일에 들어있는 모든 데이터(특별히 데이터베이스에 사용된)를 점검하라. 다른 여타의 곳에서 사용될 것이라고 믿거나 기대하지 말아라.
  17. 내장할 코드 블럭들은 명확한 PHP 구조(예: 클래스 선언, 함수 정의 등)를 포함하여야 한다. 코드 블럭의 정돈은 초기화되지 않은 변수 사용을 증진시킨다.