Разработка

PHP: PsySH или Что такое REPL, Exploratory development

Что такое REPL, Exploratory development

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

Недавно я узнал, что это не просто отчаянная попытка двоечника, а системный подход под названием Exploratory development, что переводится как исследовательская разработка

Я люблю исследования, поэтому этот термин и подход мне очень нравится

Такое программирование выглядит как бесконечный цикл примерно следующего вида:

  • Узнать примерно, как написать то, что нужно
  • Написать
  • Проверить, что получилось, как работает
  • Осознать ограничения, исправить ошибки
  • Повторить, выйти за рамки :)

Или на другом этапе этот цикл может быть представлен так:

  • Найти часть кода, который работает не так, как хочется
  • Понять, почему
  • Изменить (исправить)
  • Повторить

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

Традиционные инструменты, используемые до REPL в PHP - это var_dump()+die() и XDebug.

REPL (Read, Execute, Print Loop) - новый инструмент, позволяющий сделать этот цикл более удобным, интерактивным и быстрым.

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

Запуск PsySH

Процесс установки в зависимости от ОС можно найти здесь: https://psysh.org/#install

и здесь: https://github.com/bobthecow/psysh/wiki/Installation

Запуск выполняется командой:

psysh

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

Первый метод - REPL

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

Дальше приведу основной список команд консоли psysh:

  • doc - Отображает документацию по стандартным командам PHP и классам. Можем почитать то, что не успели прямо здесь
  • list (ls) - показывает методы и свойства классов (или глобальных переменных и т.п.) (reflection), сродни автокомплиту
  • wtf - показывает предыдущее (самое свежее) исключение - можно вспомнить, какая ошибка была ранее
  • history - Показывает историю введенных ранее команд, есть параметры фильтрации
  • dump - выводит класс или примитив (значения)
  • show - выводит код класса или метода
  • whereami - выводит код, на исполнении которого мы сейчас остановились
  • throw-up - выбрасывает исключение или ошибку
  • timeit - профилирование времени - можно выполнить код, переданный в качестве параметра и получить время его выполнения. Можно выполнить данный код указанное количество раз
  • $_ - содержит последний полученный результат, с помощью неё можем сделать что-то с полученным на предыдущем шаге примитивом (числом - посчитать, строкой - объединить) или объектом - вызывать метод
  • [tab] - Автокомплит, показывает возможные варианты имён классов, методов и т.п.
  • Поддерживает неймспейсы (можно подключать функционал из библиотек)
  • Можно выполнять команды ОС, заключив команду в обратные кавычки: pwd
  • Можно прописывать настройки на языке php (т.е. делать вобщем-то что угодно, что будет выполняться каждый раз перед загрузкой консоли), список команд настройки: https://github.com/bobthecow/psysh/wiki/Config-options
  • Можно создавать свои собственные команды в настройках

Второй метод - Debug

Делая в коде точки останова (breakpoints), мы

  • eval(\Psy\sh()); - Делаем точку останова в коде, смотрим результат в командной строке, и что важно, выполняем с этого места команды, столько, сколько нужно
  • \Psy\Shell::debug(get_defined_vars()); - выводит заданные переменные с их значениями

Зачем (Use Cases)

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

  • Чтобы узнать, как работают команды PHP
  • Чтобы быстро попробовать, как что-то сработает в приложении. Под что-то я понимаю вызов метода своего класса, или класса какой-то используемой сторонней библиотеки с одними и с другими параметрами
  • Альтернативный отладчик - поставить точку останова и после этого не только посмотреть значения переменных, но еще и выполнить с создавшимся в этой точке состоянием переменных столько операций, сколько надо - попробовать разные варианты без необходимости каждый раз менять код и перезагружать приложение
  • Профилирование заданного куска кода - можно очень просто посмотреть, сколько времени выполняется какой-то запрос к БД, или какая-то вычислительная операция
  • Короткие команды фрэймворка. В Laravel - вместо "php artisan down" - набираем: "down"
  • Подключая компоненты фрэймворка, появляется возможность понять глубже, как работает фрэймворк, последовательности подгрузки и выполнения операций

Удобства

