» Главная
eXcode.ru » Статьи » PHP » Трюки
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 11







TDD: Рефакторинг приложения




Рефакторинг приложения

Отделяем бизнес логику от презентационной

Пожалуй, это самый важный первый шаг, который стоит сделать. Для этого несколько модифицируем index.php, выделив из него разметку в отдельный файл /templates/feedback.html.

index.php

<?php
ob_start();
 
include_once('db.php');
 
$conn = mysql_connect($db_host, $db_user, $db_password);
 
if($conn === FALSE){
    die('db connect error: ' . mysql_error());
}
 
if(!mysql_select_db($db_name, $conn)){
    die('can not use db: ' . mysql_error());
}
 
if(isset($_POST['submit'])) {
    $name = mysql_escape_string($_POST['name']);
    $email = mysql_escape_string($_POST['email']);
    $message = mysql_escape_string($_POST['message']);
    $time = time();
 
    $sql = "INSERT INTO feedback (name, email, message, time) VALUES ('$name', '$email', '$message', '$time')";
 
    $result = mysql_query($sql, $conn);
    if(!$result){
        die('invalid query: ' . mysql_error());
    }
}
 
$limit = 3;
$offset = isset($_GET['offset']) ? $_GET['offset'] : 0;
 
$sql = "SELECT * FROM feedback ORDER BY time DESC LIMIT " . ($offset * $limit) . ", {$limit}";
$fetch_result = mysql_query($sql, $conn);
if(!$fetch_result){
    die('invalid query: ' . mysql_error());
}
 
$sql = "SELECT COUNT(*) as counter FROM feedback";
$count_result = mysql_query($sql, $conn);
if(!$count_result){
    die('invalid query: ' . mysql_error());
}
$row = mysql_fetch_assoc($count_result);
$total = (int)$row['counter'];
 
include_once('templates/feedback.html');
 
ob_end_flush();
?>

templates/feedback.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<link rel=stylesheet type='text/css' href='styles/main.css'>
<script language="JavaScript" type="text/javascript" src="js/form.js"></script>
</head>
<body>
<table width="100%" style="height:100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="10%" style="background-color:#7F1A22">
</td>
<td width="90%" style="padding:5px 10px 5px 10px" valign="top">
<h1>Обратная связь</h1>
<p>
  Если у вас есть пожелания или вопросы к сотрудникам нашей компании,<br>
  пожалуйста, заполните поля формы.<br>
</p>
<form action="index.php" method="post" onsubmit="return submit_form(this);">
<table>
  <tr>
    <td align="right">
      Ваше имя:
    </td>
    <td>
      <input name="name" value="" type="text">
    </td>
 </tr>
  <tr>
    <td align="right">
      Email:
    </td>
    <td>
      <input name="email" value="" type="text">
    </td>
 </tr>
    <tr>
     <td align="right">
       Текст вопроса:
     </td>
     <td>
       <textarea name="message" cols="50" rows="4"></textarea>
     </td>
    </tr>
    <tr>
    <td>
    </td>
    <td>
        <input value="Отправить" name="submit" type="submit">
    </td>
    </tr>
</table>
</form>
<?php if($offset > 0) :?><b><a href="?offset=<?=($offset-1)?>">&lt;</a></b><?php endif; ?>
<?php if($total > 0) :?><?=($offset*$limit)+1?> - <?=(($offset+1)*$limit > $total)? $total : ($offset+1)*$limit ?><?php endif; ?>
<?php if(($offset+1)*$limit < $total) :?><b><a href="?offset=<?=($offset+1)?>">&gt;</a></b><?php endif; ?>
<?php
while ($row = mysql_fetch_assoc($fetch_result)) {
?>
<hr/>
<b>Автор:</b> <a href="mailto:<?=htmlspecialchars($row['email']);?>"><?=htmlspecialchars($row['name']);?></a><br/>
<b>Сообщение:</b> <?=htmlspecialchars($row['message']);?><br/>
<b>Время:</b> <?=strftime("%m/%d/%y %H:%M:%S", $row['time'])?><br/>
<?php } ?>
</td>
</tr>
</table>
</body>
</html>

До идела еще далеко, но читается уже намного лучше. Удостоверившись в том, что все функциональные тесты срабатывают, продолжаем дальше.

Используем WACT

WACT предоставляет мощные средства для отделения презентационной и бизнес логики. Помимо гибкой шаблонной системы в WACT присутствуют также инструменты для абстрагирования работы с БД. Т.к. эти инструменты очень гибко интегрируюся с шаблонной системой, имеет смысл остановить на них выбор.

WACT требует наличие config.ini файла, в котором описываются глобальные конфигурационные настройки приложения. Перенесем данные из db.php в config.ini.

[templates]
forcecompile = TRUE

[database]
driver = mysql
mysql.database = "feedback"
mysql.user = "root"
mysql.password = "test"
mysql.host = "localhost" 

Создадим также файл tests/config.ini, в котором мы будем хранить настройки для тестов.

[templates]
forcecompile = TRUE

[database]
driver = mysql
mysql.database = "feedback-web-tests"
mysql.user = "root"
mysql.password = "test"
mysql.host = "localhost" 

Заставим WACT также пользоваться этим конфигурационным файлом при вызове из тестов. Для этого добавим следующую строку в /tests/setup.php:

<?php
define('WACT_CONFIG_DIRECTORY', dirname(__FILE__) . '/'); 
?>

Нам необходимо заменять config.ini на /tests/config.ini на время выполнения тестов, как мы это делали с db.php, для этого несколько изменим фикстуру:

<?php
class AcceptanceTestOfFeedbackProject extends WebTestCase {
    function setUp() {
        DBC :: execute('DELETE FROM feedback');
        $this->_switchToWebTestingConfig();
    }
 
    function tearDown() {
        $this->_switchToProductionConfig();
    } 
 
    function _switchToWebTestingConfig() {
        $project_dir = dirname(__FILE__) . '/../';
        $tests_dir = dirname(__FILE__) . '/';
 
        if(!file_exists($project_dir . 'config.ini~')) {
            rename($project_dir . 'config.ini', $project_dir . 'config.ini~');
        }
        copy($tests_dir . 'config.ini', $project_dir . 'config.ini');
    }
 
    function _switchToProductionConfig() {
        $project_dir = dirname(__FILE__) . '/../';
        if(file_exists($project_dir . 'config.ini~')) {
            unlink($project_dir . 'config.ini');
            rename($project_dir . 'config.ini~', $project_dir . 'config.ini');
        }
    } 
    [...]
?>

Имеет смысл также пользоваться в тесте средствами WACT для работы с БД. Как можно видеть, вызов DBC :: execute('DELETE FROM feedback') - пришел на смену жесткой привязке к mysql_ функциям.

Все готово к тому, чтобы полностью отделить бизнес логику от презентационной. Начинаем с index.php:

<?php
ob_start();
 
require_once(dirname(__FILE__) . '/external/wact/framework/common.inc.php');
require_once(WACT_ROOT . '/db/db.inc.php');
require_once(WACT_ROOT . '/template/template.inc.php');
 
function &getList(&$pager) {
    return DBC::NewPagedRecordSet('SELECT * FROM feedback ORDER BY time DESC', $pager);
}
 
function insertFeedback($arr) {
    $dataspace = new DataSpace();
    $dataspace->import($arr);
    $record =& DBC::NewRecord($dataspace);
    return $record->insert('feedback', array('name', 'email', 'message', 'time'));
}
 
if(isset($_POST['submit'])) {
    insertFeedback(array('name' => $_POST['name'],
                 'email' => $_POST['email'],
                 'message' => $_POST['message'],
                 'time' => time()));
}
 
$page = new Template('/feedback.html');
$pager =& $page->getChild('pager');
 
$feedback =& $page->findChild('feedback');
$feedback->registerDataSet(getList($pager));
 
$page->display();
 
ob_end_flush();
?>

WACT ищет по-умолчанию шаблоны в директории /templates/source, модифицируем и перенесем feedback.html.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<link rel=stylesheet type='text/css' href='styles/main.css'>
<script language="JavaScript" type="text/javascript" src="js/form.js"></script>
</head>
<body>
<table width="100%" style="height:100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="10%" style="background-color:#7F1A22">
</td>
<td width="90%" style="padding:5px 10px 5px 10px" valign="top">
<h1>Обратная связь</h1>
<p>
  Если у вас есть пожелания или вопросы к сотрудникам нашей компании,<br>
  пожалуйста, заполните поля формы.<br>
</p>
<form action="index.php" method="post" onsubmit="return submit_form(this);">
<table>
  <tr>
    <td align="right">
      Ваше имя:
    </td>
    <td>
      <input name="name" value="" type="text">
    </td>
 </tr>
  <tr>
    <td align="right">
      Email:
    </td>
    <td>
      <input name="email" value="" type="text">
    </td>
 </tr>
    <tr>
     <td align="right">
       Текст вопроса:
     </td>
     <td>
       <textarea name="message" cols="50" rows="4"></textarea>
     </td>
    </tr>
    <tr>
    <td>
    </td>
    <td>
        <input value="Отправить" name="submit" type="submit">
    </td>
    </tr>
</table>
</form>
<list:LIST id="feedback">
<page:navigator id="pager" items="3">
Страница: {$PageNumber} из {$TotalPages}
    <page:first>&lt;&lt;</page:first> <page:prev>&lt;</page:prev>
    <page:list>
        <page:number>
        <page:elipses>...</page:elipses>
        <page:separator> </page:separator>
    </page:list>
    <page:next>&gt;</page:next> <page:last>&gt;&gt;</page:last>
</page:navigator>
<list:ITEM>
<hr>
<b>Автор:</b> <a href="mailto:{$email}">{$name}</a><br>
<b>Сообщение:</b> {$message}<br>
<b>Время:</b> {$time|date:"H:i:s m/d/Y"}<br>
</list:ITEM>
</list:LIST>
</td>
</tr>
</table>
</body>
</html>

WACT предоставляет набор компонентов, позволяющих заметно облегчить жизнь верстальщика. При помощи <list:LIST> компонента организуется итерация по сообщениям в шаблоне. <page:navigator> компонент берет полностью на себя всю рутину по организации и выводу пейджера. При этом содержимое index.php и feedback.html заметно упростилось и приобрело более логический вид.

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

Далее - Шаг третий - внедряем паттерн ActiveRecord.

К началу статьи





Добавил: PIXELДата публикации: 2008-03-05 08:58:31
Рейтинг статьи:4.00 [Голосов 1]Кол-во просмотров: 13935

Комментарии читателей

Всего комментариев: 6

2012-02-22 19:09:56
ABSOMSBAW
<a href=http://www.formspring.me/JuliannMacivor/q/237576617247913089>viagra gratuit</a> - <a href=http://www.formspring.me/JuliannMacivor/q/237576617247913089>viagra prix</a> , http://www.formspring.me/JuliannMacivor/q/237576617247913089 acheter viagra france
<a href=http://www.formspring.me/TrustedHealth/q/175726032479885835>Buy Gabapentin Online</a> - <a href=http://www.formspring.me/TrustedHealth/q/175726032479885835>cheap gabapentin</a> , http://www.formspring.me/TrustedHealth/q/175726032479885835 gabapentin 100mg
<a href=http://www.formspring.me/SupervisorHere/q/176760472270299724>silagra 50mg</a> - <a href=http://www.formspring.me/SupervisorHere/q/176760472270299724>Buy Silagra</a> , http://www.formspring.me/SupervisorHere/q/176760472270299724 sildenafil citrate uk
<a href=http://www.formspring.me/RobVongsakda/q/179246124991799604>Misoprostol 200Mcg</a> - <a href=http://www.formspring.me/RobVongsakda/q/179246124991799604>misoprostol 200 mcg cheap</a> , http://www.formspring.me/RobVongsakda/q/179246124991799604 misoprostol 200 mcg cheap
<a href=http://www.formspring.me/JohnKreisher/q/238195109374465842>cialis generico 5mg</a> - <a href=http://www.formspring.me/JohnKreisher/q/238195109374465842>cialis in farmacia</a> , http://www.formspring.me/JohnKreisher/q/238195109374465842 cialis in farmacia
<a href=http://www.formspring.me/UncleBobHere/q/176753643024837028>Buy Cipro Online no prescription</a> - <a href=http://www.formspring.me/UncleBobHere/q/176753643024837028>Buy Cipro Online</a> , http://www.formspring.me/UncleBobHere/q/176753643024837028 Buy Ciprofloxacin no prescription
<a href=http://www.formspring.me/HipolitoGoletz/q/178849007907411130>buy cytotec online</a> - <a href=http://www.formspring.me/HipolitoGoletz/q/178849007907411130>Cytotec Abortion</a> , http://www.formspring.me/HipolitoGoletz/q/178849007907411130 Cytotec Abortion
<a href=http://www.formspring.me/TakishaLamia/q/242200307973492486>singulair cost</a> - <a href=http://www.formspring.me/TakishaLamia/q/242200307973492486>Singulair Cost Without Insurance</a> , http://www.formspring.me/TakishaLamia/q/242200307973492486 Singulair Cost
<a href=http://www.formspring.me/ShonnaPraino/q/178852499426408726>Zithromax</a> - <a href=http://www.formspring.me/ShonnaPraino/q/178852499426408726>zithromax 250mg</a> , http://www.formspring.me/ShonnaPraino/q/178852499426408726 Zithromax Single Dose
<a href=http://www.formspring.me/EmmalineMacke/q/237584345991218358>kamagra acheter</a> - <a href=http://www.formspring.me/EmmalineMacke/q/237584345991218358>acheter du kamagra</a> , http://www.formspring.me/EmmalineMacke/q/237584345991218358 kamagra achat
<a href=http://kvartira-na-sutki-minsk.ru/>Квартира на сутки в Минске</a> , ZTKYZYZZZZKY, <a href="http://kvartira-na-sutki-minsk.ru/">Квартира на сутки в Минске</a> http://kvartira-na-sutki-minsk.ru/ Снять однокомнатную квартиру на сутки

2012-02-22 16:52:22
ABSOMSBAW
<a href=http://www.formspring.me/JuliannMacivor/q/237576617247913089>viagra generiques</a> - <a href=http://www.formspring.me/JuliannMacivor/q/237576617247913089>achetez viagra</a> , http://www.formspring.me/JuliannMacivor/q/237576617247913089 viagra 100mg prix
<a href=http://www.formspring.me/TrustedHealth/q/175726032479885835>cheap gabapentin</a> - <a href=http://www.formspring.me/TrustedHealth/q/175726032479885835>gabapentin 300mg</a> , http://www.formspring.me/TrustedHealth/q/175726032479885835 Buy Gabapentin
<a href=http://www.formspring.me/SupervisorHere/q/176760472270299724>sildenafil citrate uk</a> - <a href=http://www.formspring.me/SupervisorHere/q/176760472270299724>silagra 50mg</a> , http://www.formspring.me/SupervisorHere/q/176760472270299724 silagra 50mg
<a href=http://www.formspring.me/RobVongsakda/q/179246124991799604>misoprostol 200 mcg no prescription</a> - <a href=http://www.formspring.me/RobVongsakda/q/179246124991799604>misoprostol 200 mcg no prescription</a> , http://www.formspring.me/RobVongsakda/q/179246124991799604 Misoprostol 200Mg
<a href=http://www.formspring.me/JohnKreisher/q/238195109374465842>cialis generico 5mg</a> - <a href=http://www.formspring.me/JohnKreisher/q/238195109374465842>aquista cialis</a> , http://www.formspring.me/JohnKreisher/q/238195109374465842 cialis generico 5mg
<a href=http://www.formspring.me/UncleBobHere/q/176753643024837028>Buy Ciprofloxacin no prescription</a> - <a href=http://www.formspring.me/UncleBobHere/q/176753643024837028>Buy Cipro Online</a> , http://www.formspring.me/UncleBobHere/q/176753643024837028 Buy Ciprofloxacin
<a href=http://www.formspring.me/HipolitoGoletz/q/178849007907411130>purchase cytotec</a> - <a href=http://www.formspring.me/HipolitoGoletz/q/178849007907411130>Cytotec</a> , http://www.formspring.me/HipolitoGoletz/q/178849007907411130 order cytotec
<a href=http://www.formspring.me/TakishaLamia/q/242200307973492486>Singulair Cost Without Insurance</a> - <a href=http://www.formspring.me/TakishaLamia/q/242200307973492486>singulair cost</a> , http://www.formspring.me/TakishaLamia/q/242200307973492486 singulair online
<a href=http://www.formspring.me/ShonnaPraino/q/178852499426408726>order zithromax</a> - <a href=http://www.formspring.me/ShonnaPraino/q/178852499426408726>order zithromax</a> , http://www.formspring.me/ShonnaPraino/q/178852499426408726 zithromax price
<a href=http://www.formspring.me/EmmalineMacke/q/237584345991218358>kamagra acheter</a> - <a href=http://www.formspring.me/EmmalineMacke/q/237584345991218358>kamagra acheter</a> , http://www.formspring.me/EmmalineMacke/q/237584345991218358 kamagra generique
<a href=http://kvartira-na-sutki-minsk.ru/>Снять однокомнатную квартиру на сутки</a> , ZTKYZYZZZZKY, <a href="http://kvartira-na-sutki-minsk.ru/">Аренда квартиры на сутки Минск</a> http://kvartira-na-sutki-minsk.ru/ Снять однокомнатную квартиру

2012-02-16 02:34:32
AtraulseTrerge
<a href=http://kvartira-na-sutki-minsk.ru/>Снять однокомнатную квартиру на сутки</a> , ZTKYZYZZZZKY, <a href="http://kvartira-na-sutki-minsk.ru/">Аренда квартиры на сутки Минск</a>

2012-02-15 17:35:39
AtraulseTrerge
<a href=http://kvartira-na-sutki-minsk.ru/>Квартира на сутки в Минске</a> , ZTKYZYZZZZKY, <a href="http://kvartira-na-sutki-minsk.ru/">Аренда квартиры на сутки Минск</a>

2012-02-12 03:12:59
AFlangealt
<a href=http://votebook.ru/>Задать Вопрос</a> , ZAFZFFAZPVFZ ,<a href="http://votebook.ru/">Задать Вопрос</a> , http://votebook.ru/

2011-12-08 11:24:44
ElbertWidner
<a href=http://www.fotele-obrotowe.com.pl>krzes&#322;a</a> lub <a href=http://www.fotele-obrotowe.com.pl>krzes&#322;a</a> obrotowe sa niezbednym elementem wyposazenia wszelkiego biura. Dzieki mechanizmowi obrotowemu ulatwiony jest dostep do urzadzen biurowych. Waznym detalem oprzyrzadowania wszystkiego <a href=http://www.fotele-obrotowe.com.pl>Krzesla</a> lub <a href=http://www.fotele-obrotowe.com.pl>Krzesla</a> obrotowego jest wygodne profilowane siedzisko i oparcie. Krzesla obrotowe sa skonstruowane z rуznego typu surowcуw. Waznym szczegуlem kazdego krzesla jest jego rуwnowaga, ktуra zapewniaja nogi wyposazone w kуlka z kauczuku. Krzeslo musi miec regulowana wysokosc oparcia i siedzenia. Krzesla sa dostepne w wielorakich przedzialach cenowych, ich cena jest uzalezniona od gatunku pуlproduktu wykonczeniowego. Ekskluzywnym artykulem sa <a href=http://www.fotele-obrotowe.com.pl>Fotele</a> lub <a href=http://www.fotele-obrotowe.com.pl>fotele</a> obrotowe z wysokimi oparciami wykonczone skуra naturalna w rуznorodnych odcieniach. Krzesla i fotele obrotowe dobrej jakosci przyczyniaja sie do wygodnej i efektywnej pracy biurowej. Pozwala to na unikniecie problemуw z kregoslupem i przyczynia sie do zachowania wlasciwej pozycji ciala. Zasadniczym detalem kazdego krzesla i fotela obrotowego jest blokada oparcia ktуra pozwala na utrzymanie poprawnej pozycji co gwarantuje wygode przy pracy przez dlugie godziny. Dysponuja tez funkcje sposobu relaksu, dzieki ktуrym mozna odpoczac i sie zrelaksowac nie wychodzac z biura. Fotele sa dostepne w wielorakich rozmiarach: male, srednie (dla wiekszosci ludzi) i duze. Kazdy moze odszukac cos dla siebie. Aby fotele i krzesla sprawowaly swoje role musza byc wygodne, ergonomiczne, wykonane z wysokiej jakosci pуlproduktуw, z dostosowywanym oparciem, podlokietnikami i podglуwkiem. Kazde krzeslo i fotel powinien byc bezproblemowy w obsludze.
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Как вы относитесь к интернет-магазинам?
Не доверяю
18% (16)
Ни разу не пользовался и не буду
16% (15)
Пользовался единожды
12% (11)
Пользуюсь регулярно
26% (24)
Пользовался бы, но нет денег
18% (16)
А что такие бывают?
2% (2)
Обычные магазины лучше!
8% (7)

Проголосовало: 91
Из открытий компьютерной вирусологии:
Oказывается, первый троян был конь!
Рейтинг: 1/10 (1)
Посмотреть все анекдоты

 
eXcode.ru » Статьи » PHP » Трюки