PHPStorm: Когда IDE действительно имеет значение

О, я обожаю быстрые и простые текстовые редакторы. Будучи пользователем Linux, я несколько лет практически не расставался с Kate и KWrite.

С помощью ряда приемов и плагинов, я сделал эти редакторы действительно очень интеллектуальными. Я написал в них целые проекты на Perl, Bash и даже на PHP и Java.

Я могу понять энтузиазм, с которым воспринимаются Sublime Text или TextMate, но сегодня я уже не могу обойтись без полномасштабной IDE.

Культура

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

Но это сказывается на обучаемости приложения и легкости его использования. Это те программисты, которые предпочитают Vi(m) или Emacs.

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

В результате у них формируется совершенно другой менталитет и представление проекта и кода. Я программист из этой категории, поэтому в данной статье мы поговорим об IDE, которую я использую в данный момент: PHPStorm.

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

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

Так, в чем разница?

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

Сегодняшние компьютеры и интегрированные среды разработки настолько быстры, что теперь это практически занимает столько же времени: запустить PHPStorm и начать писать код в нем или запустить KWrite и писать код в этом редакторе.

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

Хорошо, хорошо... Все это общие характеристики. Но как насчет специфических функций IDE? Аббревиатура IDE происходит от термина интегрированная среда разработки. Эта фраза содержит две ключевых части: интегрированная и среда разработки.

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

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

Ключевой особенностью IDE является ее понимание кода, который вы пишете. IDE не просто содержит список команд, которые можно использовать в вашем любимом языке, например, PHP или каком-либо другом. Она поддерживает сложные алгоритмы, предназначенные для понимания вашего кода.

PHPStorm не предложит вам команду или выражение, которое было бы синтаксически неверным. Он знает, например, что вы не можете написать "print('Hello World');" непосредственно внутри класса, не заключив это выражение в функцию.

Так что IDE не предложит команду "print()" в случае, когда она не может быть использована. Но это только верхушка айсберга.

Давайте рассмотрим еще несколько конкретных примеров.

Использование PHPStorm в серии статей «Рефакторинг производного кода»

Да. Если вы читали первые две части серии статей «Рефакторинг производного кода»: Золотой мастер и Магические строки и константы, вы могли заметить, что в них приведены скриншоты из IDE.

То есть, как выглядит мой PHPStorm. И, следовательно, как PHPStorm помогает мне, обучать вас программированию.

Подсветка кода

Это очень важно. Большинство простых редакторов также может сделать подсветку кода, но IDE - это совсем другая история. В ней вы можете настроить различные подсветки для разных языков, таких как PHP, HTML, CSS и так далее.

Каждую со своим собственным набором правил. Например, я хотел бы, чтобы строки CSS имели зеленый цвет, PHP и HTML - оранжевый:

Подсветка кода

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

Когда мы искали магические строки в серии по рефакторингу, мы могли легко определить эти строки, просто найдя оранжевый текст на экране. То же самое касается и магических констант и чисел. Когда мы искали их, синий цвет помогал нам в этом.

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

Обзор инструментов рефакторинга

На протяжении всей своей карьеры я использовал много IDE и редакторов. Я действительно любил и ценил NetBeans. Но примерно через пять лет использования исключительно NetBeans, я вынужден был от него отказаться.

Есть вещи, предлагаемые PHPStorm, которых вы не найдете ни в одном другом редакторе или IDE для PHP. Это набор инструментов рефакторинга, которые так необходимы в нашей повседневной работе.

Подсветка, отступы, управление проектами, шаблоны, макросы - все эти функции вы можете найти в большинстве редакторов. Интеграция со средой тестирования и отладчики по определению являются частями любой IDE. Но интеллектуальные и сложные инструменты рефакторинга - это совершенно другая история.

Мы программисты тратим половину нашего времени на чтение кода, около 40% времени на изменение и рефакторинг существующего кода, и, если повезет, если действительно повезет, 10 % на написание нового кода.

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

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

Вот почему я оставил бесплатный, с открытым кодом NetBeans и заплатил за PHPStorm. Набор инструментов рефакторинга делает PHPStorm действительно особенным, и за это стоит заплатить.

Представление локальных переменных

Одним из самых простых видов рефакторинга, с которым мы уже работали в магических строках и константах, являлось «Представление локальных переменных», также известное как «Извлечение переменных».

Я кратко напомню этапы, которые мы должны пройти, чтобы использовать этот вид рефакторинга:

  • Добавление переменной с требуемым значением;
  • Поиск всех вхождений ее значений;
  • Замена всех вхождений переменной.

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

Вам нужно проанализировать ваш код и принять сознательные решения о том, что заменять, а что нет. Например:

class SomeClass {
 
    function printAPairOfPlayers() {
        echo "Players are:";
 
        echo "Player name: " . $this->getRandomPlayerName();
        echo "Player name: " . $this->getRandomPlayerName();
    }
 
    function printOnePlayer() {
        echo "Player name: " . $this->getRandomPlayerName();
    }
 
    function getRandomPlayerName() {
        // Логика для определения имен игроков //
        return $playerName;
    }
 
}

В printAPairOfPlayers( мы можем видеть, что строка "Player name:" повторяется дважды. Если мы хотим извлечь эту строку в локальную переменную, переменную внутри функции, нам нужно будет заменить оба вхождения на printAPairOfPlayers(), а не одно на printOnePlayer().

Если printOnePlayer() будет располагаться на 100 строк ниже, мы даже не сможем увидеть, что есть еще одно дублирование строки в другом методе.

Поэтому нам нужна локальная переменная. Мы сначала создаем переменную, запускаем тесты, а затем ищем строку и находим ее во втором операторе echo.

Мы заменяем ее, запускаем тесты, еще раз ищем, находим ее в последнем операторе echo, заменяем ее, снова запускаем тесты. Ищем снова, пока не достигнем конца метода.

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

Не было бы проще нажать одну кнопку или выбрать опцию в меню, и IDE сделала бы все это за нас? Это действительно было бы здорово, и PHPStorm вполне способен это сделать.

В случае с приведенным выше кодом просто наведите курсор на строку "Player name: " в любом месте и щелкните правой кнопкой мыши:

Представление локальных переменных

После того, как вы выберете команду «Extract Variable...», PHPStorm проанализирует код и произведет поиск различных фрагментов кода, которые вы зададите.

В нашем случае будет предложено два варианта выражения:

Представление локальных переменных - 2

Это не просто крутая фишка, это еще и очень полезно. Очень часто случается так, что дублирование может возникнуть за пределами вашего поля зрения.

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

Для нашего примера, давайте выберем только часть строки, без объединения:

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

В поле ввода вам не нужно ставить символ "$" перед ее именем. PHPStorm проставит его в код автоматически. Еще одним важным аспектом является то, что у нас есть еще и дополнительные опции. PHPStorm нашел все вхождения нашей переменной.

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

Такая же строка в методе printOnePlayer(), не учитывалась и не была нам предложена, поэтому она не будет заменена. В противном случае это привело бы к ошибке в коде, и PHPStorm достаточно умен, чтобы предостеречь нас от этой ошибки:

Меньше тестов

Еще одно преимущество PHPStorm заключается в том, что вам не нужно часто выполнять тесты. Когда мы производим рефакторинг вручную, мы запускаем тесты после каждого следующего шага.

На случай, если бы мы сделали опечатку или заменили какой-то код другим, который, как мы думали, будет делать то же самое, но в действительности это не так, нам нужны были бы определенные инструменты, чтобы быстро проинформировать нас об этом.

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

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

Не имеет значения, как вы относитесь к этому, это в любом случае легче, быстрее и гораздо более защищено от ошибок, чем при любом другом способе рефакторинга.

Извлечение переменных классов

Чтобы извлечь нашу строку в переменную класса - также известную как поле класса - мы можем использовать опцию рефакторинга «Extract Field» из того же контекстного меню, которое было описано выше.

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

Извлечение переменных классов

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

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

Извлечение переменных классов - 2

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

Инициализация зависимой от контекста переменной

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

Давайте рассмотрим один из способов извлечения переменной из магических строк и констант:

Инициализация зависимой от контекста переменной

В методе roll(), в строке 73 - та, что выбрана - есть число "11". Это магическое число, которое мы только что определили, и теперь мы хотим извлечь его.

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

  • Определить переменную в строке, предшествующей строке со значением 11;
  • Запустить тесты;
  • Заменить значение переменной;
  • Запустить тесты;
  • Осуществить поиск другого вхождения числа 11;
  • Определить ее в строке 90;
  • Заменить значение нашей переменной;
  • Запустить тесты. Они выдадут ошибку;
  • Спросить себя, где разместить инициализацию переменной так, что она работала, но по-прежнему как можно ближе к месту ее использования;
  • Переместить инициализацию переменной на один уровень выше;
  • Запустить тесты. Они все равно выдают ошибку;
  • Переместить инициализацию переменной еще на один уровень вверх, за пределы всего оператора if;
  • Запустить тесты. Они, наконец, проходят;
  • Осуществить поиск других вхождений;
  • Больше не найдено. Дело сделано.

Как видите, это очень сложный процесс. И чреватый ошибками. Мы предполагаем, что у вас могут быть тесты, которые помогают вам, но что, если вы работаете с каким-то совершенно нечитаемым, трудно проверяемым кодом?

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

Инициализация зависимой от контекста переменной - 2

Подводная часть айсберга

То, что мы описали вам выше, это примерно верхушка айсберга. Извлечение переменных это, вероятно, самый простой и легкий способ рефакторинга.

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

Мы научим вас, как это сделать вручную, но рекомендую вам использовать смарт IDE, которая будет делать всю работу за вас.

Переименование

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

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

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

Представьте, что у вас есть два совершенно разных класса. В каждом из них у вас есть открытый метод под названием "findAll()". Это очень распространенная ситуация.

Для чего нам нужно оценивать изменения?

Допустим, 50 классов используют первый класс, и еще 50 классов используют второй. Если вы использовали надлежащие интерфейсы и указания для типов, где это возможно, PHPStorm предложит правильные классы для замены.

Но если вы не указали тип, который вы используете, или вы не использовали интерфейс, реализованный с помощью класса в методе findAll(), не существует способа, чтобы автоматически установить, который из ваших двух классов, содержащих метод findAll(), нужно использовать.

Из-за динамической типизации PHP. Хотя в некоторых случаях это дает определенные преимущества, в случаях, когда нам нужно произвести рефакторинг, как сейчас, это является недостатком. Когда такое происходит, единственное, что можно сделать, это самому человеку оценить необходимость замены.

С учетом всего вышесказанного, хотя в PHPStorm есть и другие функции, кроме рефакторинга, это, тем не менее, лучшая IDE, если основная задача это именно рефакторинг.

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

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

Тестирование и просмотр кода

Вы делаете TDD, не так ли? Если нет, то стоило бы. Тестирование так же важно в программировании, как собственно написание кода. Лично я не могу представить свою жизнь без TDD.

За последние несколько лет я настолько привык к нему, что сама мысль о коде без неотъемлемого тестирования, кажется для меня противоестественной.

Тестирование и IDE

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

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

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

Другие IDE, как правило, просто используют исполняемые функции PHPUnit, функции записи и вывода в XML-файле и интерпретируют результаты, чтобы показать их вам. Так работает NetBeans.

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

Но в этом также заключается и огромное неудобство. Все начинает работать медленно.

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

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

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

Затем файл должен быть считан, чтобы вывести его пользователю.

Хотя это супер гибко настраиваемое решение, оно требует много времени. Слишком много, если речь идет о юнит-тестировании и миллисекундах на прохождение тестов. И юнит-тесты, которые занимают более пяти миллисекунд, вообще уже нельзя считать юнит-тестами.

Внутреннее использование PHPUnit

PHPStorm решает проблему, или, по крайней мере, уменьшает потребление ресурсов за счет внутреннего использования PHPUnit и вывода результатов предпочтительным для PHPStorm способом.

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

Нет больше exec, нет больше файлов, записываемых медленными файловыми системами. Для удаленного выполнения может потребоваться дополнительное время на передачу данных по сети, но мы в любом случае не можем обойтись без этого.

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

Так мы получаем преимущество в скорости, подробности и четкости информации за счет гибкости.

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

Организация и поиск файлов

Как и большинство IDE, PHPStorm также является проект ориентированным приложением. Обычно ваш проект содержит исходные файлы и тестовые файлы. Что касается PHPStorm, то он требует от вас указать одну отдельную папку в качестве папки для тестов.

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

Организация и поиск файлов

Но и это еще не все. Когда речь заходит о поиске и запуске файлов в PHPStorm есть уникальная функция: перейти к Everything (или Search Everything) - я обожаю эту функцию.

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

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

Поэтому я могу просто нажать Shift + Shift и начать набирать искомый параметр. Это замечательно и быстро.

Заключительное слово

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

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

Онлайн шаблоны - они прекрасно подходят для создания ваших собственных шаблонов. Например, когда я пишу эту статью в HTML мне нужно соблюдать определенный набор тегов и других элементов форматирования.

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

Управление проектами - это довольно типичная для IDE функция. Все ваши файлы организованы в проекты. Но программисты JetBrains сделали кое-что действительно удивительное.

Их движок индексации просто быстр, как фурия. Ни одной другой IDE не удалось загрузить наш огромный проект на Syneto так быстро. А затем так же быстро провести по нему поиск.

Фактически интегрированные среды разработки, такие как NetBeans или Eclipse и его производные, как правило, не в состоянии проиндексировать весь проект.

Это делает поиск очень медленным. PHPStorm делает это корректно и очень быстро по сравнению с любой другой IDE.

Интеграция версий документов - это еще один козырь в колоде PHPStorm. Mercurial, Git, CVS, Subversion, вы можете сами продолжить этот список. PHPStorm чувствует себя как рыба в воде с каждым из них.

От выборочной фиксации и установления совместимости с различными инструментами и до разнообразных графических функций - все это вы имеете в своем расположении.

Так как я являюсь пользователем PHPStorm, мне приходилось использовать CLI для выдачи команды "hg", возможно, два раза или около того. И он просто работал.

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

Очень редко. Как правило, вы работаете над контекстом самой строки: прописываете в скобках некоторые параметры или что-то вроде того. А после этого вам нужно перейти в конец строки и нажать ";". Что ж, с помощью макросов это легко автоматизировать.

Ок, достаточно разговоров. Не буду больше удерживать вас, чтобы вы могли сами скачать и попробовать PHPStorm.

Наслаждайтесь.