Что такое 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