Что такое RDD и почему нужно его придерживаться

Автор: Aport Суббота, Январь 31st, 2015 Нет комментариев

Рубрика: Язык PHP

RDD — Readme driver development. Разработка приложений через описание задачи и написания тестов.
То есть перед тем, как приступить к непосредственному выполнению задачи разработчик должен сначала описать что потребуется сделать для выполнения задачи и как он собирается это сделать.
После этого он приступает к написанию тестов для своего приложения. И только после написания тестов приступает к разработке функционала, требуемого для задачи.

Для чего нужен RDD?

  1. RDD заставляет думать перед тем как начать что-либо разрабатывать.
  2. RDD дает понимание руководителям о том, что собирается делать программист до того, как программист начинает это делать. Соответственно можно избежать неправильных путей решения задачи.
  3. Описание README заставит понять что именно нужно для решения задачи, заставит взглянуть на задачу со стороны
  4. Описание тестов предотвратит появление багов и ошибок в логике до начала разработки самой логики и функционала, так как если вы описали README, то вы уже знаете что у вас будет на входе и что будет на выходе.

Зачем писать README, если мне и так всё понятно?

Затем, что задача понятна вам только с вашей точки зрения. А вот является ли ваша точка зрения правильной? Это и даст понять README. Возможно, что кто-то прочитав ваше ридми подскажет путь в разы короче, нежели выбранный вами. Или просто поправит неправильный подход к решению задачи.
Плюс ко всему, чтобы написать README вам придется узнать задачу от самого начала до самого конца, чтобы она полностью была у вас в голове. О том как ваша задача может повлиять на другой, уже существующий функционал. О том как ваша задача может повлиять на другой функционал, разрабатываемый другими программистами в это же время. И о том что именно вам действительно нужно сделать для решения вашей задачи.

Как же можно писать тесты до того, как написан сам функционал?

Очень просто. Раз вы уже написали README, то значит вы прекрасно знаете какие «внутренности» должны быть у задачи.
Правила решения любых задач одинаковые:

  1. Пишите только в стиле ООП
  2. Мельчите! Чем меньше кода содержит каждый класс — тем лучше! Тем легче его тестировать, тем легче его поддерживать.
  3. Чем больше классов, чем меньше кода в каждом классе — тем лучше!
  4. Логику всегда можно разбить на части, но нужно всегда думать что стоит дробить, а что нет.

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

Приведу пример. Допустим есть задача: реализовать отсылку статистики на e-mail каждый час.
Что я вижу? План моих действий будет таков:

  1. Написать общее README по задаче (по сути этот текст уже является частью README)
  2. Реализовать класс для отправки писем на почту
  3. Реализовать класс шаблонизатора для формирования контента письма
  4. Реализовать класс управления cron’ом
  5. Реализовать класс формирования статистики
  6. Реализовать приложение для получения данных из статистики, генерации контента через шаблонизатор и отправки этого контента через класс отправки писем
  7. Внести правки в конфиг для класса управления кроном
  8. Выкатить

Под текстом «Реализовать класс …» подразумевается написание README и тестов для каждого из классов (если этот функционал еще не реализован, конечно)

Стандарт написания README для приложения перед написанием тестов и самого приложения

1. Заголовок — название приложения

Тестовое приложение

h1. Тестовое приложение

2. Общее описание логики работы приложения

Описание тестового приложения. Описание общей «полезной» логики приложения.

Простой текст, без форматирования. Описание как будет реализовываться задача.

3. Исходный код — описание методов

 1 /**  2 * Кратое описание для чего нужен метод согласно стандарту PhpDoc  3 * (пустая строка)  4 * Подробное описание для чего нужен данный метод, что он делает  5 * Что метод возвращает и для чего это можно использовать  6 * и т.д. и т.п.  7 *  8 * @param string $params_name1 Описание входящих параметров так же согласно PhpDoc  9 * @return bool Описание что именно возвращает данный метод 10 */ 11 public function isStringValue($param_name1); 12 return boolean; throw cantCheckStringValueException; 13 // Основные примеры тестов 14 $phpunit->assertTrue($this->isStringValue("parameter value")); 15 $phpunit->assertFalse($this->isStringValue(12345)); 

Пример описания метода

 1 /**  2 * Выводит сообщение с меткой о дате  3 *  4 * Выводит на экран сообщение, указанное пользователем,  5 * добавляя в начало сообщения дату вывода в формате Y-m-d H:i:s  6 *  7 * @param string $text Текст сообщения для вывода  8 * @return string Текст выведенного сообщения  9 * @throws printTextException 10 */ 11 public function printText($text); 12 // Тесты 13 $phpunit->assertContains($this->printText("test"), "test"); 14 $phpunit->assertContains($this->printText("test"), date("Y-m-d H:i:s")); 15 //@todo Проверить выводит ли сообщение в output 

Для подсветки кода в redmine (без пробелов в начале и конце html-тегов, конечно):
строка перед кодом: <pre><code class="php">
строка после кода: </code></pre>

Стандарты кодирования

Т.к. в последнее время я все больше использую при разработке Symfony, то советую использовать те же стандарты кодирования, которые используются в симфони: PSR-0, PSR-1 и PSR-2.
Чтобы быстрее понять, можно просто глянуть кусок кода:

 1 <?php  2  3 /*  4 * This file is part of the Symfony package.  5 *  6 * (c) Fabien Potencier <fabien@symfony.com>  7 *  8 * For the full copyright and license information, please view the LICENSE  9 * file that was distributed with this source code. 10 */ 11 12 namespace Acme; 13 14 class FooBar 15 { 16 const SOME_CONST = 42; 17 18 private $fooBar; 19 20 /** 21 * @param string $dummy Some argument description 22 */ 23 public function __construct($dummy) 24 { 25 $this->fooBar = $this->transformText($dummy); 26 } 27 28 /** 29 * @param string $dummy Some argument description 30 * @return string|null Transformed input 31 */ 32 private function transformText($dummy, $options = array()) 33 { 34 $mergedOptions = array_merge($options, array( 35 'some_default' => 'values', 36 )); 37 38 if (true === $dummy) { 39 return; 40 } 41 if ('string' === $dummy) { 42 if ('values' === $mergedOptions['some_default']) { 43 $dummy = substr($dummy, 0, 5); 44 } else { 45 $dummy = ucwords($dummy); 46 } 47 } 48 49 return $dummy; 50 } 51 } 

Источник: yapro.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты