Статьи

Написание чистого кода на PHP 5.4

После семи кандидатов на релиз ясно, что PHP 5.4 выходит: как всегда, улучшений по сравнению с предыдущей минорной версией много.

На уровне платформы новые функции не могут причинить вреда: почти всегда удобно иметь встроенный веб-сервер или другие инструменты, если они не являются трудной задачей для основных разработчиков. Но разработчики языка должны быть более осторожными: можно использовать функции, которыми можно злоупотреблять (кому-нибудь?), Писать код, который трудно понять и использовать повторно.

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

Черты

Черты являются наиболее известным нововведением в PHP 5.4: форма горизонтального повторного использования, похожая на множественное наследование и способная включать поля и методы во многие разные места, во взаимосвязи между классами и признаками.

Черты и миксины часто приводят к плохой сплоченности классов, использующих их: объекты, которые предоставляют сотни методов просто потому, что они доступны и готовы быть захваченными в черту.

Во-первых, PHP пытается ограничить проблемы множественного наследования, вводя множество проверок во время компиляции при составлении признаков:

  • черты с одинаково именованными методами вызывают фатальную ошибку, если нет явного разрешения конфликта (поэтому не допускается перезапись методов без вывода сообщений).
  • Черты находятся в отдельной иерархии , поэтому они могут быть составлены друг с другом, но не могут заимствовать код из классов.
  • Они поддерживают абстрактные члены , вызывая определение метода в классе составления; звонки неопределенным членам в выставлении классов избегают.
  • Может определять свойства, но не существующие в классе экспонирования.
  • Изначально они могли переопределить устаревшие конструкторы, но это потенциальное злоупотребление было признано ошибкой и исправлено.

Я сравниваю черты с абстрактными классами с теми же проблемами: связывание (наследование — это фиксированная зависимость), плохая тестируемость и понятность, так как вам приходится смотреть на код во многих местах. Что касается композиции интерфейса, то, что когда все сделано правильно, вы останавливаетесь на границах интерфейса, наследование может заставить вас прыгать вверх и вниз по иерархии. Но теперь есть несколько иерархий для перемещения.

Но я бы не отказался от поддержки наследования в языке, потому что есть некоторые варианты использования даже для хардкорных OO-программистов. Проблема заключается в том, что в большинстве случаев это все равно, что использовать Decorator или Composite только потому, что это круто, а не потому, что в дизайне есть необходимость для этого.

Чего мы не хотим, так это того, что объекты используют более 300 методов «на всякий случай», хотя API-интерфейсы Java справляются с этим без особенностей (наследуя цепочку иерархии из 6-7 суперклассов). Таким образом, мне нравится возможность демонстрировать черты, хотя я знаю, что мне не понравится их фактическое использование.

Полезность: 8. Потенциал для злоупотребления: 8.

Массив коротких обозначений

Действительно, массивы PHP — это клей, который удерживает большую часть сети вместе. Это списки, карты и матрицы одновременно. И действительно, они, вероятно, чрезмерно используются в качестве примитивных типов, где какой-либо объект Value или объект домена подойдет лучше.

Однако новая запись не является проблемой сама по себе:

[giorgio@Desmond:~]$ php -r 'var_dump([4, 2]);'
array(2) {
  [0]=>
  int(4)
  [1]=>
  int(2)
}
[giorgio@Desmond:~]$ php -r 'var_dump(['key' => 4]);'
array(1) {
  ["key"]=>
  int(4)
}

JavaScript и многие другие динамические языки теперь имеют один и тот же синтаксис, поэтому нет причин навязывать array () разработчикам. В этом синтаксисе мало что может повлиять на использование массива, что уже очень популярно.

Полезность: 8. Потенциал для злоупотреблений: 2.

Разыменование массива

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

$callbacks = array('key' => function() { ... }, ...);
$callbacks['key']();

Однако, хотя [$ field] () и () [$ field] работают (а [] () [] будет), любая попытка с двумя () like () [] () не будет выполнена из-за синтаксических ошибок. Скорее всего, это нарушение закона Деметры, поэтому я согласен не поддерживать бесконечные цепочки разыменования.

Полезность: 7. Потенциал для злоупотреблений: 4.

Закрытие и вызовы массивов, плюс подсказка типа

Вы можете вызывать с помощью $ variable () не только замыкания, но и классические обратные вызовы, такие как array ($ object, ‘method’).

В результате можно избежать множества ifs и шаблонного кода:

$callback = function($param) use ($object) {
    return $object->method($param);
};

Более того, подсказка типа Callable зарезервирована для такого рода структур. Это полиморфизм как лучший.

Полезность: 9. Потенциал для злоупотреблений: 2.

Закрытие переплет и переплет

$ this теперь не нужно присваивать $ self при создании замыкания внутри объекта; Кроме того, вы можете получить доступ к закрытым полям объекта, создав закрытие внутри него, так как область действия логически позволит это сделать, когда вы получаете доступ к $ this:

<?php
class A
{
    private $field;

    public function __construct($value)
    {
        $this->field = $value;
    }

    public function goodClosure()
    {
        return function() {
            echo $this->field, "\n";
        };
    }
}
$a = new A(42);
$goodClosure = $a->goodClosure();
$goodClosure(); // prints 42

Ссылки на частные поля хранятся вместе с классом, в котором они определены, так что это действительно связное решение.

Тем не менее, Филиппо Тессаротто указал мне, что новый метод bindTo () для замыкания нацелен на изменение области действия, на которую он ссылается. Он может даже сделать частные свойства доступными с помощью кода, написанного вне класса (как в отражении, но это даже проще). Этот код вызывает большой Ват?

$closure = function() {
    echo $this->field;
};  

$a = new A(42);
$boundClosure = $closure->bindTo($a, $a);
$boundClosure(); // prints 42

Полезность: 8. Потенциал для злоупотребления: 10 .

Загрузить прогресс

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

API немного одержим примитивами (каждая информация представлена ​​в гигантском массиве в $ _SESSION, который сам по себе является другим массивом), но сюрпризов нет. Он соответствует остальной части серверной среды PHP, предоставляя $ _GET и $ _POST в качестве суперглобальных массивов.

Полезность: 7. Потенциал для злоупотреблений: 2.

Устаревшие

Все магические кавычки и функции безопасного режима не только устарели, как в PHP 5.3, но даже удалены (как говорит нам файл UPGRADING в источнике PHP 5.4). Другие устаревшие директивы — register_globals, register_long_arrays ($ HTTP_POST_VARS? Я даже не помню их имена).

Что касается баз данных, ext / sqlite была удалена из ядра, но поддержка SQLite 3 все еще существует. Функции mysql () все еще включены!

Полезность: 7 , так как это делает язык менее старым и обеспечивает новичкам язык по умолчанию. Потенциал для злоупотреблений: 1 , хотя на старых веб-сайтах возможен сбой.

JsonSerializable

Реализуя этот интерфейс, вы делаете объекты приемлемыми для json_encode (). Это процедурная форма полиморфизма, но она преобразует шаг в преобразование в JSON: PHP всегда создается с учетом веба, а не как язык общего назначения. Я просто надеюсь, что это не реализуется объектами домена и всем, что движется .

Полезность: 6. Потенциал для злоупотребления: 6.

Вывод

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