нашёл такой замечательный комментарий в коде, который обращается к базе oracle и вытаскивает только одну страницу выборки 😀

нашёл такой замечательный комментарий в коде, который обращается к базе oracle и вытаскивает только одну страницу выборки 😀

И раз уж начал писать про свои пакеты, то вот ещё один, тоже для yii2: https://github.com/ddruganov/yii2-api-essentials
Его суть в том, что при разработке апи постоянно нужны одни и те же повторяющиеся элементы, без которых уже совсем неудобно работать и которые из раза в раз доказывают свою полезность. Среди них, кстати, есть и вышеупомянутый ExecutionResult 🙂 а так же всякие сильно недостающие исключения типа NotImplementedException.
Пакет небольшой, но пока работал над системой авторизации появилось много мыслей по доработке, потихоньку буду допиливать
Наконец-то закончил доделывать систему единой авторизации для всех своих текущих и будущих сервисов.
Все пакеты, которые в этом деле участвуют, написаны для yii2 на php8.1.
1. https://github.com/ddruganov/yii2-api-auth
Это основной пакет и он управляет основным сервером авторизации. На этот сервер вы отправляете пользователей логиниться/регистрироваться, а в дальнейшем на этом сервере проверяете и обновляете токены авторизации. На этот же сервер уходит запрос для выхода из аккаунта.
Так же, вся работа по определению доступа пользователей к ресурсам производится на этом же сервере через rbac. Каждое разрешение пользователя привязано к определённому приложению из заданного реестра. Кстати, сам учёт приложений в вашей сети ведётся здесь же.
2. https://github.com/ddruganov/yii2-api-auth-proxy
Этот пакет проксирует все вызовы авторизации и проверки прав на основной сервер авторизации. Здесь дублируются все экшены из первого пакета, так что при желании можно заменить один пакет другим за минимальное время не теряя в функционале.
Планируется этот пакет перенести на c#, так это будет делом простым, а пощупать разработку апи на шарпе хочется уже слишком давно.
Так как я только закончил работу над пакетами, то многие моменты там оставляют желать лучшего, из самых ярких: readme, тесты и эндпоинты создания ролей/разрешений/приложений. В ближайшую неделю постараюсь с этим разобраться, пока главное, что это всё работает)
А вот и сам скриншот. Почему-то в прошлом сообщение ограничение по символам не дало прикрепить

Сегодня я очень рад и доволен собой!
Последние 26 часов я делал телеграм-бота для местного водоканала.
Бот представляет из себя урезанный, но от того не менее полезный, функционал личного кабинета.
Зная заказчиков, конкретно телеграмом дело не обойдётся и потому было принятно решение пилить независимое решение, чтобы можно было его подогнать под любую платформу, которая этих ботов поддерживает.
В прошлом я уже делал бота для этой компании, правда там функционал был совсем небольшой: всего лишь передача показаний по счётчикам. Тот бот был написан на коленке и как можно скорее, а потому не имел за собой никаких тестов и перед выдачей проверялся просто руками. Всё это привело к тому, что бот всё-таки работает, но развивать его нереально. В этот раз, естественно, всё делалось через тесты.
Так как изначально курс был взят на независимость от платформы, то тесты и DI показали себя здесь в полной красе. Я теперь официально в эту тему влюблён.
Все зависимости от внешних сервисов, базы и тд были вынесены за интерфейсы и через DI вместо них подключались самые простецкие заглушки.
Таким образом, мне абсолютно ничего не мешало пилить чистый функционал бота и формировать свои требования к формату входных и выходных данных, независимых от конкретного бота.
В качестве выходных данных были выбраны «сообщение» (обёртка над строкой) и «действия» (простые dto с описанием того что надо будет сделать и каким текстом это показать пользователю).
Все популярные платформы поддерживают подобные схемы в том или ином виде.
На приложенном скриншоте показано как это выглядит в итоге в телеграме.
Кстати, разработки обёртки, которая отдаёт данные в машину и отправляет ответ пользователю, заняла около часа + ещё час ушёл на мелкие доработки, вроде удаления кнопок действия после того как пользователь выбрал одно из действий. В итоге сильно выиграем в дальнейшем при разработке ботов для других платформ.
Добавление же новых кнопок или состояний будет тоже занимать мало времени: добавляем «действие», его обработчик, пишем небольшой тест и в продакшен.
В общем, это был очень полезный опыт разработки отдельно от внешней среды. Хоть я и раньше знал как это всё делается, но пощупать в таком масштабе этот приём крайне интересно.
У Макконелла в «совершенном коде» иногда попадаются крайне интересные аналогии, вот одна из них

