Пять моих «граблей» в разработке на PHP

от автора

Здравствуйте, уважаемые пользователи! В этом посте хотел бы поделиться своим личным опытом «наступания на грабли» во время разработки веб-приложений на языке программирования PHP. Текст будет интересен тем, кто хочет посмотреть на путь девелопера от «зеленого самоучки» до «профессионального разработчика», а также начинающим программистам, которые не против узнать о том, «как не нужно делать» и почему. Возможно даже кто-то вспомнит себя и улыбнётся. Возможно, кто-то просто улыбнётся с моего старого кода. В любом случае буду рад увидеть вашу улыбку.

image

Все мое ознакомление с веб-разработкой начиналось в далеком 2009-м году с распечатанных непонятных и сложных справочников и руководств, а также ковыряния кода (очень плохого, кстати) open source CMS. Позже я начал использовать ООП и заботиться о «правильности», а ещё позже — замечательный фреймворк Yii, поэтому весь «хороший» код в посте будет демонстрироваться именно с использованием этого фреймворка.

1. Дублирование кода. Сейчас, смотря на свой код минувшых лет, я понимаю, что это были действительно ужасные времена. У меня дублировалось практически всё. Функции писались редко, а один и тот же код можно было увидеть в трех-четырех (ато и больше) местах. Почему я так делал? Ну естественно потому что я был неопытным. Это раз. И потому что считал (глупо считал), что написание функции — это трата времени и что гораздо проще просто покопировать одно и тоже несколько раз.

Что было раньше:

$sql = 'SELECT `id` FROM `days` WHERE `sta`=1'; $r=mysql_query($sql,$conn); $row=mysql_fetch_row($r);  $curday=$row[0];   if (($curday>=3 && $curday<=15) || ($curday>=45 && $curday<=55) || ($curday>=90 && $curday<=105)) 	{            $on_off=1; 	}else{            $on_off=0; 	} 

Что есть сейчас:

            $curDay = BasicFunctions::getCurrentDay();             $transferStatus = BasicFunctions::getTransferStatus($curDay);              if ($transferStatus == 1) {                ...             } 

Позже я понял, зачем делать «хорошо»:

Самая важная причина создания метода — снижение сложности программы. Методы создаются для того, чтобы можно было скрыть информацию и не думать о ней. Другие причины создания методов — минимизация объема кода, облегчение сопровождения программы и снижение числа ошибок.

Ну и конечно же, методы позволяют выполнять оптимизацию кода в одном месте, а не в нескольких. Они облегчают профилирование кода, направленное на определение неэффективных фрагментов. Если код централизован в методе, его оптимизация повысит быстродействие всех фрагментов, в которых этот метод вызывается как непосредственно, так и косвенно.

2. Пересекание PHP и HTML. Да, я не использовал патернов проектирования. Да, я не использовал популярного MVC. И это было второй моей фатальной ошибкой. Почему я так делал? Я почему-то не думал о том, что код когда-то может быть переписан/дописан/изменен. Всё «хардкорилось» чисто с расчетом на сиюминутную выгоду.

Что было раньше:

echo '<br /><br /><center><img class="tTip" src="img/cap.jpeg" alt="Капитан" title="Капитан"> <b>Капитан</b></center>';                $sql = 'SELECT * FROM `capitans` WHERE `club`='.$_SESSION['my_club'];                $r=mysql_query($sql,$conn);                $row=mysql_fetch_row($r);    $idp=$row[2];  if (!isset($row[2]) || $row[2]=="")    {    echo '<center>Капитан команды не назначен</center><br>';    }else{                $sql = 'SELECT * FROM `players` WHERE `id`='.$idp;                $r=mysql_query($sql,$conn); 	       $row=mysql_fetch_row($r);       ....  } 

Что есть сейчас:

$capitan = Capitans::model()->findByAttributes(array('club' => $user->club));              $this->render('team', array(                 ...                 'capitan' => $capitan,                 ...             ));  ----------------------------------------  <?php if ($capitan == $item->pl_id) {  ?>    <i class="cap" title="Капитан" alt="Капитан"></i> <?php } ?> 

Позже я понял, зачем делать «хорошо»:

Использования паттерна проектирования (при веб-разработке чаще всего это MVC) снижает сложность разработки за счёт готовых абстракций для решения целого ряда проблем. Например, логические части приложения разделяются на автономные области. Например, в том же MVC модель данных, пользовательский интерфейс и взаимодействие с пользователем разделены на три отдельных компонента. Зачем? Затем, чтобы модификация одного из компонентов оказывала минимальное воздействие на остальные.

3. Не использование фреймворка. Я года два писал всё сам и не использовал фреймворков. Я считал, что это что-то очень сложное и на изучение «этого» у меня нет времени. Есть люди, которые принципиально не используют фреймворки, например, потому что они считают, что фреймворк — это open source, который доступен каждому (т. е. каждый может просмотреть его код и найти узкие места). Эти люди, которые так считают, пишут свои фреймворки, которые используют в подальших проектах. Лично я считаю, что сейчас есть TOP-3 (или TOP-5) тех фреймворков, которые проверены на популярных проектах и отточены до максимума, поэтому резон писать что-то свое стремится к нулю. Если вы так не считаете, проголосуйте в конце поста.

Что было раньше (авторизация):

if (!isset($_POST['login']) || strlen($_POST['login'])<3) {     $errorsArray[] = 'Не введён логин или он слишком короткий';     $sum=$sum+1; } if (!isset($_POST['pass']) || strlen($_POST['pass'])<3) {     $errorsArray[] = 'Не введён пароль или он слишком короткий';     $sum=$sum+1; } if (!preg_match("/^([a-zA-Z0-9]+)$/", $_POST['login'])) {     $errorsArray[] = 'В поле "логин" присутствуют недопустимые символы';     $sum=$sum+1; } if (!preg_match("/^([a-zA-Z0-9]+)$/", $_POST['pass'])) {     $errorsArray[] = 'В поле "пароль" присутствуют недопустимые символы';     $sum=$sum+1; }  $sql = 'SELECT * FROM `users` WHERE `login`="'.$_POST['login'].'"'; $r=mysql_query($sql,$conn); $row=mysql_fetch_row($r);  if ($row[1]!==$_POST['login'] || $row[2]!==md5($_POST['pass'])) {     $errorsArray[] = 'Неверный логин или пароль';     $sum=$sum+1; } 

Что есть сейчас (авторизация):

	public function actionLogin() 	{ 		$model=new LoginForm;  		if(isset($_POST['LoginForm'])) 		{ 			$model->attributes=$_POST['LoginForm']; 			// validate user input and redirect to the previous page if valid 			if($model->validate() && $model->login()) 				$this->redirect(Yii::app()->user->returnUrl); 		} 		// render form 		$this->render('login',array('model'=>$model)); 	} 

Позже я понял, зачем нужно использовать фреймворк:

Любой фреймворк — это, в первую очередь, набор уже готовых к использованию стандартов, которые используют, тратя намного меньше времени, разработчики. Кроме этого, вокруг популярных open sourse фреймворков собирается серьезное сообщество разработчиков. Что это значит? А это значит то, что будет легко подключить или заменить человека в команде работающей над проектом. Плюс, комьюнити создает массу готовых сторонних решений.

4. Классы? Не, не слышал. Классы не использовались вообще. Хотя, при описанных выше «ляпах», о каких классах может идти речь 🙂

Что было раньше:

include_once("inc.php"); include_once("head.php"); include_once("system.php");  if (isset($_SESSION['login']) && isset($_SESSION['password']))    {    if (!isset($_GET['id']) || $_GET['id']=="")      {         ...       }    } 

Что есть сейчас (класс с набором базовых функций, которые используются по всему приложению):

/**  * Class BasicFunctions  * Same functions for all controllers  */ class BasicFunctions {    ...      /**      * Get info about last registered users      * @ param type $limit - limit      * @ return array - users      */     public static function getLastRegUsers ($limit) {            $criteria=new CDbCriteria;            $criteria->limit = $limit;            $criteria->order = 'user_id DESC';            $users = Users::model()->findAll($criteria);             return $users;             }     ...  } 

Позже я понял, зачем делать «хорошо»:

Самая важная причина создания класса — это снижение сложности. Класс создается для сокрытия информации, чтобы о ней можно было не думать (да, точно так же не думать, как и в случае с методом). Вы сможете забыть о деталях и использовать класс, не зная о его внутренней работе. Другие причины создания классов — минимизация объема кода, облегчение сопровождения программы и снижение числа ошибок (да, точно так же, как и в случае с методом).

5. Не использование LIMIT’ов, JOIN’ов, запросы в циклах. Если бы сейчас существавала инквизиция, то на огонь попадали бы все начинающие программисты, которые занимаются такой ересью 🙂 Это, наверное, самый смертный грех программиста. Такими действиями я просто убивал быстродействие своих приложений. А, как вы знаете, быстродействие — это один из основных факторов, которые влияют на то, вернется ли второй раз к вам пользователь или нет.

Что было раньше (случайный код):

              $sqlo = 'SELECT `id`, `pos` FROM `players`';                $ro=mysql_query($sqlo); 	       while($rowo=mysql_fetch_row($ro)) 		{ if ((int)$rowo[0]==(int)$ex2[0]){  $r_tmp_2 = mysql_query("SELECT `pos` FROM `pos` WHERE `id`=".$rowo[1].""); $row_tmp_2=mysql_fetch_row($r_tmp_2);              ...  				} 		} 

Что есть сейчас (случайный код):

            if ($addNewBuild = Yii::app()->request->getQuery('addNewBuild')) {                 $building = Buildings::model()->findByPk($addNewBuild); // Ищем первую запись по Primary Key и возвращаем её, если она найдена                 if ($building) {                    ...                 }else{                   ...                 }            } 

Позже я понял, зачем делать «хорошо»:

Вы должны заботиться о быстродействии своих приложений. Вы должны заботиться о правильности написания SQL-запросов. Именно SQL-запросы составляют большую часть приложения и именно они в основном влияют на быстродействие. Использование LIMIT’ов помогает избежать проходов по всем записям таблицы, а использование JOIN’ов помогает избежать циклических запросов.

Вот такая вот история. Всем спасибо за интерес, внимание, и улыбки (надеюсь, они у вас были). Если вам этот пост понравился, в следующем расскажу о том, как я «вышел» на фреймворки и на Yii в частности.

P. S. Про именование переменных уже не стал писать (вы наверное заметили $rowo, $r_tmp_2, $sqlo), как нибудь в другой раз обязательно напишу.

Как вы относитесь к использованию open sourse frameworks?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Никто ещё не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи http://habrahabr.ru/post/208838/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *