# 02. Функции и методы
[← Оглавление](./index.md)
---
## Одна функция — одна ответственность (SRP)
**ПЛОХО**
```php
function processLeadAndSendNotification(array $data): void {
// валидация, сохранение в CRM, отправка письма, логирование — всё в одном месте
}
```
**ХОРОШО**
```php
function validateLeadData(array $data): array { /* ... */ }
function createLead(array $validatedData): \Bitrix\Crm\Item { /* ... */ }
function sendLeadNotification(\Bitrix\Crm\Item $lead): void { /* ... */ }
```
---
## Избегайте флаговых аргументов (boolean trap)
**ПЛОХО**
```php
function addProductToDeal(int $dealId, array $productRow, bool $recalculate = true): void {
// добавление товара
if ($recalculate) {
\CCrmDeal::Recalculate($dealId);
}
}
```
**ХОРОШО — ДВА ЯВНЫХ МЕТОДА**
```php
function addProductToDeal(int $dealId, array $productRow): void {
// только добавление товара
}
function addProductToDealAndRecalculate(int $dealId, array $productRow): void {
$this->addProductToDeal($dealId, $productRow);
\CCrmDeal::Recalculate($dealId);
}
```
---
## Количество параметров ≤ 3–4, иначе — DTO
**ПЛОХО**
```php
function updateCompany(int $id, string $title, string $phone, string $email, ?string $address, bool $isActive) { /* ... */ }
```
**ХОРОШО — READONLY DTO (PHP 8.2+)**
```php
readonly class UpdateCompanyDto {
public function __construct(
public string $title,
public string $phone,
public string $email,
public ?string $address = null,
public bool $isActive = true,
) {}
}
function updateCompany(int $id, UpdateCompanyDto $dto): void { /* ... */ }
```
---
## Ранний возврат (early return)
**ПЛОХО — ГЛУБОКАЯ ВЛОЖЕННОСТЬ**
```php
function getDiscountForDeal(\Bitrix\Crm\Item $deal): float {
$discount = 0.0;
if ($deal->getStageId() === 'EXECUTING') {
$client = $deal->getClient();
if ($client && $client->hasActiveSubscription()) {
if ($deal->getOpportunity() > 100000) {
$discount = 0.15;
} else {
$discount = 0.05;
}
}
}
return $discount;
}
```
**ХОРОШО — FLAT-СТРУКТУРА**
```php
function getDiscountForDeal(\Bitrix\Crm\Item $deal): float {
if ($deal->getStageId() !== 'EXECUTING') {
return 0.0;
}
$client = $deal->getClient();
if (!$client || !$client->hasActiveSubscription()) {
return 0.0;
}
return $deal->getOpportunity() > 100000 ? 0.15 : 0.05;
}
```