PHPプログラミングで理解しなければならない5つの良い習慣
PHPプログラミングで理解しなければならない5つの良い習慣
具体的には、一般的な開発者は優秀な開発者より10%~20%効率が低いことが多い.優れた開発者は、豊富な経験と優れたプログラミング習慣を持っているため、より効率的です.悪いプログラミング習慣は効率に影響します.この文書では、優れたプログラミング習慣を示すことで、より優れたプログラマーになることができます.
これらの優れたプログラミング習慣は、効率を向上させるだけでなく、アプリケーションのライフサイクル全体でメンテナンスしやすいコードを作成することができます.作成されたコードには大量のメンテナンスが必要になる可能性があります.アプリケーションのメンテナンスは大きな費用です.良好なプログラミング習慣を身につけることで、設計品質(例えばモジュール化)を向上させ、コードをより理解しやすくすることができるため、メンテナンスがより容易になり、メンテナンスコストも低減される.
不良なプログラミング習慣はコードの欠陥をもたらし、メンテナンスと修正が困難になり、修正時に他の欠陥を導入する可能性が高い.以下は、PHPコードがこれらの欠陥を回避するのに役立つ5つの良いプログラミング習慣です.
良好なネーミングを使用します.
より小さな部分に分ける.
コードにコメントを追加します.
エラー条件を処理します.
コピー&ペーストは使用しないでください.
次のセクションでは、これらの習慣について詳しく説明します.
良好なネーミングの使用
記述性の強い名前はコードを読みやすく理解するため、良い名前を使用することが最も重要なプログラミング習慣です.コードが理解できるかどうかは、将来維持できるかどうかにかかっています.コードにコメントがなくても、理解しやすい場合は、後で変更するのに便利です.この習慣の目標は、あなたが書いたコードを本のように読みやすく理解することです.
悪い習慣:あいまいまたは無意味な名前
リスト1のコードには、短すぎる変数名、認識しにくい略語が含まれており、メソッド名はそのメソッドの機能を反映できない.メソッド名がこのことをすべきだと感じているのに、実際には別のことをすると、人を誤解させるため、深刻な問題をもたらします.
リスト1.悪い習慣:あいまいまたは無意味な名前
<?php
function getNBDay($d)
{
switch($d) {
case 5:
case 6:
case 7:
return 1;
default:
return ($d + 1);
}
}
$day = 5;
$nextDay = getNBDay($day);
echo ("Next day is: " . $nextDay . "
");
?>
良い習慣:説明性が強く、簡潔な名前
リスト2のコードは良好なプログラミング習慣を体現している.新しいメソッド名は説明性が強く,メソッドの用途を反映している.同様に,変更後の変数名もより説明的である.最も短い変数は
$i
であり、このリストでは循環変数である.短い名前の使用に賛成しない人が多いが、コードの機能を明確に示しているため、ループ変数での使用は許容できる(さらには利点がある).リスト2.良い習慣:説明性が強く、簡潔な名前
<?php
define ('MONDAY', 1);
define ('TUESDAY', 2);
define ('WEDNESDAY', 3);
define ('THURSDAY', 4);
define ('FRIDAY', 5);
define ('SATURDAY', 6);
define ('SUNDAY', 7);
/*
*
* @param $dayOfWeek
* @return int Day of week, with 1 being Monday and so on.
*/
function findNextBusinessDay($dayOfWeek)
{
$nextBusinessDay = $dayOfWeek;
switch($dayOfWeek) {
case FRIDAY:
case SATURDAY:
case SUNDAY:
$nextBusinessDay = MONDAY;
break;
default:
$nextBusinessDay += 1;
break;
}
return $nextBusinessDay;
}
$day = FRIDAY;
$nextBusDay = findNextBusinessDay($day);
echo ("Next day is:" . $nextBusDay . "
");
?>
大きな条件を1つの方法に分割し、その条件を記述できる名前で名前を付けることをお勧めします.このテクニックは、コードの可読性を向上させ、条件を具体化し、抽出したり再利用したりすることができる.条件が変化すれば、更新方法も簡単です.メソッドには意味のある名前があるので、コードの用途を反映し、コードを読みやすくすることができます.
トップに戻る
より小さな部分に分ける
問題の解決に専念してからプログラミングを続けると、より簡単になります.緊急の問題を解決するとき、プログラミングを続けると、関数がますます長くなります.長期的には問題ではありませんが、振り返ってより小さな部分に再構築することを覚えておいてください.
再構築は良いアイデアですが、より短く、機能が集中したコードを書くことを身につけなければなりません.短い方法は1つのウィンドウで一度に見ることができ、理解しやすい.方法が長すぎて、1つのウィンドウで一度に見ることができない場合は、最初から最後まで考え全体を迅速に理解できないため、理解しにくくなります.
メソッドを構築するときは、各メソッドが1つのことしかできないようにする習慣を身につけなければなりません.この習慣はとても良いです.まず、方法が一つのことだけを完成すれば、それはもっと再利用されやすいからです.次に、このような方法はテストしやすい.第三に、このような方法は理解しやすく、変更しやすい.
悪い習慣:長すぎる方法(多くのことを完成する)
リスト3は,多くの問題がある長い関数を示している.それは多くのことを完成しているので、コンパクトではありません.読み取り、デバッグ、テストにも不便です.ファイルを巡ること、リストを構築すること、オブジェクトごとに値を割り当てること、計算を実行することなどが含まれます.
リスト3.悪い習慣:長すぎる関数
<?php
function writeRssFeed($user)
{
// Get the DB connection information
// look up the user's preferences...
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());
// Query
$perfsQuery = sprintf("SELECT max_stories FROM user_perfs WHERE user= '%s'",
mysql_real_escape_string($user));
$result = mysql_query($query, $link);
$max_stories = 25; // default it to 25;
if ($row = mysql_fetch_assoc($result)) {
$max_stories = $row['max_stories'];
}
// go get my data
$perfsQuery = sprintf("SELECT * FROM stories WHERE post_date = '%s'",
mysql_real_escape_string());
$result = mysql_query($query, $link);
$feed = "<rss version=\"2.0\">" .
"<channel>" .
"<title>My Great Feed</title>" .
"<link>http://www.example.com/feed.xml</link>" .
"<description>The best feed in the world</description>" .
"<language>en-us</language>" .
"<pubDate>Tue, 20 Oct 2008 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Tue, 20 Oct 2008 10:00:00 GMT</lastBuildDate>" .
"<docs>http://www.example.com/rss</docs>" .
"<generator>MyFeed Generator</generator>" .
"<managingEditor>[email protected]</managingEditor>" .
"<webMaster>[email protected]</webMaster>" .
"<ttl>5</ttl>";
// build the feed...
while ($row = mysql_fetch_assoc($result)) {
$title = $row['title'];
$link = $row['link'];
$description = $row['description'];
$date = $row['date'];
$guid = $row['guid'];
$feed .= "<item>";
$feed .= "<title>" . $title . "</title>";
$feed .= "<link>" . $link . "</link>";
$feed .= "<description> " . $description . "</description>";
$feed .= "<pubDate>" . $date . "</pubDate>";
$feed .= "<guid>" . $guid . "</guid>";
$feed .= "</item>";
}
$feed .= "</rss";
// write the feed out to the server...
echo($feed);
}
?>
このような方法をいくつか多く作成すれば、メンテナンスは本当の難題になります.
良好な習慣:管理しやすく、機能が専門的な方法
リスト4は、従来の方法をよりコンパクトで読みやすい方法に書き換える.この例では、長い方法をいくつかの短い方法に分解し、各短い方法に1つのことを担当させる.このようなコードは、将来の再利用やテストに役立ちます.
リスト4.良好な習慣:管理しやすく、機能が専門的な方法
<?php
function createRssHeader()
{
return "<rss version=\"2.0\">" .
"<channel>" .
"<title>My Great Feed</title>" .
"<link>http://www.example.com/feed.xml</link>" .
"<description>The best feed in the world</description>" .
"<language>en-us</language>" .
"<pubDate>Tue, 20 Oct 2008 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Tue, 20 Oct 2008 10:00:00 GMT</lastBuildDate>" .
"<docs>http://www.example.com/rss</docs>" .
"<generator>MyFeed Generator</generator>" .
"<managingEditor>[email protected]</managingEditor>" .
"<webMaster>[email protected]</webMaster>" .
"<ttl>5</ttl>";
}
function createRssFooter()
{
return "</channel></rss>";
}
function createRssItem($title, $link, $desc, $date, $guid)
{
$item .= "<item>";
$item .= "<title>" . $title . "</title>";
$item .= "<link>" . $link . "</link>";
$item .= "<description> " . $description . "</description>";
$item .= "<pubDate>" . $date . "</pubDate>";
$item .= "<guid>" . $guid . "</guid>";
$item .= "</item>";
return $item;
}
function getUserMaxStories($db_link, $default)
{
$perfsQuery = sprintf("SELECT max_stories FROM user_perfs WHERE user= '%s'",
mysql_real_escape_string($user));
$result = mysql_query($perfsQuery, $db_link);
$max_stories = $default;
if ($row = mysql_fetch_assoc($result)) {
$max_stories = $row['max_stories'];
}
return $max_stories;
}
function writeRssFeed($user)
{
// Get the DB connection information
$settings = parse_ini_file("rss_server.ini");
// look up the user's preferences...
$link = mysql_connect($settings['db_host'], $settings['user'],
$settings['password']) OR die(mysql_error());
$max_stories = getUserMaxStories($link, 25);
// go get my data
$newsQuery = sprintf("SELECT * FROM stories WHERE post_date = '%s'",
mysql_real_escape_string(time()));
$result = mysql_query($newsQuery, $link);
$feed = createRssHeader();
$i = 0;
// build the feed...
while ($row = mysql_fetch_assoc($result)) {
if ($i < $max_stories) {
$title = $row['title'];
$link = $row['link'];
$description = $row['description'];
$date = $row['date'];
$guid = $row['guid'];
$feed .= createRssItem($title, $link, $description, $date, $guid);
$i++;
} else {
break;
}
}
mysql_close($link);
$feed .= createRssFooter();
// write the feed out to the server...
echo($feed);
}
?>
長い方法を短い方法に分割することも制限されており、過度な分割は逆効果になります.そのため、この良い習慣を乱用しないでください.コードを大量のセグメントに分割することは、長いコードを分割していないように、読み取りが困難になります.
トップに戻る
コードにコメントを追加
コードに良いコメントを追加するのは、コードを書くのと同じように難しい場合があります.注釈コードが現在行われていることに傾いているため、注釈を追加するのは容易ではありません.注釈コードの目的はいいアイデアです.関数のあまり明らかでないヘッダコードブロックでは,読者にメソッドの入力と出力,およびメソッドの最初のターゲットを教える.
アノテーションコードは現在何をしているかはよくありますが、これは必要ありません.コードが複雑な場合は、現在何をしているのかコメントしなければなりません.これは、コードを書き直して理解しやすくすることを意味します.良好な名前とより短い方法を学び、注釈を提供せずにその用途を説明する場合にコードの可読性を高める.
悪い習慣:関数の注釈が多すぎるか不足している
インベントリ5の注釈は、読者コードが何をしているかのみを示します.これは、1つのループで反復または数値を追加しています.しかし、なぜ現在の仕事をしているのか無視されています.これにより、コードを維持するユーザは、コードを安全に変更できるかどうか(新しい欠陥を導入しない)分からない.
リスト5.悪い習慣:関数の注釈が多すぎるか不足している
<?php
class ResultMessage
{
private $severity;
private $message;
public function __construct($sev, $msg)
{
$this->severity = $sev;
$this->message = $msg;
}
public function getSeverity()
{
return $this->severity;
}
public function setSeverity($severity)
{
$this->severity = $severity;
}
public function getMessage()
{
return $this->message;
}
public function setMessage($msg)
{
$this->message = $msg;
}
}
function cntMsgs($messages)
{
$n = 0;
/* iterate through the messages... */
foreach($messages as $m) {
if ($m->getSeverity() == 'Error') {
$n++; // add one to the result;
}
}
return $n;
}
$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));
$errs = cntMsgs($messages);
echo("There are " . $errs . " errors in the result.
");
?>
良い習慣:注釈付き関数とクラス
リスト6の注釈は、読者にクラスと方法の目的を教える.このコメントは、コードが現在の作業をしている理由を説明し、将来のコードの維持に役立ちます.条件変更に応じてコードを修正する必要がある場合がありますが、コードの目的を簡単に理解できれば、修正が容易になります.
リスト6.良い習慣:注釈付き関数とクラス
<?php
/**
* The ResultMessage class holds a message that can be returned
* as a result of a process. The message has a severity and
* message.
*
* @author nagood
*
*/
class ResultMessage
{
private $severity;
private $message;
/**
* Constructor for the ResultMessage that allows you to assign
* severity and message.
* @param $sev See {@link getSeverity()}
* @param $msg
* @return unknown_type
*/
public function __construct($sev, $msg)
{
$this->severity = $sev;
$this->message = $msg;
}
/**
* Returns the severity of the message. Should be one
* "Information", "Warning", or "Error".
* @return string Message severity
*/
public function getSeverity()
{
return $this->severity;
}
/**
* Sets the severity of the message
* @param $severity
* @return void
*/
public function setSeverity($severity)
{
$this->severity = $severity;
}
public function getMessage()
{
return $this->message;
}
public function setMessage($msg)
{
$this->message = $msg;
}
}
/*
* Counts the messages with the given severity in the array
* of messages.
*
* @param $messages An array of ResultMessage
* @return int Count of messages with a severity of "Error"
*/
function countErrors($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Error") {
$matchingCount++;
}
}
return $matchingCount;
}
$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));
$errs = countErrors($messages);
echo("There are " . $errs . " errors in the result.
");
?>
トップに戻る
処理エラー
一般的な経験によると、堅牢なアプリケーションを作成するには、エラー処理は80/20ルールに従います.80%のコードは例外と検証を処理し、20%のコードは実際の作業を完了するために使用されます.プログラムの基本論理(happy-path)コードを記述する際によくそうします.これは、基本条件に適したコードを記述することを意味します.すなわち、すべてのデータが使用可能であり、すべての条件が予想に合致しています.このようなコードは、アプリケーションのライフサイクルで脆弱である可能性があります.もう1つの極端は、経験したことのない条件のためにコードを書くのに多くの時間がかかることです.
この習慣では、すべてのエラーに対処するコードを書くのではなく、十分なエラー処理コードを書く必要があります.そのため、コードがなかなか完成しません.
不良習慣:エラー処理コードがまったくありません
リスト7のコードは、2つの不良習慣を示している.第一に、入力されたパラメータはチェックされていません.ある状態のパラメータがメソッドに異常をもたらすことを知っていても.第二に、コードは例外を放出する可能性のある方法を呼び出すが、例外は処理されない.問題が発生した場合、コードの作成者またはコードを維持している人は、問題の根源を推測するしかありません.
http://varsoft.iteye.com/blog/969135
リスト7.不良習慣:エラー条件を処理しない
<?php
// Get the actual name of the
function convertDayOfWeekToName($day)
{
$dayNames = array(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday");
return $dayNames[$day];
}
echo("The name of the 0 day is: " . convertDayOfWeekToName(0) . "
");
echo("The name of the 10 day is: " . convertDayOfWeekToName(10) . "
");
echo("The name of the 'orange' day is: " . convertDayOfWeekToName('orange') . "
");
?>
良好な習慣:異常処理
インベントリ8は、有意義な方法で異常を放出および処理することを示す.追加のエラー処理は、コードをより丈夫にするだけでなく、コードの可読性を向上させ、コードをより理解しやすくします.異常処理の仕方は,原作者が方法を記述する際の意図をよく説明している.
リスト8.良好な習慣:異常処理
<?php
/**
* This is the exception thrown if the day of the week is invalid.
* @author nagood
*
*/
class InvalidDayOfWeekException extends Exception { }
class InvalidDayFormatException extends Exception { }
/**
* Gets the name of the day given the day in the week. Will
* return an error if the value supplied is out of range.
*
* @param $day
* @return unknown_type
*/
function convertDayOfWeekToName($day)
{
if (! is_numeric($day)) {
throw new InvalidDayFormatException('The value \'' . $day . '\' is an ' .
'invalid format for a day of week.');
}
if (($day > 6) || ($day < 0)) {
throw new InvalidDayOfWeekException('The day number \'' . $day . '\' is an ' .
'invalid day of the week. Expecting 0-6.');
}
$dayNames = array(
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday");
return $dayNames[$day];
}
echo("The name of the 0 day is: " . convertDayOfWeekToName(0) . "
");
try {
echo("The name of the 10 day is: " . convertDayOfWeekToName(10) . "
");
} catch (InvalidDayOfWeekException $e) {
echo ("Encountered error while trying to convert value: " . $e->getMessage() . "
");
}
try {
echo("The name of the 'orange' day is: " . convertDayOfWeekToName('orange') . "
");
} catch (InvalidDayFormatException $e) {
echo ("Encountered error while trying to convert value: " . $e->getMessage() . "
");
}
?>
パラメータの確認は確認ですが、パラメータがある状態であることが要求される場合は、メソッドを使用する人に役立ちます.ただし、それらを確認し、意味のある例外を投げ出す必要があります.
異常の処理はできるだけ発生した問題と密接に関連しなければならない.
各例外を専門に処理します.
トップに戻る
コピー&ペーストは使用しないでください
他の場所からコードをコピーして自分のコードエディタに貼り付けることができますが、これはメリットとデメリットがあります.良い側面は、1つの例またはテンプレートから多くのエラーを回避できることである.悪い面は、これは多くの類似プログラミング方式をもたらしやすいことです.
アプリケーションの一部から別の部分にコードをコピーして貼り付けないように注意してください.このような方法を採用する場合は、この悪い習慣を止めて、このコードを再利用可能に書き換えることを考えてください.一般的に、コードを1つの場所に配置すると、コードを1つの場所で変更するだけで、後日のメンテナンスが容易になります.
悪い習慣:類似のコードセグメント
リスト9は、その値が異なるだけで、ほとんど同じ方法をいくつか示しています.コピーして貼り付けられたコードを見つけるのに役立つツールがあります(参考資料を参照).
リスト9.悪い習慣:類似のコードセグメント
<?php
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Error"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countErrors($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Error") {
$matchingCount++;
}
}
return $matchingCount;
}
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countWarnings($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Warning") {
$matchingCount++;
}
}
return $matchingCount;
}
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Information"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countInformation($messages)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Information") {
$matchingCount++;
}
}
return $matchingCount;
}
$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));
$errs = countErrors($messages);
echo("There are " . $errs . " errors in the result.
");
?>
良い習慣:パラメータ付き再利用可能な関数
インベントリ10は、コピーされたコードを1つの方法に格納する修正されたコードを示している.別のメソッドも変更され、新しいメソッドにタスクを委任します.汎用的な方法を構築するには時間がかかり、本能的にコピーペーストを使用するのではなく、思考を止めることができます.ただし、変更が必要な場合は、共通の方法に費やした時間が報われます.
リスト10.良い習慣:パラメータ付き再利用可能な関数
<?php
/*
* Counts the messages with the given severity in the array
* of messages.
*
* @param $messages An array of ResultMessage
* @return int Count of messages matching $withSeverity
*/
function countMessages($messages, $withSeverity)
{
$matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == $withSeverity) {
$matchingCount++;
}
}
return $matchingCount;
}
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Error"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countErrors($messages)
{
return countMessages($messages, "Errors");
}
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countWarnings($messages)
{
return countMessages($messages, "Warning");
}
/**
* Counts the number of messages found in the array of
* ResultMessage with the getSeverity() value of "Warning"
*
* @param $messages An array of ResultMessage
* @return unknown_type
*/
function countInformation($messages)
{
return countMessages($messages, "Information");
}
$messages = array(new ResultMessage("Error", "This is an error!"),
new ResultMessage("Warning", "This is a warning!"),
new ResultMessage("Error", "This is another error!"));
$errs = countErrors($messages);
echo("There are " . $errs . " errors in the result.
");
?>
終わりの言葉
PHPコードの作成中に本明細書で説明する良い習慣を身につけると、読みやすく、理解しやすく、メンテナンスしやすいコードを構築できます.この方法で構築されたメンテナンスしやすいコードは、デバッグ、修復、拡張コードが直面するリスクを低減します.
良好な名前とより短い方法を使用すると、コードの可読性が向上します.注釈コードの目的は、コードの理解と拡張に有利である.エラーを適切に処理すると、コードがより丈夫になります.最後に,コピー貼り付けの使用を停止し,コードをきれいに保ち,再利用性を向上させる.