Заглушка сервісу (шаблон проєктування)
Заглушка сервісу (англ. Service Stub) — шаблон проєктування, який дозволяє позбутись залежностей від зовнішніх компонентів.
Опис[ред. | ред. код]
Часто система залежить від зовнішніх сервісів. Зовнішні сервіси можуть створювати неочікувані проблеми, їх не можна контролювати та підтримувати. Ненадійність зовнішніх ресурсів викликає проблеми в самій аплікації. При цьому розробка уповільнюється також через неможливість тестувати логіку аплікації.
Рішенням буде робити залежність не на зовнішній сервіс, а на абстракцію. А при потребі (у разі несправності сервісу, чи тестуванні) використовувати заглушку, цього сервісу, яка виконується локально.
Реалізація[ред. | ред. код]
Нехай, наша аплікація містить операції із конвертуванням грошей. Тоді нам необхідний сервіс, який повертатиме курс валют на цю мить. Представимо таку залежність у вигляді абстракцію.
public interface ICurrencyExchange { Task<Money> Convert(Money originalAmount, Currency destinationCurrency); }
Тоді реалізуємо інтерфейси використовуючи необхідний сервіс.
public sealed class CurrencyExchangeService : ICurrencyExchange { private const Uri _exchangeUrl = new Uri("https://api.exchangeratesapi.io/latest?base=USD"); private readonly IHttpClient _httpClient; public CurrencyExchangeService(IHttpClient httpClient) { _httpClient = httpClient; } public async Task<Money> Convert(Money originalAmount, Currency destinationCurrency) { var response = await _httpClient.GetAsync(_exchangeUrl); var usdRates = await response.ReadAsAsync<CurrencyMap>(); decimal usdAmount = usdRates[originalAmount.Currency] / originalAmount.Amount; decimal destinationAmount = usdRates[destinationCurrency] / usdAmount; return new Money(destinationAmount, destinationCurrency); } }
Та щоб уникнути залежності на зовнішній ресурс, напишемо заглушку, яку будемо використовувати при тестах.
public sealed class CurrencyExchangeStub : ICurrencyExchange { private readonly Dictionary<Currency, decimal> _usdRates = new Dictionary<Currency, decimal> { [Currency.Dollar] = 1m, [Currency.Euro] = 0.89021m, }; public Task<Money> Convert(Money originalAmount, Currency destinationCurrency) { decimal usdAmount = this._usdRates[originalAmount.Currency] / originalAmount.Amount; decimal destinationAmount = this._usdRates[destinationCurrency] / usdAmount; var money = new Money(destinationAmount, destinationCurrency) return Task.FromResult(money); } }
Зв'язок з іншими патернами[ред. | ред. код]
- Макет об'єкта та заглушка сервісу часто плутають. Та варто розуміти, що макет об'єкта використовуються для імітації поведінки однієї чи декількох функцій та залежно від умов ця імітація може відрізнятись в той час, як заглушка сервісу замінює цілий сервіс та його реалізація залишається незмінною.
Див. також[ред. | ред. код]
Джерела[ред. | ред. код]
- Service Stub [Архівовано 18 серпня 2020 у Wayback Machine.]