Что такое Strangler Fig?
Паттерн Strangler Fig, названный в честь фикуса-душителя, который постепенно окружает и заменяет дерево-хозяина, - это стратегия пошаговой модернизации legacy-систем. Вместо рискованного полного переписывания всей системы за один раз мы постепенно заменяем старую функциональность новой, пока система продолжает работать.
Практический кейс: миграция ASP.NET MVC на ASP.NET Core
Представим, что у нас есть старое приложение на .NET Framework 4.8. Переписывать все сразу слишком рискованно. Вместо этого используем паттерн Strangler Fig.
Вот стартовая точка: стандартный legacy-контроллер, который напрямую обращается к бизнес-сервису.
namespace LegacyMvcApp.Controllers
{
public class LegacyOrdersController : Controller
{
public async Task<ActionResult> Details(int id)
{
// Old direct dependency
var ordersService = new OrderService();
var order = await ordersService.GetById(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
}
}
}
Шаг 1. Поднимаем новый ASP.NET Core API
Сначала создаем новый API. В нем будет современная бизнес-логика и независимые контроллеры.
[Route("api/[controller]")]
[ApiController]
public class OrdersController(IOrdersService ordersService) : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<Order> Get(int id)
{
var order = ordersService.GetById(id);
if (order == null)
{
return NotFound();
}
return Ok(order);
}
}
Шаг 2. Старый MVC начинает вызывать новую систему
Legacy-контроллер остается на месте, а маршруты работают точно так же, как раньше. Но внутри контроллера запрос теперь перенаправляется в новый ASP.NET Core API.
В production лучше использовать
IHttpClientFactory, а не создавать статическийHttpClient.
public class LegacyOrdersController : Controller
{
private static readonly HttpClient _httpClient = new HttpClient();
private static readonly string _newApiBaseUrl =
ConfigurationManager.AppSettings["NewApiBaseUrl"];
public async Task<ActionResult> Details(int id)
{
var url = $"{_newApiBaseUrl}/api/orders/{id}";
// Call the new API to get the order details
var response = await _httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var order = JsonConvert.DeserializeObject<Order>(json);
if (order == null)
{
return HttpNotFound();
}
return View(order);
}
return new HttpStatusCodeResult((int)response.StatusCode);
}
}
Так UI не меняется, URL остаются прежними, но функциональность уже живет в Core.
Преимущества подхода
-
Постепенный процесс. Переносим функциональность по одному endpoint за раз.
-
Минимальный риск. Старая логика остается доступной как fallback, если она понадобится.
-
Тестирование в реальных условиях. Новый API сразу работает под настоящей нагрузкой, но в контролируемом режиме.
-
Без downtime. Пользователи не замечают процесс миграции.
Что происходит после переноса backend?
Когда весь API уже работает на .NET Core, можно начинать следующий этап. Старые MVC Views постепенно заменяются современным frontend: React, Vue или Angular. Старая система постепенно уменьшается, и в конце остается только новая архитектура.
Заключение
Паттерн Strangler Fig - самый безопасный способ модернизировать устаревшие .NET-приложения. Он позволяет постепенно и безболезненно переносить логику в ASP.NET Core, сохраняя стабильность и контроль на каждом шаге.