Краткая инструкция по работе с ключами для деплоя, чтобы каждый раз не гуглить:
1. создаём ключ через ssh-keygen -t rsa2. путь указываем любой, желательно чтобы он содержал в себе название репозитория
3. делаем cat /путь/до/ключа.pub и вывод добавляем в delpoy keys своего git-сервиса (в gitlab это settings -> repository -> deploy keys)
4. проверяем: ssh -T your-username@your-git-server.com5. заставляем git ходить на сервер именно с этим ключом: ssh-agent sh -c 'ssh-add /путь/до/ключа; git pull;'6. вы великолепны
вместо git pull можно подставить любую другую операцию, просто в моём случае репозиторий уже был развёрнут на сервере
Когда я начал работать с Yii2, то меня вполне устраивало, что в результате выполнения любого метода на объекте можно вернуть true/false, потому как если какие-то ошибки и были, то их всегда можно было потом вытянуть через getErrors(). Или, того хуже, можно было кинуть исключение, а выше его отловить и использовать сообщение исключения где-нибудь дальше.
Однако, с течением времени в голову начали закрадываться мысли, что было бы неплохо, если бы результат выполнения метода сам рассказывал как всё прошло, успешно ли и где я там накосячил, а так же возвращал данные, сформированные в ходе выполнения.
Таким образом родился ExecutionResult — data transfer object для получения данных о результате работы формы. В данном случае под формой подразумевается класс, принимающий и валидирующий входные данные, а затем выполняет над этими данные необходимые операции. Это позволило решить две проблемы:
1. Результат работы формы теперь содержался в одном объекте, мне не приходится больше в трех строках кода вытягивать те или иные данные после выполнения
2. Инкапсуляция восторжествовала: форма стала по-настоящему чёрным ящиком — она отдаёт только те данные (ошибки, объекты или сообщение об исключении), которые посчитает нужным
Конечно, это не панацея и всё должно быть в меру, но, как мне кажется, решение вышло достаточно простым и удобным.
Собственно, сам интерфейс ExecutionResult:
⁃ bool $success
⁃ mixed $data
⁃ array $errors
⁃ string $exception
В имплементации это всё обёрнуто геттерами и имеет и несколько статических методов для быстрой генерации того или иного варианта.
Кстати, из-за такой структуры ExecutionResult удобно использовать как ответ на api-запрос.
P.S. Буду рад услышать какую-либо критику в адрес этого метода, либо запрос на пример использования в конкретной ситуации
Сегодня через тесты писал систему авторизации в новом проекте. Заметил, что по сравнению с практически любыми другими тестами они выполнялись очень медленно, хотя там работы ноль — сравнить почту и пароль в базе. Даже тесты на создание заказа с тяжёлыми запросами и логикой выполняются в среднем быстрее.
Полез искать в чём дело и выяснил, что всё упирается в функцию password_hash(). Как оказалось, она намеренно сделана медленной для повышения безопасности. Грустно, конечно, но оптимизировать безопасность, пожалуй, дело не самое лучшее.
Подробнее тут: https://stackoverflow.com/questions/30215781/why-is-password-hashing-e-g-phps-password-hash-so-slow
Написал это в пятницу утром и наконец-то дискуссия началась, правда, почему-то с бухгалтером, которая спросила что это значит, а не с программистами🤔
