クリンナップのまとめ

  • ページ: BugTrack
  • 投稿者: henoheno
  • 優先順位: 低
  • 状態: 着手
  • カテゴリー: その他
  • 投稿日: 2005-01-15 (土) 16:05:34
  • バージョン:

メッセージ

PHPについてよくやりがちな修正といつかやりそうな修正について、その解説をここにまとめましょう。



ポカヨケ


'and/or' for boolean => '&&/||'

BEFORE: if ($count == 0 or $foo == 'bar') do_someting();
AFTER:  if ($count == 0 || $foo == 'bar') do_someting();

if文などで使われる論理演算( a == b, a > b など ) に演算子「and」「or」が使われている場合、容赦なく「&&」「||」に修正します (^^;

概要

OK: $dp = @opendir($dir) or die($dir . ' is not found or not readable.');

and / or 演算子は 代入文よりも後に評価されます。

'something or die()' という書き方はPerlでは普通に使われています。

実例

BUG:   $via_proxy = $use_proxy and via_proxy($arr['host']);

!boolean => ! boolean / &var => & var

BEFORE: if (!bool) do_someting();
AFTER:  if (! bool) do_someting();

今後のメンテナンスをふまえ、変数名・関数名の修正などを行う際にうっかり判定結果を反転させる事が無い様に、同様に参照渡しであるところの「&」を削ることが無い様に、極力スペースを挿入する様にしています (^^;


記述内容の整理

function_exists('gzfile') => extension_loaded('zlib')

BEFORE:  if (function_exists('gzfile')) { ... }
AFTER:   if (extension_loaded('zlib')) { ... }

特定のPHPエクステンションを要求している場合、それを明確に記述します。

このようにしておくと、コードを見た人間が「そうかウチの環境にはzlib入ってないや」などと即座に気付く事ができるようにもなります。


簡潔な記述 (兼 多少の速度向上)

  • $increment++; => ++$increment;
  • $decrement--; => --$decrement;

正規表現が不要な文字列操作であるならば preg_ 系関数は使わない

preg_replace("/\n/", '', $string) => str_replace("\n", '', $string)
preg_replace("/[\r\n]*$/", '', $line); => rtrim($line, "\r\n");

簡潔な文字列関数で表現できる操作(意図)についてはそのように記述すべきです。正規表現を利用する関数を用いる場合、正規表現を処理するため、一般的にオーバーヘッド(メモリとCPU)が大きくなります。

一方、正規表現関数を用いることでコードを手早く構築することができるでしょう。また、時間が豊富にあるならば、後で整理する事ができます。これはバランスの問題です。

Quotation ("strings" => 'strings')

BEFORE: $str = "strings"; $array = array["cmd"];
AFTER:  $str = 'strings'; $array = array['cmd'];

(PHPの場合)単なる文字列を囲むのにダブルクォートを使っている場合、無条件でシングルクォートに直すことができます。一般的にダブルクォートは変数展開などが可能であるため、コンパイル時に無駄な処理が発生します。

BEFORE: $url = "$script?$r_page";
AFTER:  $url = $script . '?' . $r_page;

同様に、変数を不必要にダブルクォーテーションの中に入れている場合、無条件で取り出すことができます。不要な変数展開を防ぐほか、PHPコードのシンタックスカラーリングが可能なエディタやデバッガでの可読性が向上します。

count() => empty()

BEFORE: if(count($array))
AFTER:  if(! empty($array))
BEFORE: if(count($array) == 0)
AFTER:  if(empty($array))

「配列の数が0かどうか」を比較している部分に count() を使っている場合、随時 ! empty() に置き換えます。(配列の数を最後まで数えさせる必要が無いため)

ポイント

厳密には empty は必要ではありませんが、コード(行)の可読性が損なわれると判断しているため省略していません。

AFTER:  if(! empty($array))
AFTER:  if($array)

ベンチマーク

<?php
       // Code from PukiWiki
       // 現在時刻をマイクロ秒で取得
       function getmicrotime() {
               list($usec, $sec) = explode(' ', microtime());
               return ((float)$sec + (float)$usec);
       }

       // Init
       $count = array();
       for($i = 0; $i < 10; $i++)
               $count[$i] = TRUE;

       // Bench start -----------------
       define('MUTIME', getmicrotime());
       // ----

       //var_dump($count);
       for($i = 0; $i < 5000; $i++) {
               if (1) {
                       if (count($count))  echo '- ';
                       //if ($count) echo '- ';
               } else {
                       if (! empty($count)) echo '- ';
               }
       }

       // ----
       $taketime = sprintf('%01.03f', getmicrotime() - MUTIME);
       // Bench end -------------------

       echo '<br/>' . 'HTML convert time: ' . $taketime;
?>

array_key_exits() => isset()

BEFORE: $page = array_key_exists('page', $vars) ? $vars['page'] : '';
AFTER:  $page = isset($vars['page']) ? $vars['page'] : '';

多少早くなるという事以外に、「その配列の利用のされ方」を理解しやすくなるのが大きなポイントです。

ベンチマーク

※上下は省略

       for($i = 0; $i < 5000; $i++) {
               if (1) {
                       if (array_key_exists(0, $count))  echo '- ';
               } else {
                       if (isset($count[0])) echo '- ';
               }
       }

マルチバイト文字列

主に文字化けが絶対に起きないようにするためのケア

  • SOURCE_ENCODINGを明確に指定すること
BEFORE: mb_convert_kana($str, $option);
AFTER:  mb_convert_kana($str, $option, SOURCE_ENCODING);
BEFORE: mb_strlen($word_nm);
AFTER:  mb_strlen($word_nm, SOURCE_ENCODING);
BEFORE: mb_substr($word_nm, $pos, 1);
AFTER:  mb_substr($word_nm, $pos, 1, SOURCE_ENCODING);

PukiWiki独自の部分

  • global $script => get_script_uri()
    • 設定 $script_directory_index の値を反映した内容を返します。

プラグイン

  • 定数の名称:
       PLUGIN_<プラグイン名(大文字)>_<[A-Z0-9][A-Z0-9_]+[A-Z0-9]>
  • プラグインファイル内で別途定義する関数の名称:
      function plugin_<プラグイン名(小文字)>_<[a-z0-9][a-z0-9_]+[a-z0-9]>
    • ※プライベートな関数を アンダースコア (_) 始まりにする事はまだ行われていません

過去の整理事例


コメント

  • このほか、従来のPukiWikiのスタイル(ハードタブでインデントしているなど)に沿わせる修正や、PEAR標準コーディング規約で示されているようなスタイルに沿わせる形の修正が 1.4.4 => 1.4.5 の間に大量に入っています。 -- henoheno 2005-02-05 (土) 14:36:07
  • インデント1つとっても、diff に含まれる tab を patch がうまく拾わない場合があり、汚いソースになる。そういう汚いソースを見たことがあるかどうかですよねぇ。 -- upk 2005-02-05 (土) 17:06:26
  • へーこういうのがあったんですが。今度はこれを気にして書こうと思います。function の場合は { が次の行で if の場合は同行なんですか。なんかフォーマッタ作りにくそうですね。これに準拠したフォーマッタってあるんですか? -- 2005-02-05 (土) 18:27:43
  • 関連?ロードマップ -- 2005-09-25 (日) 15:33:27
  • count() は empty() よりも重たくはあるが、「配列の要素数に比例してコストが増える」わけではない。また、keyなしのforeachが最速という話 http://d.hatena.ne.jp/odz/20061026/1161927585 -- 2006-10-30 (月) 23:37:14
  • メンバ変数の参照は、通常の変数の参照より遅いよという話 http://d.hatena.ne.jp/nazone/20070508/p1 -- 2007-06-24 (日) 19:30:35
  • 2004/03 の時点では、PHP5はPHPより遅く見えるんだけれどという話 -- 2007-06-24 (日) 19:35:52
  • カタコト日記: PHP コード最適化 Best Practices 63+ http://d.hatena.ne.jp/koto2/20080518/1211070116 -- 2008-05-23 (金) 01:59:19
  • ウノウラボ PHP最適化tipsまとめサイト http://labs.unoh.net/2007/05/phptips.html -- 2008-05-23 (金) 01:59:43

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-05-23 (金) 02:00:15
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.204 sec.

OSDN