Blog

Coding Convention 이란?

Coding Convention은 개발자들이 서로 작성한 코드들을 다른사람들이 보기 쉽도록 규칙을 정해 규격화 시키는 것을 말합니다.
그럼 Coding Convention을 왜 맞추어야 할까요? 말 그대로 코드의 가독성을 높여 작업 시간의 비용요소를 줄이고자 하는데 그 목적이 있습니다.

Code Sniffer

규칙을 정해놨다고 해도 단순히 눈으로만 보면 어느부분이 규칙에 맞지 않게 작성되었는지 찾기가 매우 어렵습니다.
그래서 간편하게 검사할 수 있는 툴을 활용하는 것이 좋습니다. Code Sniffer가 바로 Conding Convention을 검사하는 툴입니다.

설치

환경은 리눅스를 기반으로 진행하도록 하겠습니다.
참고로 제 vm 환경은 CentOS 6.5, PHP 5.5.15 입니다.

  • pear 설치
    먼저 pear를 다운로드 합니다.

    $ wget http://pear.php.net/go-pear.phar
    or 
    $ curl -O http://pear.php.net/go-pear.phar
    

    그리고 설치를 진행합니다.

    $ php go-pear.phar
    

    위 명령어를 입력하면 다음과 같은 화면이 나타납니다.스크린샷 2014-08-04 오후 6.11.28.png


  • 설치 경로를 지정하는 화면인데 엔터를 입력하시면 보이는 설정대로 설치가 진행됩니다. 다른 경로에 설치를 원하시면 해당 번호를 입력 후 원하는 경로로 변경하시면 됩니다.

  • Code Sniffer 설치
    pear 설치가 완료되면 Code Sniffer를 설치합니다.

    $ pear install PHP_CodeSniffer
    

    Code Sniffer를 실행하는 커맨드 phpcs는 pear설치시 binaries directory로 설정한 위치에 존재합니다.
    커맨드를 path 설정하거나 /usr/local/bin등에 소프트링크를 걸어두면 편리하게 사용할 수 있습니다.

설정

자 이제 설치가 완료 되었습니다. 테스트를 해봐야 겠죠?
php로 작성된 파일 하나를 가지고 Code Sniffer를 실행해 봅니다.

$ phpcs /path/to/filename.php

에러가 발생되지 않으면 바로 사용하시면 됩니다. 하지만 아마 에러가 발생하셨을거라 생각되네요.

PHP Warning:  include_once(PHP/CodeSniffer/CLI.php): failed to open stream: No such file or directory in /home/vagrant/pear/bin/phpcs on line 31

아마 이런 메시지가 나타나셨을 것입니다. 보시는 그대로 경로에 대한 에러죠. 수정해줍니다.
앞전에 path를 잡거나 소프트링크를 걸어주었던 phpcs 바이너리 파일을 열어줍니다.
그리고 에러가 발생된 부분을 수정합니다.

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
     include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} elseif (is_file(dirname(__FILE__).'/../share/pear/PHP/CodeSniffer/CLI.php') === true) {
         include_once dirname(__FILE__).'/../share/pear/PHP/CodeSniffer/CLI.php';
 } else {
     include_once 'PHP/CodeSniffer/CLI.php';
 }

저는 elseif구문을 추가해주었습니다. 앞서 진행한 pear설치 설정에 맞게 경로를 맞추어 주시면 됩니다.
자 그럼 다시 테스트 해보겠습니다.

$ phpcs /path/to/filename.php
FILE: /path/to/filename.php
--------------------------------------------------------------------------------
FOUND 6 ERROR(S) AFFECTING 4 LINE(S)
--------------------------------------------------------------------------------
  2 | ERROR | Missing file doc comment
  7 | ERROR | File is being conditionally included; use "include" instead
 14 | ERROR | Expected "if (...) {\n"; found "if (...)\n{\n"
 14 | ERROR | There must be a single space between the closing parenthesis and
    |       | the opening brace of a multi-line IF statement; found newline
 16 | ERROR | Spaces must be used to indent lines; tabs are not allowed
 16 | ERROR | Line indented incorrectly; expected at least 4 spaces, found 1
--------------------------------------------------------------------------------

실행이 정상적으로 처리되면 위와 같은 결과를 보실 수 있습니다.

설치 과정 Animation

codeSniffer.gif


사용

아 그런데 기본으로 잡혀있는 규칙은 우리가 사용하고자 하는 규칙이 아닙니다. 그럼 우리가 쓰고자하는 규칙을 정해야겠죠?

XE 전용 규칙을 적용해서 코드를 검사해보도록 하겠습니다.

XE 코딩 규칙에 대해서는 아래쪽에서 자세히 다루도록 하겠습니다.

규칙을 정하는 방법은 두가지 입니다.
하나는 명령어 실행시 옵션을 주는 방식입니다.

$ phpcs --standard=XpressEngine /path/to/filename.php

다른 하나는 config에 설정값을 넣어두는 것입니다.

$ phpcs --config-set default_standard XpressEngine

XpressEngine이 코딩 규칙의 이름입니다.

코딩 규칙들은 pear가 설치된 디렉토리 하위에 share/pear/PHP/CodeSniffer/Standards 아래 존재합니다. PEAR, Squiz, Zend, PSR1-2등등이 존재하며 필요시 규칙을 새로 생성할 수도 있습니다.
사용하고자 하는 규칙의 디렉토리명 그대로 standard 옵션에 작성하시면 해당 규칙으로 검사하게 됩니다.
규칙의 생성은 난이도가 높고 내용이 많아 여기서는 언급하지 않겠습니다.

Code Sniffer는 지정되는 대상이 파일이 아닌 디렉토리일 경우 해당 디렉토리 하위에 있는 모든 파일을 검사합니다.
하위의 하위 디렉토리도 포함됩니다.

이렇게 디렉토리 단위로 검사를 하게 될경우 php파일이 아닌 파일들이 있으면 해당파일들은 검사를 하지 않도록 해야합니다. 이럴땐extensions옵션을 추가해주시면 됩니다.

$ phpcs --standard=XpressEngine --extensions=php /path/to/dir

그런데 코딩을 하다보면 php파일이지만 검사하고 싶지 않은 것들도 있습니다. 이럴땐 ignore옵션을 추가해줍니다.

$ phpcs --standard=XpressEngine --extensions=php --ignore=aaa.php,bbb.php /path/to/dir

기타 옵션들에 대한 내용은 help옵션으로 확인하시면 됩니다.

$ phpcs --help

XpressEngine 코딩 규칙

XE 코딩 규칙 Sniff 파일은 GitHub 에서 가져올 수 있습니다.

$ git clone https://github.com/xpressengine/xe-coding-standard.git /path/to/your/standard/sniffer/directory/XpressEngine

설치 디렉토리경로는 위에서 설명한 다른 Standard들이 위치한 곳으로 지정해주시면 됩니다.your/pear-dir/share/pear/PHP/CodeSniffer/Standards/XpressEngine이 되겠죠.

그리고

$ phpcs --standard=XpressEngine /path/to/filename.php

이렇게 하시면 XE코딩 규칙 검사를 수행하게 됩니다.

XE에서 PHP코딩시 지켜져야할 규칙은 다음과 같습니다.

File

  • 파일 인코딩은 항상 UTF-8이여야 합니다.
  • 라인의 마지막은 Unix-style LF이어야 합니다.

일반

  • PHP파일의 오픈 태그는 <?php로 작성해야합니다.
  • PHP파일의 클로즈 태그 ?>는 사용하지 않습니다.
  • 파일의 마지막부분에 파일에 관한 코멘트가 작성되어야 합니다.
  • 문자열을 연결하는 dot.의 앞, 뒤에는 1개씩의 공백이 있어야 합니다.
  • 한줄에는 하나의 변수만 선언합니다.

[잘못된 코드 예시]

<?
echo 'Sample code'.$string;

$foo = 'this'; $bar = 'that'; $bat = str_replace($foo, $bar, $bag);
?>

[정상적인 코드 예시]

<?php
echo 'Sample code' . $string;

$foo = 'this';
$bar = 'that';
$bat = str_replace($foo, $bar, $bag);

/* End of file ModuleHandler.class.php */
/* Location: ./classes/module/ModuleHander.class.php */
  • 코멘트를 작성할때 #은 사용하지 않습니다.
  • TRUE, FALSE, NULL은 대문자로 작성합니다.

[잘못된 코드 예시]

<?php
if($var == true)
{
        echo 'Success';
}
function someFunction($arg = null)
{
        # function body here
}

[정상적인 코드 예시]

<?php
if($var == TRUE)
{
        echo 'Success';
}
function someFunction($arg = NULL)
{
        // function body here
}
  • 들여쓰기는 tab을 사용합니다.

