diff --git a/resources/views/library/actions.blade.php b/resources/views/library/actions.blade.php index 96488b41..0695da78 100644 --- a/resources/views/library/actions.blade.php +++ b/resources/views/library/actions.blade.php @@ -1,16 +1,13 @@ @extends('layout') @section('title', 'Один класс — одна задача') -@section('description', 'Каждый класс в приложении должен отвечать только за одну конкретную задачу или функциональность.') +@section('description', 'Каждый класс в приложении должен отвечать только за одну конкретную задачу.') @section('content') - - Чистота и порядок + + Ясность с первого взгляда Один класс — одна задача - Каждый класс в приложении должен отвечать только за одну конкретную задачу или функциональность. - - - + Каждый класс в приложении должен сосредоточиться на выполнении одной конкретной задачи или функции @@ -18,6 +15,7 @@ $sections = collect([ 'basics', 'focus', + 'package', 'conventions', 'tests', ]) diff --git a/resources/views/library/index.blade.php b/resources/views/library/index.blade.php index db088801..ab6788a9 100644 --- a/resources/views/library/index.blade.php +++ b/resources/views/library/index.blade.php @@ -17,7 +17,7 @@
-
+
@@ -74,7 +74,7 @@ class="link-body-emphasis text-decoration-none icon-link icon-link-hover stretch
-
+
    @@ -95,6 +95,25 @@ class="link-body-emphasis text-decoration-none icon-link icon-link-hover stretch
+ + +
+
+
+

Действия

+

+ Класс должен сосредоточиться на выполнении одной конкретной задачи +

