Skip to content

Commit

Permalink
Init Action page for library
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuna committed Sep 9, 2024
1 parent 08e7e41 commit 56e3c6d
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 0 deletions.
29 changes: 29 additions & 0 deletions resources/views/library/actions.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@extends('layout')
@section('title', 'Один класс — одна задача')
@section('description', 'Каждый класс в приложении должен отвечать только за одну конкретную задачу или функциональность.')
@section('content')

<x-header align="align-items-end">
<x-slot name="sup">Чистота и порядок</x-slot>
<x-slot name="title">Один класс — одна задача</x-slot>
<x-slot name="description">
Каждый класс в приложении должен отвечать только за одну конкретную задачу или функциональность.
</x-slot>
<x-slot name="content">
<img src="/img/gusli.svg" class="img-fluid d-block mx-auto">
</x-slot>
</x-header>

@php
$sections = collect([
'basics',
'focus',
'conventions',
'tests',
])
->map(fn ($file) => \Illuminate\Support\Str::of($file)->start('actions/'))
->map(fn ($file) => new \App\Library($file));
@endphp

@include('particles.library-section', ['sections' => $sections])
@endsection
1 change: 1 addition & 0 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
Route::view('/library/how-to-ask', 'library.how-to-ask')->name('library.how-to-ask');
Route::view('/library/collection', 'library.collection')->name('library.collection');
Route::view('/library/solid', 'library.solid')->name('library.solid');
Route::view('/library/actions', 'library.actions')->name('library.actions');
/*
|--------------------------------------------------------------------------
| Open Quiz
Expand Down
21 changes: 21 additions & 0 deletions storage/library/actions/basics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: "Основы"
description: "Что такое принцип 'Один класс — одна задача'?"
---

Принцип «Один класс — одна задача» (One Class, One Task) предполагает, что каждый класс в приложении должен отвечать
только за одну конкретную задачу или функциональность. Это упрощает структуру кода, делает его более понятным и легким
для поддержки. В контексте Laravel этот подход помогает организовать бизнес-логику в виде отдельных классов, которые
выполняют конкретные действия, что позволяет избежать перегруженности классов и улучшает читаемость кода.

Преимущества использования принципа «Один класс — одна задача»:

- **Читаемость кода**: каждый класс отвечает только за одну задачу, что упрощает понимание его назначения и логики.
- **Поддерживаемость**: изменение и тестирование классов становится проще, так как каждый класс содержит только одну
задачу.
- **Изоляция логики**: каждый класс действия изолирован от других частей приложения, что упрощает его тестирование и
поддержку.
- **Повторное использование**: классы действий могут быть повторно использованы в разных частях приложения, что
упрощает разработку и поддержку кода.
- **Улучшение архитектуры**: применение принципа «Один класс — одна задача» помогает улучшить архитектуру вашего
приложения, сделав его более гибким и масштабируемым.
62 changes: 62 additions & 0 deletions storage/library/actions/conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: "Рекомендуемые соглашения"
description: "Помогут вам оставаться последовательными при организации вашего приложения"
---

**Начните с глагола**

Назовите свои классы действий как небольшие явные предложения, начинающиеся с глагола. Например, действие, которое
«отправляет электронное письмо пользователю для сброса пароля», можно назвать `SendResetPasswordEmail`. Такой подход
делает названия классов самодокументированными и легко понятными, что улучшает читабельность кода.

**Используйте папку `Actions`**

Создайте папку `app/Actions` и сгруппируйте свои действия внутри неё по темам. Это помогает поддерживать структуру
вашего кода организованной и логичной. Например:

```php
app/
├── Actions/
│ ├── Authentication/
│ │ ├── LoginUser.php
│ │ ├── RegisterUser.php
│ │ ├── ResetUserPassword.php
│ │ └── SendResetPasswordEmail.php
│ ├── Leads/
│ │ ├── BulkRemoveLead.php
│ │ ├── CreateNewLead.php
│ │ ├── GetLeadDetails.php
│ │ ├── MarkLeadAsCustomer.php
│ │ ├── MarkLeadAsLost.php
│ │ ├── RemoveLead.php
│ │ ├── SearchLeadsForUser.php
│ │ └── UpdateLeadDetails.php
│ └── Settings/
│ ├── GetUserSettings.php
│ ├── UpdateUserAvatar.php
│ ├── UpdateUserDetails.php
│ ├── UpdateUserPassword.php
│ └── DeleteUserAccount.php
├── Models/
└── ...
```

В качестве альтернативы, если ваше приложение уже разделено на темы — или модули — вы можете создать папку `Actions` под
каждым из этих модулей. Например:

```php
app/
├── Authentication/
│ ├── Actions/
│ ├── Models/
│ └── ...
├── Leads/
│ ├── Actions/
│ ├── Models/
│ └── ...
└── Settings/
├── Actions/
└── ...
```

Такая организация помогает вам поддерживать порядок в коде и упрощает его навигацию.
77 changes: 77 additions & 0 deletions storage/library/actions/focus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: "Фокус на работе приложения"
description: "Что такое принцип 'Один класс — одна задача'?"
---

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


```php
class GenerateReservationCode
{
const UNAMBIGUOUS_ALPHABET = 'BCDFGHJLMNPRSTVWXYZ2456789';

public function __invoke(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
$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. Важно помнить, что главная цель — разделить логику
вашего приложения на небольшие, легко понимаемые и поддерживаемые части.
7 changes: 7 additions & 0 deletions storage/library/actions/tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Тестирование"
description: "Что такое принцип 'Один класс — одна задача'?"
---

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

0 comments on commit 56e3c6d

Please sign in to comment.