В зависимости от конкретной ситуации средние разработчики зачастую на 10–20 % менее эффективны, чем отличные разработчики. Хорошие разработчики более эффективны, потому что у них большой опыт и хорошие навыки программирования. Плохие привычки программирования влияют на эффективность. Эта статья поможет вам стать лучшим программистом, продемонстрировав некоторые хорошие навыки программирования.
Эти хорошие навыки программирования не только повышают эффективность, но и позволяют писать код, который легко поддерживать на протяжении всего жизненного цикла вашего приложения. Код, который вы пишете, может потребовать большого обслуживания; обслуживание приложения требует значительных затрат. Развитие хороших навыков программирования может улучшить качество проектирования (например, модульность), сделать код более понятным и, следовательно, более простым в обслуживании, а также снизить затраты на обслуживание.
Плохие привычки программирования приводят к дефектам кода, затрудняют его поддержку и модификацию, а также могут привести к появлению других дефектов при изменении. Ниже приведены 5 полезных привычек программирования, которые помогут PHP-коду избежать этих ошибок:
◆Используйте правильное именование.
◆Разделите на более мелкие части.
◆Добавляйте комментарии к коду.
◆Обработка ошибок.
◆Не используйте копирование и вставку.
Эти привычки подробно описаны ниже:
Используйте правильное именование
.Использование правильного именования является наиболее важной привычкой программирования, поскольку описательные имена облегчают чтение и понимание кода. Легкость понимания кода зависит от того, можно ли его поддерживать в будущем. Даже если код раскомментирован, он значительно облегчит будущие изменения, если его будет легко понять. Цель этой привычки — сделать код, который вы пишете, таким же простым для чтения и понимания, как книгу.
Плохая привычка: расплывчатые или бессмысленные имена.
Код в листинге 1 содержит слишком короткие имена переменных, неразборчивые сокращения и имена методов, которые не отражают функциональность метода. Если имя метода создает впечатление, что он должен делать одно, а на самом деле он делает другое, это вызовет серьезные проблемы, поскольку будет вводить в заблуждение.
Листинг 1. Вредные привычки: расплывчатые или бессмысленные имена
<?php
function getNBDay($d){
переключатель ($ d) {
случай 5:
случай 6:
случай 7:
возврат 1;
по умолчанию:
возврат ($d + 1);
}
}
$day = 5;
$nextDay = getNBDay($day);
echo ("Следующий день: " . $nextDay . "n")
;
Передовая практика: описательные и краткие имена
Код в листинге 2 демонстрирует хорошие методы программирования. Имена новых методов очень информативны и отражают цель метода. Аналогично, измененные имена переменных более информативны. Единственная переменная, которая остается самой короткой, — это $i, которая в этом листинге является переменной цикла. Хотя многие люди не одобряют использование слишком коротких имен, их допустимо (и даже полезно) использовать в переменных цикла, поскольку это четко указывает на функцию кода.
Листинг 2. Хорошая практика: описательные и краткие имена
<?php
определить («ПОНЕДЕЛЬНИК», 1);
определить («ВТОРНИК», 2);
определить («СРЕДА», 3);
определить («ЧЕТВЕРГ», 4);
определить («ПЯТНИЦА», 5);
определить («СУББОТА», 6);
определить («ВОСКРЕСЕНЬЕ», 7);
/*
*
* @param $dayOfWeek
* @return int День недели, где 1 — понедельник и так далее.
*/
функция findNextBusinessDay($dayOfWeek){
$nextBusinessDay = $dayOfWeek;
переключатель ($dayOfWeek) {
дело ПЯТНИЦА:
дело СУББОТА:
дело ВОСКРЕСЕНЬЕ:
$nextBusinessDay = ПОНЕДЕЛЬНИК;
перерыв;
по умолчанию:
$nextBusinessDay += 1;
перерыв;
}
вернуть $nextBusinessDay;
}
$день = ПЯТНИЦА;
$nextBusDay = findNextBusinessDay($day);
echo ("Следующий день:" . $nextBusDay . "n");
?>
Мы рекомендуем вам разбить большие условия на метод, а затем назвать метод именем, описывающим условие. Этот метод может улучшить читаемость кода и сделать условие конкретным, чтобы его можно было извлечь и даже повторно использовать. Также легко обновлять методы, если условия меняются. Поскольку метод имеет осмысленное имя, оно отражает назначение кода и облегчает его чтение.
по частям,
прежде чем продолжить программирование. Если продолжать программировать, одновременно решая насущную задачу, функция будет становиться все длиннее и длиннее. В долгосрочной перспективе это не проблема, но вам стоит не забыть вернуться и разбить его на более мелкие части.
Рефакторинг — хорошая идея, но вам следует выработать привычку писать более короткий и целенаправленный код. Короткие методы можно прочитать в одном окне, и они просты для понимания. Если метод слишком длинный, чтобы его можно было прочитать в одном окне, за ним становится трудно следовать, поскольку вы не можете быстро проследить всю идею от начала до конца.
При создании методов вы должны привыкнуть к тому, чтобы каждый метод выполнял только одну функцию. Это хорошая привычка, потому что: во-первых, если метод делает только одну вещь, его с большей вероятностью будут использовать повторно; во-вторых, такой метод легко протестировать; в-третьих, такой метод легко понять и изменить;
Плохая привычка: слишком длинные методы (выполняют слишком много действий)
В листинге 3 показана очень длинная функция, вызывающая множество проблем. Он делает много всего, поэтому недостаточно компактен. Его также легче читать, отлаживать и тестировать. Он выполняет итерацию по файлу, построение списка, присвоение значений каждому объекту, выполнение вычислений и многое другое.
Листинг 3. Вредная привычка: слишком длинная функция
<?php
function writeRssFeed($user)
{
//Получаем информацию о подключении к БД
// ищем предпочтения пользователя...
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
ИЛИ die(mysql_error());
// Запрос
$perfsQuery = sprintf("ВЫБЕРИТЕ max_stories ИЗ user_perfs ГДЕ user= '%s'",
mysql_real_escape_string($user));
$result = mysql_query($query, $link);
$max_stories = 25 // по умолчанию 25;
если ($row = mysql_fetch_assoc($result)) {
$max_stories = $row['max_stories'];
}
// идем за моими данными
$perfsQuery = sprintf("ВЫБРАТЬ * ИЗ историй WHERE post_date = '%s'",
mysql_real_escape_string());
$result = mysql_query($query, $link);
$feed = "<rss version="2.0">" .
"<канал>" .
«<title>My Great Feed</title>» .
«<ссылка> http://www.example.com/feed.xml </link>» .
«<description>Лучший корм в мире</description>» .
«<язык>en-us</language>» .
"<pubDate>Вторник, 20 октября 2008 г., 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Вторник, 20 октября 2008 г., 10:00:00 GMT</lastBuildDate>" .
«<docs> http://www.example.com/rss </docs>» .
"<generator>Генератор MyFeed</generator>" .
«<managingEditor> [email protected] </managingEditor>» .
«<webMaster> [email protected] </webMaster>» .
"<ttl>5</ttl>";
// создаем фид...
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 .= "<ссылка>" . $ссылка . "</ссылка>";
$feed .= "<описание>" . $description "</описание>";
$feed .= "<pubDate>" $date "</pubDate>";
$feed .= "<guid>" . $guid . "</guid>";
$feed .= "</item>";
}
$feed .= "</rss"
// записываем фид на сервер...
echo($feed);
}
?>Если вы напишете еще несколько таких методов, обслуживание станет настоящей проблемой.
Полезная привычка: список управляемых, специфичных для функций методов
4. Перепишите исходный метод в более компактный и читаемый метод. В этом примере длинный метод разбит на несколько коротких методов, и каждый короткий метод отвечает за что-то одно. Такой код очень полезен для будущего повторного использования и тестирования.
Листинг 4. Хорошая практика: простой в управлении подход с учетом особенностей функций
<?php
function createRssHeader()
{
верните "<rss version="2.0">" .
"<канал>" .
«<title>My Great Feed</title>» .
«<ссылка> http://www.example.com/feed.xml </link>» .
«<description>Лучший корм в мире</description>» .
«<язык>en-us</language>» .
"<pubDate>Вторник, 20 октября 2008 г., 10:00:00 GMT</pubDate>" .
"<lastBuildDate>Вторник, 20 октября 2008 г., 10:00:00 GMT</lastBuildDate>" .
«<docs> http://www.example.com/rss </docs>» .
"<generator>Генератор MyFeed</generator>" .
«<managingEditor> [email protected] </managingEditor>» .
«<webMaster> [email protected] </webMaster>» .
"<ttl>5</ttl>";
}
Функция createRssFooter()
{
return "</channel></rss>";
}
функция createRssItem($title, $link, $desc, $date, $guid)
{
$item .= "<item>";
$item .= "<title>" . $title .
$item .= "<ссылка>" . $ссылка . "</ссылка>";
$item .= "<описание>" . $description "</описание>";
$item .= "<Дата публикации>" . $date . "</Дата публикации>";
$item .= "<guid>" . $guid . "</guid>";
$item .= "</item>";
вернуть $предмет;
}
функция getUserMaxStories($db_link, $default)
{
$perfsQuery = sprintf("ВЫБЕРИТЕ max_stories ИЗ user_perfs ГДЕ user= '%s'",
mysql_real_escape_string($user));
$result = mysql_query($perfsQuery, $db_link);
$max_stories = $default;
если ($row = mysql_fetch_assoc($result)) {
$max_stories = $row['max_stories'];
}
вернуть $max_stories;
}
функция writeRssFeed($user)
{
//Получаем информацию о подключении к БД
$settings = parse_ini_file("rss_server.ini");
// ищем предпочтения пользователя...
$link = mysql_connect($settings['db_host'], $settings['user'],
$settings['password']) ИЛИ die(mysql_error());
$max_stories = getUserMaxStories($link, 25);
// идем за моими данными
$newsQuery = sprintf("ВЫБРАТЬ * ИЗ историй WHERE post_date = '%s'",
mysql_real_escape_string(время()));
$result = mysql_query($newsQuery, $link
$feed = createRssHeader()
);
$я = 0;
// создаем фид...
while ($row = mysql_fetch_assoc($result)) {
если ($i <$max_stories) {
$title = $row['title'];
$ссылка = $строка['ссылка'];
$description = $row['description'];
$date = $row['date'];
$guid = $row['guid'];
$feed .= createRssItem($title, $link, $description, $date, $guid);
$я++;
} еще {
перерыв;
}
}
mysql_close($link);
$feed .= createRssFooter();
// записываем канал на сервер...
эхо ($ корма);
}
?> Существуют также ограничения на разделение длинных методов на короткие, и чрезмерное разделение будет контрпродуктивным. Поэтому не злоупотребляйте этой хорошей привычкой. Разбиение кода на большие куски может затруднить чтение так же, как и не разбиение длинного кода.
Добавление комментариев к вашему коду
Добавление хороших комментариев к вашему коду иногда может показаться таким же трудным, как и написание кода. Нелегко понять, что аннотировать, потому что мы часто склонны аннотировать то, что код делает в данный момент. Рекомендуется прокомментировать назначение вашего кода. В менее очевидном блоке заголовка функции читателю сообщается о входных и выходных данных метода, а также об исходной цели метода.
Обычно комментируют то, что в данный момент делает код, но в этом нет необходимости. Если код сложен и вам нужно закомментировать то, что он делает в данный момент, это будет означать, что вам следует переписать код, чтобы его было легче понять. Научитесь использовать хорошие имена и более короткие методы, чтобы сделать ваш код более читабельным, не добавляя комментариев, объясняющих их назначение.
Плохая привычка: функции чрезмерного или недостаточного комментирования.
Комментарии в листинге 5 лишь сообщают читателю, что делает код — он проходит цикл или добавляет число. Но он игнорирует, почему он выполняет свою текущую работу. В результате люди, поддерживающие код, не знают, можно ли безопасно изменить код (без внесения новых дефектов).
Листинг 5. Вредная привычка: слишком много или недостаточно комментариев к функциям
<?php
класс ResultMessage
{
частная $серьезность;
личное $сообщение;
публичная функция __construct($sev, $msg)
{
$this->severity = $sev;
$this->сообщение = $msg;
}
публичная функция getSeverity()
{
верните $this->severity;
}
публичная функция setSeverity($severity)
{
$this->severity = $severity;
}
публичная функция getMessage()
{
вернуть $this->сообщение;
}
общедоступная функция setMessage($msg)
{
$this->message = $msg;
}
}
функция cntMsgs($messages)
{
$п = 0;
/* перебираем сообщения... */
foreach($messages as $m) {
if ($m->getSeverity() == 'Ошибка') {
$n++; // добавляем единицу к результату;
}
}
вернуть $n;
}
$messages = array(new ResultMessage("Ошибка", "Это ошибка!"),
new ResultMessage("Предупреждение", "Это предупреждение!"),
new ResultMessage("Ошибка", "Это еще одна ошибка!"));
$errs = cntMsgs($messages);
echo("В result.n есть ошибки " . $errs ."
?>
Хорошая практика: аннотированные функции и классы
Комментарии в листинге 6 рассказывают читателю о классах и методах. цель. Этот комментарий объясняет, почему код выполняет свою текущую работу, что может быть полезно при обслуживании кода в будущем. Код, возможно, придется модифицировать по мере изменения условий, но внести изменения легко, если легко понять цель кода.
Листинг 6. Хорошая практика: аннотированные функции и классы
<?php
/**
* Класс ResultMessage содержит сообщение, которое может быть возвращено.
* в результате процесса Сообщение имеет серьезность и
* сообщение.
*
* @author нехорошо
*
*/
класс ResultMessage
{
частная $серьезность;
личное $сообщение;
/**
* Конструктор для ResultMessage, который позволяет вам назначать
* серьезность и сообщение.
* @param $sev См. {@link getSeverity()}.
* @param $msg
* @return неизвестный_тип
*/
публичная функция __construct($sev, $msg)
{
$this->severity = $sev;
$this->сообщение = $msg;
}
/**
* Возвращает серьезность сообщения. Должна быть равна единице.
* «Информация», «Предупреждение» или «Ошибка».
* @return string Серьезность сообщения
*/
публичная функция getSeverity()
{
верните $this->severity;
}
/**
* Устанавливает серьезность сообщения
* @param $severity
* @return void
*/
публичная функция setSeverity($severity)
{
$this->severity = $severity;
}
публичная функция getMessage()
{
вернуть $this->сообщение;
}
общедоступная функция setMessage($msg)
{
$this->message = $msg;
}
}
/*
* Подсчитывает сообщения с заданной серьезностью в массиве.
* сообщений.
*
* @param $messages Массив ResultMessage
* @return int Количество сообщений с уровнем серьезности «Ошибка».
*/
функция countErrors($messages)
{
$ matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Ошибка") {
$matchingCount++;
}
}
вернуть $matchingCount;
}
$messages = array(new ResultMessage("Ошибка", "Это ошибка!"),
new ResultMessage("Предупреждение", "Это предупреждение!"),
new ResultMessage("Ошибка", "Это еще одна ошибка!"));
$errs = countErrors($messages);
echo("В результате есть ошибки " . $errs. ""
?>
Обработка ошибок
Как правило, если вы хотите писать надежные приложения, следуйте правилу 80/20 для обработки ошибок: 80% вашего кода используется для обработки исключений и проверки, а 20% вашего кода используется для обработки ошибок. реальная работа. Это часто делается при кодировании базовой логики (счастливого пути) программы. Это означает написание кода, который работает «под капотом», что все данные доступны и все условия соответствуют ожиданиям. Такой код может быть хрупким в течение жизненного цикла приложения. С другой стороны, написание кода для условий, с которыми вы никогда раньше не сталкивались, занимает много времени.
Эта привычка требует от вас писать достаточно кода для обработки ошибок, а не писать код для обработки всех ошибок, чтобы код никогда не завершался.
Вредные привычки: отсутствие обработки ошибок Код
в листинге 7 демонстрирует две вредные привычки. Во-первых, входные параметры не проверяются, хотя известно, что параметры в определенных состояниях будут вызывать исключения в методе. Во-вторых, код вызывает метод, который может генерировать исключение, но не обрабатывает его. Когда возникает проблема, автор кода или человек, обслуживающий код, могут только догадываться об источнике проблемы.
Листинг 7. Плохая привычка: не обрабатывать ошибки
<?php
// Получаем фактическое имя
функция ConvertDayOfWeekToName($day)
{
$dayNames = массив(
"Воскресенье",
"Понедельник",
"Вторник",
"Среда",
"Четверг",
"Пятница",
"Суббота");
вернуть $dayNames[$day];
}
echo("Название нулевого дня: " . ConvertDayOfWeekToName(0) . "n");
echo("Название 10-го дня: " . ConvertDayOfWeekToName(10) . "n");
echo("Название "оранжевого" дня: " . ConvertDayOfWeekToName('orange') . "n")
;
Передовая практика: обработка исключений.
В листинге 8 показано, как создавать и обрабатывать исключения. Дополнительная обработка ошибок не только делает код более надежным, но и улучшает его читаемость, упрощая его понимание. Способ обработки исключений является хорошим показателем намерений первоначального автора при написании метода.
Листинг 8. Хорошая практика: обработка исключений
<?php
/**
* Это исключение выдается, если день недели недействителен.
* @author нехорошо
*
*/
class InvalidDayOfWeekException расширяет Exception { }
class InvalidDayFormatException расширяет Exception { }
/**
* Получает название дня по дню недели.
* вернуть ошибку, если предоставленное значение выходит за пределы диапазона.
*
* @param $день
* @return неизвестный_тип
*/
функция ConvertDayOfWeekToName($day)
{
если (! is_numeric($day)) {
throw new InvalidDayFormatException('Значение '' . $day . '' представляет собой ' .
'неверный формат дня недели.');
}
if (($day > 6) || ($day < 0)) {
throw new InvalidDayOfWeekException('Номер дня '' . $day . '' представляет собой ' .
'недопустимый день недели. Ожидается 0-6.');
}
$dayNames = массив(
"Воскресенье",
"Понедельник",
"Вторник",
"Среда",
"Четверг",
"Пятница",
"Суббота");
вернуть $dayNames[$day];
}
echo("Название нулевого дня: " . ConvertDayOfWeekToName(0) . "n")
;
echo("Название 10-го дня: " . ConvertDayOfWeekToName(10) . "n");
} catch (InvalidDayOfWeekException $e) {
echo ("Обнаружена ошибка при попытке преобразовать значение: " . $e->getMessage() . "n");
}
пытаться {
echo("Название "оранжевого" дня: " . ConvertDayOfWeekToName('orange') . "n");
} catch (InvalidDayFormatException $e) {
echo ("Обнаружена ошибка при попытке преобразовать значение: " . $e->getMessage() . "n");
}
?>
Хотя проверка параметров является подтверждением: если вам требуется, чтобы параметры находились в определенном состоянии, это будет полезно для людей, использующих этот метод — вам следует проверять их и генерировать значимые исключения:
◆ Обрабатывайте исключения как можно точнее. Проблемы возникающие тесно связаны между собой.
◆Специальная обработка каждого исключения.
Не используйте копирование и вставку.
Вы можете скопировать и вставить код из любого места в свой редактор кода, но у этого есть свои плюсы и минусы. Хорошо, что копирование кода из примера или шаблона позволяет избежать многих ошибок. Обратной стороной является то, что это легко приводит к появлению множества похожих методов программирования.
Будьте осторожны, не копируйте и не вставляйте код из одной части приложения в другую. Если вы так думаете, избавьтесь от этой вредной привычки и подумайте о том, чтобы переписать этот код, чтобы его можно было использовать повторно. Вообще говоря, размещение кода в одном месте облегчает его дальнейшее сопровождение, поскольку его нужно изменить только в одном месте.
Вредные привычки. В похожих фрагментах кода
в листинге 9 показано несколько почти идентичных методов, но с разными значениями. Существуют инструменты, которые могут помочь найти скопированный и вставленный код (см. Ресурсы).
Листинг 9. Вредные привычки: похожие фрагменты кода
<?php
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Ошибка».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countErrors($messages)
{
$ matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Ошибка") {
$matchingCount++;
}
}
вернуть $matchingCount;
}
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Предупреждение».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countWarnings($messages)
{
$ matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Внимание") {
$matchingCount++;
}
}
вернуть $matchingCount;
}
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Информация».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countInformation($messages)
{
$ matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == "Информация") {
$matchingCount++;
}
}
вернуть $matchingCount;
}
$messages = array(new ResultMessage("Ошибка", "Это ошибка!"),
new ResultMessage("Предупреждение", "Это предупреждение!"),
new ResultMessage("Ошибка", "Это еще одна ошибка!"));
$errs = countErrors($messages);
echo("В результате.n есть ошибки " . $errs . ");
?>
Передовая практика: многократно используемые функции с параметрами
В листинге 10 показан измененный код, который помещает скопированный код в метод. Другой метод также был изменен, и теперь он делегирует задачи новому методу. Создание общего подхода требует времени на проектирование, и это позволяет вам остановиться и подумать, а не инстинктивно копировать и вставлять. Но время, потраченное на общий подход, окупится, когда потребуются изменения.
Листинг 10. Хорошая практика: повторно используемые функции с параметрами
<?php
/*
* Подсчитывает сообщения с заданной серьезностью в массиве.
* сообщений.
*
* @param $messages Массив ResultMessage
* @return int Количество сообщений, соответствующих $withSeverity
*/
функция countMessages($messages, $withSeverity)
{
$ matchingCount = 0;
foreach($messages as $m) {
if ($m->getSeverity() == $withSeverity) {
$matchingCount++;
}
}
вернуть $matchingCount;
}
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Ошибка».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countErrors($messages)
{
return countMessages($messages, "Ошибки");
}
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Предупреждение».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countWarnings($messages)
{
return countMessages($messages, "Предупреждение");
}
/**
* Подсчитывает количество сообщений, найденных в массиве
* ResultMessage со значением getSeverity() «Предупреждение».
*
* @param $messages Массив ResultMessage
* @return неизвестный_тип
*/
функция countInformation($messages)
{
return countMessages($messages, "Информация");
}
$messages = array(new ResultMessage("Ошибка", "Это ошибка!"),
new ResultMessage("Предупреждение", "Это предупреждение!"),
new ResultMessage("Ошибка", "Это еще одна ошибка!"));
$errs = countErrors($messages);
echo("В результате.n есть ошибки " . $errs . ""
?>
Заключение
Если вы при написании PHP-кода выработаете полезные привычки, описанные в этой статье, вы это сделаете. уметь создавать код, который легко читать, понимать и поддерживать. Построенный таким образом поддерживаемый код снизит риск отладки, исправления и расширения кода.
Использование хороших имен и более коротких методов улучшает читаемость кода. Цель комментирования кода — облегчить понимание и расширение кода. Правильная обработка ошибок делает ваш код более надежным. Наконец, прекратите использовать копирование и вставку, чтобы сохранить чистоту кода и улучшить возможность повторного использования.