Роберт

Backend-разработчик
Пишу о программировании, музыке, книгах и жизни

Блог

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

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

Чистая архитектура. Искусство разработки программного обеспечения

"Идеальный программист" и "Чистый код" - легендарные бестселлеры Роберта Мартина - рассказывают, как достичь высот профессионализма. "Чистая архитектура" продолжает эту тему, но не предлагает несколько вариантов в стиле "решай сам", а объясняет, что именно следует делать, по какой причине и почему именно такое решение станет принципиально важным для вашего успеха. Роберт Мартин дает прямые и лаконичные ответы на ключевые вопросы архитектуры и дизайна. "Чистую архитектуру" обязаны прочитать разработчики всех уровней, системные аналитики, архитекторы и каждый программист, который желает подняться по карьерной лестнице или хотя бы повлиять на людей, которые занимаются данной работой. Все архитектуры подчиняются одним и тем же правилам!
Читать

Yii::t('app', 'message') -> trans('app.category.sub_category.message')

Переопределяем метод PhpMessageSource::loadMessages()


namespace app\components;

use Yii;

class PhpMessageSource extends \yii\i18n\PhpMessageSource
{
    protected function loadMessages($category, $language)
    {
        $newCategory = $category;
        $keys = [];
        if (false !== strpos($category, '.')) {
            $keys = explode('.', $category);
            $newCategory = array_shift($keys);
        }
        $messageFile = $this->getMessageFilePath($newCategory, $language);
        $messages = $this->loadMessagesFromFile($messageFile);

        if (false !== strpos($category, '.')) {
            $messages = $this->searchKey($messages, $keys);
        }

        $fallbackLanguage = substr($language, 0, 2);
        $fallbackSourceLanguage = substr($this->sourceLanguage, 0, 2);

        if ($language !== $fallbackLanguage) {
            $messages = $this->loadFallbackMessages($newCategory, $fallbackLanguage, $messages, $messageFile);
        } elseif ($language === $fallbackSourceLanguage) {
            $messages = $this->loadFallbackMessages($newCategory, $this->sourceLanguage, $messages, $messageFile);
        } else {
            if ($messages === null) {
                Yii::warning("The message file for category '$newCategory' does not exist: $messageFile", __METHOD__);
            }
        }

        return (array)$messages;
    }

    private function searchKey($messages, $keys)
    {
        $keyCurrent = array_shift($keys);

        if (array_key_exists($keyCurrent, $messages) && is_array($messages[$keyCurrent])) {
            if (!$keys) {
                return $messages[$keyCurrent];
            }

            return $this->searchKey($messages[$keyCurrent], $keys);
        }
    }
}

В конфиге приложения для компонента i18n указываем наш класс:


'components' => [
    ...
    'i18n' => [
            'translations' => [
                '*' => [
                    'class' => \app\components\PhpMessageSource::class,
    ...

Добавляем глобальную функцию, которая будет оберткой для стандартного вызова метода Yii::t()


function trans(string $message)
{
    return Yii::t($message, substr(strrchr($message, '.'), 1));
}

Теперь в файлах переводов можно указывать переводы с категориями


'access_denied' => 'Доступ закрыт',
'category' => [
    'sub_category' => [
        'message' => 'Сообщение',
    ],
],

Интернационализация Yii2 а-ля Laravel

I18n а-ля Laravel
Читать

Бек Кент.  Экстремальное программирование. Разработка через тестирование

Возвращение знаменитого бестселлера. Изящный, гибкий и понятный код, который легко модифицировать, который корректно работает и который не подкидывает своим создателям неприятных сюрпризов. Неужели подобное возможно? Чтобы достичь цели, попробуйте тестировать программу еще до того, как она написана. Именно такая парадоксальная идея положена в основу методики TDD (Test-Driven-Development – разработка, основанная на тестировании). Бессмыслица? Не спешите делать скороспелые выводы. Рассматривая применение TDD на примере разработки реального программного кода, автор демонстрирует простоту и мощь этой методики. В книге приведены два программных проекта, целиком и полностью реализованных с использованием TDD. За рассмотрением примеров следует обширный каталог приемов работы в стиле TDD, а также паттернов и рефакторингов, имеющих отношение к TDD. Книга будет полезна для любого программиста, желающего повысить производительность своей работы и получить удовольствие от программирования.
Читать

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

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

Причина 2 (Удобство). Легче использовать единичные имена, чем множественные. Объекты могут иметь неправильное множественное число или вообще не иметь множественное число, но всегда будут иметь единственное число, за некоторыми исключениями, такими как, например, "новости - news"):

  • Customer
  • Order
  • User
  • Status
  • News

Причина 3 (Эстетика и порядок). Особенно в сценариях "мастер-детали", он лучше читается, лучше выравнивается по имени и имеет более логичный порядок (сначала мастер, потом детали):

  • Order
  • OrderDetail

В сравнении с:

  • OrderDetails
  • Orders

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

  • Customer
  • Customer.CustomerID
  • CustomerAddress
  • class Customer {...}
  • SELECT FROM Customer WHERE CustomerID = 100

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

Причина 5 (Глобализация). Мир становится меньше, у вас может быть команда разных национальностей, не все из них знают английский как родной язык. Для программиста, не являющегося носителем английского языка, было бы проще думать о "Репозитории", чем о "Репозиториях" или 'Статусе" вместо "Статусы". Наличие единичных имен может привести к меньшему количеству ошибок, вызванных опечатками, сэкономить время, не думая "это ребенок или дети?", следовательно, повысить производительность.

Причина 6 (Почему нет?). Это может даже сэкономить ваше время записи, сэкономить дисковое пространство и даже продлить срок службы клавиатуры вашего компьютера!

SELECT Customer.CustomerName FROM Customer WHERE Customer.CustomerID = 100
SELECT Customer.CustomerName FROM Customer WHERE Customer.CustomerID = 100

Вы сохранили 3 буквы, 3 байта, 3 дополнительных нажатия клавиш 🙂

Дилемма имен таблиц: сингулярные или множественные имена

Размышления о именовании таблиц базы данных
Читать

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

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

class EventDispatcher extends Component
{ 
    public function dispatch($event)
    {
        $this->trigger(get_class($event), $event);
    }
}

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

В таком случае я действительно хочу временно назначить \Yii::$app->eventDispatcher PHPUnit Mock Class, чтобы я мог переопределить возвращаемое значение метода dispatch(), например

$eventDispatcherMock = $this->getMockClass(EventDispatcher::class, ['dispatch']);
\Yii::$app->set('eventDispatcher', $eventDispatcherMock);

После данных преобразований метод dispatch() будет возвращать null, следовательно события вызвано не будет.

мОкаем компонент Yii2

мОкаем компонент Yii2
Читать

Подпишитесь на обновления