+ + + Начать читать + + +
+
+
+
diff --git a/storage/library/actions/basics.md b/storage/library/actions/basics.md index 3cf44344..e8fe839f 100755 --- a/storage/library/actions/basics.md +++ b/storage/library/actions/basics.md @@ -1,21 +1,20 @@ --- title: "Основы" -description: "Что такое принцип 'Один класс — одна задача'?" +description: "Что такое принцип One Class, One Task?" --- -Принцип «Один класс — одна задача» (One Class, One Task) предполагает, что каждый класс в приложении должен отвечать -только за одну конкретную задачу или функциональность. Это упрощает структуру кода, делает его более понятным и легким -для поддержки. В контексте Laravel этот подход помогает организовать бизнес-логику в виде отдельных классов, которые -выполняют конкретные действия, что позволяет избежать перегруженности классов и улучшает читаемость кода. - -Преимущества использования принципа «Один класс — одна задача»: - -- **Читаемость кода**: каждый класс отвечает только за одну задачу, что упрощает понимание его назначения и логики. -- **Поддерживаемость**: изменение и тестирование классов становится проще, так как каждый класс содержит только одну - задачу. -- **Изоляция логики**: каждый класс действия изолирован от других частей приложения, что упрощает его тестирование и - поддержку. -- **Повторное использование**: классы действий могут быть повторно использованы в разных частях приложения, что - упрощает разработку и поддержку кода. -- **Улучшение архитектуры**: применение принципа «Один класс — одна задача» помогает улучшить архитектуру вашего - приложения, сделав его более гибким и масштабируемым. +Принцип «Один класс — одна задача» (`One Class, One Task`) устанавливает требование, согласно которому каждый класс в приложении должен выполнять лишь одну конкретную задачу или функциональность. Этот подход способствует созданию более структурированного и предсказуемого кода, а также облегчает его поддержку. + +В Laravel это позволяет выделить бизнес-логику в отдельные классы, что освобождает контроллеры и модели от лишних обязанностей и улучшает организацию и читаемость кода. + +##### Что это даст? + +- **Читаемость кода**: Наличие класса, отвечающего за единую задачу, значительно упрощает понимание его назначения и поведения. Это особенно важно в рамках командной разработки или при возвращении к проекту спустя значительное время, так как открыв класс, разработчик может быстро оценить его функциональность. + +- **Простота тестирования**: Изолирование логики в небольшие классы упрощает процесс тестирования. Каждый класс может быть протестирован независимо, что повышает точность и снижает время, необходимое для написания тестов. + +- **Снижение сложности**: Логика приложения становится более управляемой, когда она разбивается на мелкие, специализированные части. Такой подход способствует снижению уровня сложности кода и облегчает его восприятие. + +- **Легкость изменений**: Внесение изменений в код становится проще, когда изменения касаются небольших классов, каждое из которых отвечает за одну задачу. Это предотвращает возникновение неожиданностей при редактировании, так как изменения в одной части приложения не затрагивают другие компоненты. + +Тем не менее, важно сохранять баланс между дроблением логики на мелкие классы и чрезмерной детализацией. Не все аспекты логики следует выносить в отдельные классы, необходимо учитывать контекст. diff --git a/storage/library/actions/conventions.md b/storage/library/actions/conventions.md index 3f3a4f0c..1e2280e1 100644 --- a/storage/library/actions/conventions.md +++ b/storage/library/actions/conventions.md @@ -3,16 +3,20 @@ title: "Рекомендуемые соглашения" description: "Помогут вам оставаться последовательными при организации вашего приложения" --- -**Начните с глагола** -Назовите свои классы действий как небольшие явные предложения, начинающиеся с глагола. Например, действие, которое -«отправляет электронное письмо пользователю для сброса пароля», можно назвать `SendResetPasswordEmail`. Такой подход -делает названия классов самодокументированными и легко понятными, что улучшает читабельность кода. +Для упрощения поддержки и организации кода целесообразно придерживаться ряда рекомендаций при создании классов действий. -**Используйте папку `Actions`** +##### Начните с глагола -Создайте папку `app/Actions` и сгруппируйте свои действия внутри неё по темам. Это помогает поддерживать структуру -вашего кода организованной и логичной. Например: +Названия классов действий должны представлять собой глаголы, отражающие выполняемую задачу. + +Например, если класс предназначен для отправки письма для сброса пароля, его следует назвать `SendResetPasswordEmail`. + + +##### Используйте директорию `Actions` + +Создайте папку `app/Actions` и сгруппируйте свои действия внутри неё по модулям. +Это поможет поддерживать структуру вашего кода организованной и логичной. Например: ```php app/ @@ -41,8 +45,8 @@ app/ └── ... ``` -В качестве альтернативы, если ваше приложение уже разделено на темы — или модули — вы можете создать папку `Actions` под -каждым из этих модулей. Например: +Если ваше приложение уже разделено на модули - создайте директорию `Actions` в +каждом из них: ```php app/ @@ -59,4 +63,4 @@ app/ └── ... ``` -Такая организация помогает вам поддерживать порядок в коде и упрощает его навигацию. +Такая организация поможет вам поддерживать порядок в коде и упростит навигацию. diff --git a/storage/library/actions/focus.md b/storage/library/actions/focus.md index 5b760b15..d34c4f51 100755 --- a/storage/library/actions/focus.md +++ b/storage/library/actions/focus.md @@ -1,12 +1,12 @@ --- title: "Фокус на работе приложения" -description: "Что такое принцип 'Один класс — одна задача'?" +description: "Использование Actions позволяет сосредоточиться на бизнес-логике приложения, а не на технических деталях." --- -Использование `Actions` позволяет сосредоточиться на бизнес-логике приложения, а не на технических деталях. Классы `Action` выполняют конкретные задачи и изолируют их от других частей приложения, что упрощает понимание кода и его поддержку. Логика, связанная с выполнением одной задачи, собирается в одном месте, что облегчает её изменение и тестирование. +Пример класса действия: ```php class GenerateReservationCode @@ -29,49 +29,9 @@ class GenerateReservationCode } ``` -Это позволит вам вызывать объект класса, как если бы он был функцией. Например: +Данный класс можно вызвать как функцию: + ```php $generator = new GenerateReservationCode(); $reservationCode = $generator(8); // Генерация кода длиной 8 символов ``` - - -В это системе Laravel есть прекрасный пакет `Laravel Actions` — это пакет, который предлагает новый способ организации -логики вашего Laravel-приложения, сосредоточив внимание на действиях, которые выполняет ваше приложение. Вместо создания -контроллеров, джобов, слушателей и других элементов, этот пакет позволяет создавать PHP-классы, каждый из которых -выполняет одну конкретную задачу. Эти классы можно запускать как угодно: из контроллеров, консольных команд, событий и -так далее. - -```php -class GenerateReservationCode -{ - use AsAction; - - const UNAMBIGUOUS_ALPHABET = 'BCDFGHJLMNPRSTVWXYZ2456789'; - - public function handle(int $characters = 7): string - { - do { - $code = $this->generateCode($characters); - } while(Reservation::where('code', $code)->exists()); - - return $code; - } - - protected function generateCode(int $characters): string - { - return substr(str_shuffle(str_repeat(static::UNAMBIGUOUS_ALPHABET, $characters)), 0, $characters); - } -} -``` - -и вызывать его так: -```php -GenerateReservationCode::run() // Генерация кода длиной 7 символов -``` - -> **Примечание** Вы можете узнать больше об удобстве использование действий с пакетом `Laravel Actions` на его [официальном сайте](https://laravelactions.com/). - -Но вам не обязательно использовать пакет, чтобы следовать принципу «Один класс — одна задача». Вы можете создавать свои -собственные классы действий, используя стандартные средства Laravel/PHP. Важно помнить, что главная цель — разделить логику -вашего приложения на небольшие, легко понимаемые и поддерживаемые части. diff --git a/storage/library/actions/package.md b/storage/library/actions/package.md new file mode 100644 index 00000000..25c161ca --- /dev/null +++ b/storage/library/actions/package.md @@ -0,0 +1,49 @@ +--- +title: "Пакет Laravel Actions" +description: "Действие можно удобно запустить как объект, контроллер, фоновую задачу и консольную команду." +--- + +В экосистеме Laravel есть прекрасный пакет `Laravel Actions` который способствует организации кода вокруг действий. +Данный пакет позволяет создавать классы действий, которые могут быть вызваны в различных контекстах, таких как контроллеры, события и консольные команды. +Это обеспечивает более универсальный и гибкий код. + + +Пример использования: + +```php +class GenerateReservationCode +{ + use AsAction; + + const UNAMBIGUOUS_ALPHABET = 'BCDFGHJLMNPRSTVWXYZ2456789'; + + public function handle(int $characters = 7): string + { + do { + $code = $this->generateCode($characters); + } while(Reservation::where('code', $code)->exists()); + + return $code; + } + + protected function generateCode(int $characters): string + { + return substr(str_shuffle(str_repeat(static::UNAMBIGUOUS_ALPHABET, $characters)), 0, $characters); + } +} +``` + +Класс можно вызвать следующим образом: + +```php +GenerateReservationCode::run() +``` + +Если вам нужно выполнить действие в очереди, то вы так же можете это сделать, например: + +```php +GenerateReservationCode::dispatch(); +``` + +> **Примечание** Вы можете узнать больше об удобстве использование действий с пакетом `Laravel Actions` на его [официальном сайте](https://laravelactions.com/). + diff --git a/storage/library/actions/tests.md b/storage/library/actions/tests.md index bca4089a..ef8c27a8 100644 --- a/storage/library/actions/tests.md +++ b/storage/library/actions/tests.md @@ -5,3 +5,30 @@ description: "Что такое принцип 'Один класс — одна Поскольку каждый `Action` отвечает за одну задачу, его тестирование становится более простым и эффективным. Вы можете изолировать и протестировать каждое действие отдельно, что упрощает написание и выполнение тестов. + +```php +class GenerateReservationCodeTest extends TestCase +{ + public function testGeneratedCodeContainsOnlyAllowedCharacters(): void + { + $code = GenerateReservationCode::run(8); + + $this->assertMatchesRegularExpression( + '/^[BCDFGHJLMNPRSTVWXYZ2456789]+$/', + $code + ); + } + + public function testGeneratedCodeIsUrlSafe(): void + { + $code = GenerateReservationCode::run(); + + $this->assertTrue( + filter_var($code, FILTER_VALIDATE_URL) === false + ); + } +} +``` + +А наличие четко определенных входных и выходных данных позволят легко +обнаруживать и исправлять ошибки.