Теперь рассмотрим некоторые более конкретные удобства, которые можно увидеть в этом инструменте:

  • При возникновении ошибки или исключения, результат отображается в консоли в виде текста исключения и консоль продолжает работать. Она не закрывается и можно быстро продолжать работу не теряя результатов
  • После закрытия (или падения) консоли и переоткрытия, набор выполненных ранее команд можно быстро повторить из истории
  • Автокомплит. Это не совсем тоже самое, что предоставляет IDE, т.к. здесь автокомплит дает возможность получить свойства подгруженного класса и сразу же выполнить метод и получить результат его выполнения. Так мы можем подключать какие-то не совсем известные нам компоненты системы, получать их методы и выполнять их, быстро изучая таким образом их поведения, результаты их работы
  • Можно выполнить команду history и сохранить выполненные ранее команды в файл как результирующий код

Интеграция с фреймворком на примере Laravel

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

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

https://github.com/bobthecow/psysh/wiki/Integrations

Рассмотрим её на примере Laravel. В Laravel PsySH реализован под названием Tinker. Он интегрирован в среду и запускается с помощью консольной утилиты Artisan:

php artisan tinker

Дополнительные команды Tinker

Tinker добавляет в PsySH свои дополнительные команды, ориентированные именно на Laravel. Перечислим их для примерного понимания

  • down - перевести сайт в режим обслуживания
  • up - вывести сайт из режима обслуживания
  • env - показывает название текущей среды окружения приложения (какой файл .env используется)
  • migrate - выполнить миграции
  • inspire - вывести воодушевляющую фразу на экран (пасхалка)
  • Есть и другие команды, такие как clear-compiled и optimize

Возможности

После подключения всего кода приложения мы можем из консоли вызывать любые имеющиеся в приложении библиотеки, делать практически всё тоже самое, что мы можем делать из кода приложения.

Приведу несколько примеров того, что можно делать в консоли, подключив контекст фреймворка:

  • Заполнить БД данными: factory('App\User')->create()
  • Получить первого пользователя из таблицы пользователей из БД: App\User::first()
  • Получить общие настройки приложения: app()
  • Получить текущие дату-время из библиотеки Carbon: now()
  • Выполнить ассершн: local('localhost')->assertResponseOk()
  • Получить страницу сайта: http('google.com')
  • Получить содержимое загруженной предыдущей командой страницы: $_->getBody().''
  • register(app_path('Services')) - зарегистрировали путь, теперь там будут искаться классы, это позволяет обращаться к классам, лежащим по этому пути только по имени, без указания пути: SomeService->getData($someInput);
  • User::where('id'>10) - отобразит текст сгенерированного SQL-запроса к БД
  • $_->get() - получит и отобразит пользователей из предыдущего запроса

Выводы

Интерактивная REPL консоль PsySH позволяет производить интерактивную отладку и исследовательскую разработку.

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

Возможности отладки

Отладка в браузере пока не реализована, поддерживается только встроенный в php браузер, но и REPL-консоль - это не про линейную, а про интерактивную отладку

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

Интерактивная разработка

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

Недостатки

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

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

Нет возможности вывести в консоль графическую информацию, такую как GUI, графики, схемы

Не понятно, как тестировать запросы по API

Аналоги

  • Boris
  • Подобные инструменты появились ранее во многих языках программирования, таких как Ruby и других и активно используются разработчиками. В ruby например есть расширенная версия pry
  • В Python подобный инструмент доступен по-умолчанию, командой python. Что же у них доступно в качестве дополнительных инструментов?

P.S.:

Когда Вы поправите код в своём любимом редакторе и захотите протестировать свой класс в Tinker, то обнаружите, что в нём используется код в состоянии, которое было на момент запуска tinker. Чтобы получить новый код, понадобится перезагрузить Tinker. Для того, чтобы иметь возможность подгружать код без перезагрузки есть отладчик, основанный на tinker, под названием Tinx. В нём есть команда, перезагружающая код, а также несколько magic команд, упрощающих отладку моделей.

Удачи с REPL!

Используемые материалы

https://psysh.org/

https://psysh.org/#docs

https://github.com/bobthecow/psysh

https://www.sitepoint.com/interactive-php-debugging-psysh/

https://presentate.com/bobthecow/talks/php-for-pirates

https://laravel-news.com/laravel-tinker

видео: https://softonsofa.com/tinker-like-a-boss-custom-includes/

https://www.youtube.com/watch?v=KeQThH9tDB0

https://www.youtube.com/watch?v=xgo3klUrpSc

Илья Муромцев 17 марта 2019
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →