Zend Action Controller - стратегия рефакторинга

Я создал веб-службу для первого запуска на Zend Framework (1.10), и теперь я ищу способы рефакторинга некоторой логики в моих контроллерах действий, чтобы это было проще для меня и остальных моя команда по расширению и поддержке сервиса.

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

Базовая структура для наших контроллеров действий:

  1. Извлечь XML-сообщение из тела запроса - это включает проверку на соответствие специфической для действия схеме relaxNG.
  2. Подготовить XML-ответ
  3. Проверить данные в сообщении запроса (неверные данные вызывают исключение - сообщение добавляется к ответу, который отправляется немедленно)
  4. Выполнение действия с базой данных (выбор / вставка / обновление / удаление)
  5. Возвращает успешное или неудачное действие с требуемой информацией

Простым примером является это действие, которое возвращает список поставщиков на основе гибкого набора критериев:

class Api_VendorController extends Lib_Controller_Action
{  
    public function getDetailsAction()
    {
        try {
            $request = new Lib_XML_Request('1.0');
            $request->load($this->getRequest()->getRawBody(), dirname(__FILE__) . '/../resources/xml/relaxng/vendor/getDetails.xml');
        } catch (Lib_XML_Request_Exception $e) {
            // Log exception, if logger available
            if ($log = $this->getLog()) {
                $log->warn('API/Vendor/getDetails: Error validating incoming request message', $e);
            }

            // Elevate as general error
            throw new Zend_Controller_Action_Exception($e->getMessage(), 400);
        }

        $response = new Lib_XML_Response('API/vendor/getDetails');

        try {
            $criteria = array();
            $fields = $request->getElementsByTagName('field');
            for ($i = 0; $i < $fields->length; $i++) {
                $name = trim($fields->item($i)->attributes->getNamedItem('name')->nodeValue);
                if (!isset($criteria[$name])) {
                    $criteria[$name] = array();
                }
                $criteria[$name][] = trim($fields->item($i)->childNodes->item(0)->nodeValue);
            }

            $vendors = $this->_mappers['vendor']->find($criteria);
            if (count($vendors) < 1) {
                throw new Api_VendorController_Exception('Could not find any vendors matching your criteria');
            }

            $response->append('success');
            foreach ($vendors as $vendor) {
                $v = $vendor->toArray();
                $response->append('vendor', $v);
            }

        } catch (Api_VendorController_Exception $e) {
            // Send failure message
            $error = $response->append('error');
            $response->appendChild($error, 'message', $e->getMessage());

            // Log exception, if logger available
            if ($log = $this->getLog()) {
                $log->warn('API/Account/GetDetails: ' . $e->getMessage(), $e);
            }
        }

        echo $response->save();
    }
}

Итак - зная, где общие черты в моих контроллерах, какова лучшая стратегия для рефакторинга, сохраняя при этом Zend-подобный, а также проверяемый с помощью PHPUnit?

Я действительно думал об абстрагировании большей части логики контроллера в родительский класс (Lib_Controller_Action), но это усложняет модульное тестирование, что мне кажется неправильным.

6
задан HorusKol 12 January 2012 в 03:05
поделиться