Антон Шевчук // Web-разработчик

Usability кода // PHP

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

«Usability кода» звучит хорошо, название притягивает, еще мне нравится «эргономика кода», тоже отлично

Ну что же, в понятие юзабилити кода я вкладываю несколько вещей:

  • Соблюдение стандартов кодирования
  • Отсутствие избыточности в коде и комментариях
  • Предсказуемость кода
  • Поддержка читаемости кода на уровне «понятно и чайнику»
  • Время необходимое для изучение кода до уровня «понимаю где баг глядя на скриншот»
  • Скорость разработки при повторном использовании кода и соблюдении принятых норм и стандартов

Думаю, стоит по чуть-чуть остановиться на каждом.

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

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

Избыточность кода

Иногда, гоняясь за красотой ООП мы приходим к очень громоздким решениям:

$file = Application::getInstance()->getRequest()->getFiles()->get($filename);

По сути — думаю каждому понятно что делает данная строчка кода, но почему же не заменить ее на простую функцию? Чего боитесь?

$file = getRequestFile($filename);
// процедурное программирование отстой, бла-бла-бла
$file = Request::getFile($filename);
// выучи еще патерны
// ...

Баланс на грани

Бытует мнение, что комментировать хорошо читаемый код не стоит, и так всем всё понятно, но мне в это слабо верится, так что я тут несколько тезисов написал:

  • Отсутствие комментариев в коде — плохо
  • Правильное именование переменных в коде — хорошо
  • Много комментариев с прогнозом погоды — плохо

Что же хорошо? Вот тут вроде бы баланс удалось соблюсти:

/**
 * Check-in user location to DB
 *
 * <code>Location::checkinUser($User, 2.123654, 0.456321)</code>
 *
 * @param User $User
 * @param float $lat latitude
 * @param float $long longitude
 * @return bool
 */
function checkinUser(User $User, $lat, $long) {
    return Db::insert("checkin", array(
        'userId' => $User->id,
        'lat' => $lat,
        'long' => $long
    ));
}

В данном примере постарался уместить все, что нужно: однозначные имена методов и переменных, минимум комментариев, которых хватает для создания документации по проекту, да подсказок в IDE (что немаловажно!).

Быть провидцем

Если вам приходится работать с незнакомым кодом и мысли «я бы на месте предыдущего разработчика сделал это так-то» совпадают с реальность — поздравляю, у вас совместимость с предыдущим автором, и вы сможете легко работать с текущим кодом. Так что пишите код «предсказуемо», и это не только соблюдение правил использования глаголов в именах методов, но и простая, читаемая структуру кода.

Читаемость кода

Чего хочу я от читаемого кода? Это чтобы любой разработчик «со словариком» мог прочитать любой участок вашего кода. Я могу не знать JAVA, Python, или еще с десяток языков, но у меня есть знание о PHP и JavaScript, я и должен взяв на вооружение что-то типа «RoR для чайников» в качестве словарика и начать работать в проекте спустя день (ну уж лучше «Rails for PHP Developers», но это придирки).

Не должно быть магии по шпаргалкам — «достать объект не знаю где, вызвать метод не знаю как»:

// привет ZF
public function errorAction()
{
    // магия тут
    $errors = $this->_getParam('error_handler');
 
    // а тут правдоподобно
    $this->getResponse()->setHttpResponseCode(404);

    // ни шатко, ни валко, но все в курсе
    $this->view->message = 'Page not found';
}

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

Еще есть такая болезнь — когда из шаблонов проектирования знаешь лишь singleton, конечно же это плохо, но вот юзабельность кода, если оный применять с умом, очень даже ничего:

// тут без комментариев понятно что происходит
$id = Application::getRequest()->getParam('id');
// и тут
$User = UserManager::getById($id);

Где баг?

MVC очень правильный патерн для web приложения, он удобен и всё такое прочее — имхо, вполне юзабельный. Но вот беда, в большом приложении контроллеров много, и по этой причине появилась тенденция объединять их в модули (что вполне логично), а сами контроллеры бить на экшены (что возможно избыточно). Таким образом контроллер стал составным, и знаком нам по многим фреймворкам — модуль/контроллер/экшен. Всё хорошо, и URL к такому контроллеру выглядит адекватно и читается легко, но пришли требования, и нам приходится писать правила-роуты, и теперь URL запрошенной страницы стал совсем неоднозначным для нас. Следовательно надо просмотреть все эти роуты, которые, возможно, расфасованы по модулям, иль еще куда, да елки ж палки…

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

Время — деньги

Время потраченное непосредственно на сам кодинг оценивают в 30%, но это при проектировании «до запятой», но как-то усидчивости у нас не хватает, не наш метод. По этой причине стоит писать удобный код:

// можем же, мляяяять
$bootstrap = $application->getBootstrap();
$bootstrap->bootstrap('db');
$dbAdapter = $bootstrap->getResource('db');
$dbAdapter->getConnection()->exec($dataSql);

// но как-то сподручнее
$application->getDb()->exec($dataSql);

Если расширение функционала приводит к копи-пасту — WTF man?

Вместо выводов

Если бы разработчики фреймворков думали не о красоте ООП, а о эргономике кода, то таких популярных и удобных фреймворков как jQuery было бы больше :)

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

P.P.S. По теме нашел лишь одну статью — Introducing Code Usability, возможно кто подскажет еще?

P.P.P.S. Поругал ZF, похвалил jQuery — OK

© Антон Шевчук 2007-2023