» » Руководство по собеседованию на вакансию PHP-программиста

 

Руководство по собеседованию на вакансию PHP-программиста

Автор: admin от 23-07-2014, 09:15, посмотрело: 503

Вездесущий… это определённо то слово, которым можно описать язык PHP по отношению к вебу. Он действительно вездесущ. В настоящее время, среди всех серверных языков программирования, PHP используется наиболее широко. На нём написаны более 80% сайтов, при этом следующий по популярности ASP.NET со своими 17% остаётся далеко позади.

Руководство по собеседованию на вакансию PHP-программиста

Почему? Что позволило PHP стать настолько популярным и широко используемым? На этот вопрос нет однозначного ответа, но простота использования языка, безусловно, существенный фактор, поспособствовавший его успеху. Новички в PHP могут быстро выйти на достаточный уровень и разместить динамический контент на своих веб-сайтах с минимум познаний в программировании.

Именно в этом и заключается основная проблема поиска высококвалифицированных PHP-разработчиков. Относительно низкий порог вхождения и 20 лет развития языка привели к тому, что PHP-программисты стали такими же вездесущими, как и сам PHP. Многие из них могут на законных основания утверждать, что «знают» язык. Однако разработчики, которые действительно являются экспертами по PHP, способны создавать куда более функциональное, надёжное, масштабируемое и простое в сопровождении программное обеспечение.

Как же отличить тех, кто обладает реальной компетентностью в PHP (не говоря уже о тех, кто входит в 1% наиболее опытных кандидатов) от тех, у кого только поверхностные знания?

От переводчика: данный текст представляет собой перевод и адаптацию с небольшими дополнениями статьи The Insider's Guide to PHP Interviewing, ссылка на которую была опубликована в последнем июньском дайджесте по PHP. Я постарался максимально передать смысл оригинала, добавил несколько пояснений, значительно увеличил количество ссылок на документацию, а также добавил ссылки на статьи с хабра и на другие источники. Важное отличие от оригинала: добавлена навигация по вопросам, часть кода и текста скрыта под спойлеры.

В этом руководстве предлагаются несколько вопросов, которые помогут эффективно оценить широту и глубину владения кандидатом PHP. Стоит иметь в виду, что они являются лишь ориентирами. Не каждый высококлассный кандидат, достойный найма, сможет правильно ответить на все вопросы, как и ответ на них не гарантирует, что кандидат вам подойдет. В конце концов, рекрутинг – больше искусство, чем наука.

