---
title: "Извлечение метода"
type: "refactoring-technique"
slug: "extract-method"
url: "http://localhost:3000/ru/extract-method.md"
category: "Составление методов"
description: "Проблема: У вас есть фрагмент кода, который можно сгруппировать. Решение: Выделите участок кода в новый метод (или функцию) и вызовите этот метод вместо старого кода."
languages: ["java", "csharp", "php", "python", "typescript"]
---
# Извлечение метода

> Проблема: У вас есть фрагмент кода, который можно сгруппировать. Решение: Выделите участок кода в новый метод (или функцию) и вызовите этот метод вместо старого кода.

## Problem

У вас есть фрагмент кода, который можно сгруппировать.

## Solution

Выделите участок кода в новый метод (или функцию) и вызовите этот метод вместо старого кода.

## Why Refactor

Чем больше строк кода в методе, тем сложнее разобраться в том, что он делает. Это основная проблема, которую решает этот рефакторинг.

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

## Benefits

* Улучшает читабельность кода. Постарайтесь дать новому методу название, которое бы отражало суть того, что он делает. Например, `createOrder()`, `renderCustomerInfo()` и т. д.
* Убирает дублирование кода. Иногда код, вынесенный в метод, можно найти и в других местах программы. В таком случае, имеет смысл заменить найденные участки кода вызовом вашего нового метода.
* Изолирует независимые части кода, уменьшая вероятность ошибок (например, по вине переопределения не той переменной).

## How to Refactor

1. Создайте новый метод и назовите его так, чтобы название отражало суть того, что будет делать этот метод.
2. Скопируйте беспокоящий вас фрагмент кода в новый метод. Удалите этот фрагмент из старого места и замените вызовом вашего нового метода.
Найдите все переменные, которые использовались в этом фрагменте кода. Если они были объявлены внутри этого фрагмента и не используются вне его, просто оставьте их без изменений — они станут локальными переменными нового метода.
3. Если переменные объявлены перед интересующим вас участком кода, значит, их следует передать в параметры вашего нового метода, чтобы использовать значения, которые в них находились ранее. Иногда от таких переменных проще избавиться с помощью [замены переменных вызовом метода](/ru/replace-temp-with-query).
4. Если вы видите, что локальная переменная как-то изменяется в вашем участке кода, это может означать, что её изменённое значение понадобится дальше в основном методе. Проверьте это. Если подозрение подтвердилось, значение этой переменной следует возвратить в основной метод, чтобы ничего не сломать.
## Relations

**Helps you do**

- [Замена параметров объектом](/ru/introduce-parameter-object.md)
- [Создание шаблонного метода](/ru/form-template-method.md)
- [Параметризация метода](/ru/parameterize-method.md)

**Similar techniques**

- [Перемещение метода](/ru/move-method.md)

**Opposite refactorings**

- [Встраивание метода](/ru/inline-method.md)

**Eliminates smells**

- [Дублирование кода](/ru/smells/duplicate-code.md)
- [Длинный метод](/ru/smells/long-method.md)
- [Завистливые функции](/ru/smells/feature-envy.md)
- [Операторы switch](/ru/smells/switch-statements.md)
- [Цепочка вызовов](/ru/smells/message-chains.md)
- [Комментарии](/ru/smells/comments.md)
- [Класс данных](/ru/smells/data-class.md)

## Code Examples

### java

```java
// Before
void printOwing() {
  printBanner();

  // Print details.
  System.out.println("name: " + name);
  System.out.println("amount: " + getOutstanding());
}

// After
void printOwing() {
  printBanner();
  printDetails(getOutstanding());
}

void printDetails(double outstanding) {
  System.out.println("name: " + name);
  System.out.println("amount: " + outstanding);
}
```

### csharp

```csharp
// Before
void PrintOwing() 
{
  this.PrintBanner();

  // Print details.
  Console.WriteLine("name: " + this.name);
  Console.WriteLine("amount: " + this.GetOutstanding());
}

// After
void PrintOwing()
{
  this.PrintBanner();
  this.PrintDetails();
}

void PrintDetails()
{
  Console.WriteLine("name: " + this.name);
  Console.WriteLine("amount: " + this.GetOutstanding());
}
```

### php

```php
// Before
function printOwing() {
  $this->printBanner();

  // Print details.
  print("name:  " . $this->name);
  print("amount " . $this->getOutstanding());
}

// After
function printOwing() {
  $this->printBanner();
  $this->printDetails($this->getOutstanding());
}

function printDetails($outstanding) {
  print("name:  " . $this->name);
  print("amount " . $outstanding);
}
```

### python

```python
// Before
def printOwing(self):
    self.printBanner()

    # print details
    print("name:", self.name)
    print("amount:", self.getOutstanding())

// After
def printOwing(self):
    self.printBanner()
    self.printDetails(self.getOutstanding())

def printDetails(self, outstanding):
    print("name:", self.name)
    print("amount:", outstanding)
```

### typescript

```typescript
// Before
printOwing(): void {
  printBanner();

  // Print details.
  console.log("name: " + name);
  console.log("amount: " + getOutstanding());
}

// After
printOwing(): void {
  printBanner();
  printDetails(getOutstanding());
}

printDetails(outstanding: number): void {
  console.log("name: " + name);
  console.log("amount: " + outstanding);
}
```