Class

  • Class 구문은 들여쓰기되지 않아야 합니다.
  • 코멘트가 반드시 작성되어야 합니다.
  • 코멘트는 시작시 /**로 시작되어야합니다.
  • 코멘트는 종료시 */로 끝나야 합니다.
  • 코멘트에는 반드시 @author가 작성되어야 합니다.
  • Class명은 camelCase로 작성하시기를 권장 합니다.
  • Class를 여는 중괄호 {는 Class명 다음줄에 위치해야 합니다.

[잘못된 코드 예시]

<?php
        class some_class extends PDO{

        }

[정상적인 코드 예시]

<?php
/**
* this is someClass
*
* @author your name here
*/
class someClass extends PDO
{

}

Function

  • Class Method도 같은 규칙이 적용됩니다.
  • 이름은 camelCase형식으로 작성되어야 합니다.
  • 여는 중괄호 {는 Function명 다음 줄에 위치해야 합니다.
  • 코멘트가 반드시 작성되어야 합니다.
  • 코멘트는 시작시 /**로 시작되어야합니다.
  • 코멘트는 종료시 */로 끝나야 합니다.
  • 코멘트의 설명 앞에 공백 라인이 있으면 안됩니다.
  • 코멘트의 설명 다음 라인은 공백 라인이어야 합니다.
  • 코멘트에는 파라미터에대한 내용이 포함되어야 합니다.
    • @param 자료형 변수명 설명 형식으로 작성되어야 합니다.
    • 각 영역은 들여쓰기를 이용하여 정렬을 맞추어야 합니다.
  • 마지막 파라미터 코멘트 다음에는 빈 라인이 1개 있어야 합니다.
  • @return 태그가 작성되어야 합니다.

[잘못된 코드 예시]

<?php
/*
* This is SomeFunction
* @param int $arg1
* @param string $arg2
*/
function SomeFunction($arg1, $arg2){
    // function body
}

[정상적인 코드 예시]

<?php
/**
* This is SomeFunction
* 
* @param int    $arg1 this is first argument
* @param string $arg2 this is second argument
* 
* @return void
*/
function someFunction($arg1, $arg2)
{
    // function body
}

제어구조문

  • 연산기호, 기호구문의 앞, 뒤에는 1개의 공백이 있어야 합니다.
  • 조건절이 포함되는 소괄호 (와 제어구조문 사이에는 공백이 없어야 합니다.
  • 여는 소괄호 (뒤와 닫는 소괄호 )앞에는 공백이 없어야 합니다.
  • 제어구조문내에 처리되는 코드가 1줄만 존재하더라도 중괄호 {, }를 사용해야 합니다.
  • 여는 중괄호 {는 제어구조문의 다음 라인에 존재해야 합니다.
  • 닫는 중괄호 }는 내용의 다음줄에 존재해야 합니다.
  • for구문과 같이 조건절에 ;이 사용되는 곳에서는 ;의 앞에는 공백이 없어야 하고 뒤에는 1개의 공백이 있어야 합니다.
  • foreach구문의 key, value를 표시하는 =>의 앞과 뒤에는 1개의 공백이 있어야 합니다.

[잘못된 코드 예시]

<?php
for( $i=0;$i<10;$i++ )
{
}
if ($a == $b) echo 'it is true';
foreach($array as $key=>$value){
}

[정상적인 코드 예시]

<?php
for($i = 0; $i < 10; $i++)
{
}
if($a == $b)
{
    echo 'it is true';
}
foreach($array as $key => $value)
{
}

상수

  • 선언되어질 상수는 소문자를 사용할 수 없습니다.
  • 프로그램 전체에 사용되어질 상수는 앞과 뒤에 언더바 2개 __를 붙입니다.
  • 이해가능한 형태의 이름을 사용해야 합니다.

[잘못된 코드 예시]

<?php
define('myConstant', '1.2.3');    // 소문자 사용 불가
define('V', '1.2.3');            // 한글자만 사용할 수 없음
define('A_B_C', '1.2.3');        // 의미를 알수 없음

[정상적인 코드 예시]

<?php
define('__XE_VERSION__', '1.7.5');    // 전역 사용 상수
defind('XE_VERSION', '1.7.5');        // 지역 사용 상수

문자열

  • 선언된 그대로 표현되는 문자열은 큰따옴표"를 사용하지 않고 작은따옴표'를 사용합니다.
  • 문자열내에 작은따옴표'가 존재하는 경우 큰따옴표"를 사용합니다.
  • 문자열내에 변수가 포함될 경우 큰따옴표"를 사용합니다.
  • 문자열내에 변수가 포함될 경우 변수는 중괄호{, }를 붙입니다.

[잘못된 코드 예시]

"My String"
"My String $foo"
'SELECT foo FROM bar WHERE baz = \'bag\''

[정상적인 코드 예시]

'My String'
"My String {$foo}"
"SELECT foo FROM bar WHERE bas = 'bag'"

Contribute

XE Core GitHub

https://github.com/xpressengine/xe-core

기여해주시는 Contributor 분들은 Pull Request시 위의 규칙에 준수하여 주시기 바라며 Pull Request 전 규칙검사를 하신 후 전달해 주시기 바랍니다.