Обратите внимание, что мы сфокусировали внимание на современных версиях PHP (5.3 и старше), но также есть отсылки к концепциям и функциям, существующим уже достаточно давно, а значит знакомым всем квалифицированным PHP-разработчикам.
Расскажите о замыканиях в PHP. Приведите примеры, когда, почему и как они могут быть использованы?
  • Объясните, с какой целью и как используется ключевое слово global. Приведите пример, когда его применение целесообразно и когда нет.

  • Расскажите о пространствах имён в PHP и о том, почему они полезны.

  • Что такое типажи (traits, трейты)? Опишите их основные характеристики и расскажите, чем они полезны. Приведите пример объявления типажа и класса, использующего несколько типажей.

  • Расскажите, как связаны между собой php://input и $_POST и как получить доступ к потоку php://input?

  • Назовите не менее пяти суперглобальных переменных, имена которых начинаются с $_, и дайте им определение. Расскажите об их связи с переменной $GLOBALS.

  • Объясните назначение и применение магических методов __get, __set, __isset, __unset, __call, и __callStatic. Когда, как и почему их стоит использовать (или не использовать)?

  • Опишите несколько структур данных из стандартной библиотеки PHP (SPL). Приведите примеры использования.

  • Чему будет равен $x после выполнения выражения $x = 3 + «15%» + "$25"?

  • Объясните назначение ключевого слова static при вызове метода или обращении к свойству. Расскажите, когда и зачем его нужно использовать, а также чем оно отличается от ключевого слова self. Приведите пример.

  • Расскажите о внутреннем устройстве массивов в PHP?

  • В чем различие между ArrayAccess и ArrayObjects?

  • Что такое генераторы? Когда их можно использовать вместо итераторов и обычных массивов? Для чего нужны ключевые слова yield и send?

  • Перечислите ключевые отличия между версиями PHP 5.3, 5.4, 5.5.



  • Ключевые концепции и парадигмы


    Есть ряд основных концепций и парадигм, без знания которых нельзя считать себя экспертом в PHP. Вот несколько примеров.

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

    Первый строительный блок для замыкания – это анонимные (лямбда) функции, т.е. такие функции, у которых нет ассоциированных с ними имён. Например:

    // 2-ой аргумент для array_walk - анонимная функция
    array_walk($array, function($dog) {
        echo $dog->bark();
    }); 
    

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

    // объявляем анонимную функции и ассоциируем её
    // с переменной $dogs_bark
    $dogs_bark = function($dog) {  
        echo $dog->bark();
    }
    array_walk($array, $dogs_bark);
    

    Внутреннее устройство замыканий в PHP представлено специальным классом замыканий – Closure.
    Содержимое анонимной функции существует в своей области видимости независимо от области видимости, в которой эта функция была создана. Тем не менее, можно явно связать одну или несколько переменных из внешней области видимости, на которые можно будет сослаться в области видимости анонимной функции. Для этого нужно воспользоваться конструкцией use при определении анонимной функции.


    Способность получить доступ ко внешним переменным в пределах замыкания особенно полезна при использовании функций высшего порядка. Возьмём, например, функцию array_walk($array, $calback), которая, как и другие подобные функции, позволяет обойти переданный ей набор переменных и обработать их специфическим способом. Эта функция обходит массив $array и на каждой итерации вызывает анонимную функцию ($callback), передавая ей только значение текущего элемента и его ключ. Поэтому использовать переменную $collar без замыкания и конструкции use не получится. Конечно, мы можем воспользоваться ключевым словом global, но это приведёт к бессмысленному засорению глобального пространства имён переменной, которая нужна только в данном конкретном контексте.
    Замыкания обладают дополнительными объектно-ориентированными возможностями. Начиная с версии PHP 5.4, в интерфейсе класса Closure появились новые методы: bind() и bindTo(), которые можно использоваться для привязки новых объектов к замыканию. Например:

    Closure::bindTo($newthis, $newscope); 
    

    Этот метод дублирует замыкание и связывает его область видимости с новым объектом таким образом, что внутри замыкания переменная $this станет ссылкой на $newthis в объектном контексте. Давайте изменим функцию $dogs_bark так, чтобы она использовала переменную $this, а затем привяжем её к объекту $dog.

    // объявляем замыкание, но не связываем его с объектом
    $dogs_bark = function() {
        echo $this->sound;  // где sound - свойство объекта $this
    };
    $new_dog = new Dog();
    // создаем новое замыкание и привязываем его к объекту $new_dog
    $new_closure = $dogs_bark->bindTo($new_dog);
    $new_closure();   // выводит значение свойства $sound
    

    Привязка замыкания к переменной и получение доступа к $this – достаточно мощная возможность. В частности, мы можем присвоить замыкание свойству объекта, по существу, превратив его в метод этого объекта.

    $dog = new Dog();
    $dog->closure = $dogs_bark;
    $dog->closure();
    

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

    Wordpress Codex, на котором работает около 20% всех сайтов (и это число растёт из года в год), Joomla! 1.5 (да, она до сих пор еще широко распространена) и iLance Enterprise Auction system – это все примеры успешных проектов, в течение многих лет использующих глобальные переменные. Точно так же и у вас могут возникнуть ситуации, в которых глобальные переменные будут уместны, однако к их применению нужно подходить осторожно.
    К списку вопросов

    К списку вопросов

    Типажи – это великолепное дополнение, появившееся в PHP 5.4, позволяющее добавлять классу поведение без необходимости расширения родительского класса через наследование (до версии 5.4 это можно было реализовать с помощью паттерна примесь). Важно отметить, что в контексте одного класса можно использовать несколько типажей. Их применение способствует улучшению организации кода и разделению обязанностей, а также соответствует известному принципу проектирования, гласящему: «предпочитайте композицию наследованию».


    Теперь воспользуемся ключевым словом use, но не для импорта пространства имён, а для включение типажей в определение класса:

    К списку вопросов

    PHP на пальцах


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

    К списку вопросов

    суперглобальных переменных, имена которых начинаются с $_, и дайте им определение. Расскажите об их связи с переменной $GLOBALS.

    Суперглобальная переменная $GLOBALS – родственник ключевого слова global. В массиве $GLOBALS хранятся все переменные, доступные в глобальной области видимости, в том числе и суперглобальные массивы. Например, доступ к $_ENV можно получить вот таким образом: $GLOBALS['_ENV'];
    К списку вопросов

    перезагрузки свойств объекта. Они позволяют определить, каким образом будет взаимодействовать внешний мир со свойствами, объявленными с модификатором видимости private или protected, либо вообще отсутствующими у объекта.


    Теперь можно просто обратиться к свойству 'whiskers':

    $hairs = $dog->whiskers;
    


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


    Изменение значения свойства 'whiskers' будет выглядеть так:

    $dog->whiskers = $hairs; 
    

    Это выражение приведет к автоматическому вызову метода __set() с передачей ему в качестве первого параметра имени свойства ('whiskers') и правой части оператора присвоения в качестве второго.

    Наконец, __isset и __unset завершают квартет методов для перезагрузки свойств. Каждый из них принимает только один параметр – имя свойства, и вызываются при выполнении операций isset() и unset() над этим свойством.

    Два оставшихся метода, __call и __callStatic, выполняют похожую функцию, позволяя реализовать перегрузку методов. Они позволяют нам определить, как класс и его экземпляры отреагируют на попытки вызова неопределенных, защищенных или приватных методов.

    Прим. переводчика: __call вызывается при обращении к члену класса в контексте объекта, а __callStatic при обращении к статическому члену класса. В качестве аргументов, они оба принимают имя $name вызываемого метода и массив $args с переданными методу $name параметрами.

    Например, вот такая реализация __call приведет к тому, что при обращении к любому «невидимому» методу будет выполнена полезная нагрузка на whiskersService:

    public function __call($method, $args) {
        return $this->whiskersService->load();
    }
    

    Метод __callStatic работает таким же образом и принимает те же аргументы, однако он вызывается при обращении к «невидимому» методу не в контексте объекта, а в статическом контексте. Если мы определим этот метод, то получим возможность обрабатывать вызовы, подобные ClassName::notVisibleMethod().

    public function __callStatic($method, $args) {
        if (!is_object(static::$whiskersService)) {
            static::$whiskersService = new Whiskers(__CLASS__);
        }
        return static::$whiskersService->load(); 
    }
    
    $hairs = Dog::whiskers();
    

    В приведённых выше примерах мы инкапсулировали реализацию whiskers от внешнего мира, сделав его единственным объектом, доступным таким способом. Клиенты определенных нами методов и свойств ничего не знают о базовом классе whiskersService и о том, как вообще Dog хранит свои данные.

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

    Используя магические методы, следует помнить, что получаемые выгоды имеют свою цену. Во-первых, эти методы выполняются медленнее, чем обращение к явно определенным публичным свойствам, а также медленнее установщиков и получателей. Во-вторых, они препятствуют применению многих полезных средств, таких как рефлексия, автодополнение в IDE, утилиты автоматической документации (например, PHPDoc). Если эти вещи имеют значение, то, возможно, стоит определить публичные методы и свойства явно. Как и во многих других случаях, на вопрос о том, стоит ли использовать магические методы, однозначно ответить нельзя. Достоинства и недостатки нужно оценивать в каждом конкретном случае.
    К списку вопросов

    стандартной библиотеки PHP (Standard PHP Library, SPL) и знание её состава – та область, владение которой может подтвердить компетентность PHP-разработчика. Если у кандидата имеется приличный опыт работы с SPL, то, скорее всего, он сможет успешно работать над вашим приложением, вне зависимости от используемых в вашем окружении фреймворков.

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


    Также о структурах данных из SPL можно почитать на хабре.
    К списку вопросов

    автоматическое привидение типов, основанное на контексте, в котором используется переменная.

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

    Зная это, мы можем увидеть, что в выражении $x = 3 + "15%" + "$25" строка "15%" будет соответствовать числу 15, а строка "$25" — нулю. Поэтому результат выражения будет равен 18 (3 + 15 + 0).

    Одни программисты считают автоматическое привидение типов ценной особенностью, другие – отвратительным недостатком PHP. С одной стороны, осознанное и правильное его применение добавляет удобства разработчику (нет необходимости писать код для конвертации «15» в 15 перед применением арифметической операции). С другой стороны, оно может легко привести к трудноулавливаемым ошибкам, если будет задействовано случайно (т.к. не будет выдано никаких предупреждений и ошибок).
    К списку вопросов

    позднее статическое связывание. Термин «позднее связывание» означает, что ключевое слово static связывает метод или свойство (к которому происходит обращение через static::) не с тем классом, в котором был определён использующий его метод, а с тем, в котором этот метод был вызван во время выполнения. Кстати, название «статическое связывание» не совсем корректно, т.к. static допустимо использовать не только для обращения к статическим членам класса.


    К списку вопросов

    Под капотом PHP


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

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

    Прим. переводчика: Здесь я сознательно исключил из текста понятие бакета (bucket, корзина), т.к. автор оригинального текста не даёт никаких пояснений на его счет. Если вам действительно интересно устройство хеш-таблиц, то рекомендую к прочтению вот этот материал.

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

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

    ArrayAccess – это просто интерфейс, требующий определения следующих методов: offsetGet, offsetSet, offsetExists, и offsetUnset.

    ArrayObject – класс, реализующий интерфейс ArrayAccess. Удобство ArrayObject заключается в том, что к его свойствам можно получать доступ таким же образом, как к обычному массиву через оператор [], например: $dogs['sound'], или через метод offsetGet('имя свойства'), например: $dogs->offsetGet('sound').
    Подробнее об использовании объектов как массивов.
    К списку вопросов

    Генератор внешне похож на обычную функцию, и обладает некоторым сходством с замыканиями. При первом вызове в контексте итератора (например, в цикле foreach), генератор возвращает объекта класса Generator, который, в свою очередь, реализует интерфейс Iterator. Значения для итерации генерируются в реальном времени, что избавляет от необходимости загружать весь набор данных в память, получая значения по мере необходимости. Из этого следует, что итерация по результату осуществляется так же, как по массиву, не считая некоторых отличий:


    1. итерация направлена только вперед, нельзя вернуться к предыдущему значению или к началу. Вызов метода rewind() выбросит исключение;

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

    3. крайне эффективное использование памяти.



    Невозможность возврата значения через оператор return – это одно из основных отличий генератора от других функций или замыканий. Вместо него для передачи значения из генератора применяется ключевое слово yield (например, yield $dog). Указание значения после return приведет к синтаксической ошибке, а применение пустого оператора – простой способ остановить работу генератора.

    Оператор yield приостанавливает выполнение и возвращает текущее значение в контекст структуры, использующей генератор. Эта структура может отправить информацию обратно в генератор во время его выполнения с помощью метода send (например, $generator->send(-1);).


    Основные преимущества генераторов можно свести к простоте реализации, повышению читаемости кода, повышению эффективности расходования памяти.
    Вообще говоря, стоит применять генераторы всегда, когда не требуется повторно обходить набор данных с начала или просматривать его в обратном направлении. С другой стороны, если не учитывать расходование памяти, обход обычного массива выполняется значительно быстрее.
    Документация по генераторам на php.net на русском языке пока что отсутствует.
    К списку вопросов

    Общая картина


    Версия PHP 5.3 была выпущена в июне 2009 года, но до сих пор широко распространена. Основные новшества: замыкания, лямбда-функции, пространства имён и позднее статическое связывание.

    Релиз PHP 5.4 состоялся в марте 2012 года. В нём были представлены типажи (трейты), возможность объявления массива с коротким синтаксисом [] (например, ['шит-цу', 'ротвейлер']). Ко всему прочему, в этой версии была убрана опция register_globals.

    PHP 5.5 был выпущен в июне 2013 года, и это текущий релиз. В этой версии появились генераторы (и связанное с ними ключевое слово yield), в инструкцию try/catch добавлен блок finally, APC Cache был заменён на OpCache (базирующийся на Zend Optimizer). Также был расширен синтаксис литералов массивов (['шит-цу', 'ротвейлер'][1] вернёт 'ротвейлер'), и добавлена удобная возможность обращения к символам в строке как к элементам массива (например, '6e5d4'[0] вернёт «6»).
    К списку вопросов

    Подведём итоги


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

    Ссылка на оригинал

    Источник: Хабрахабр

    Категория: Программирование

    Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
    Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
    Введите два слова, показанных на изображении: *