Например, у меня есть класс, который выполняет различные запросы к некоторому внешнему API:
internal class ServiceCore : IDisposable
{
public ServiceCore(IConfiguration configuration, Func<HttpMessageHandler> handler)
{
_configuration = configuration;
_handler = handler;
devKey = _configuration.GetSection("ApiBillCom:DevKey").Value;
client = new HttpClient(_handler())
{
BaseAddress = new Uri(_configuration.GetSection("ApiBillCom:ApiUrl").Value)
};
if (_sessionId == null || !_sessionId.IsValueCreated)
SetSessionId();
}
public async Task<JToken> ListJTokenAsync(int start, int count, string endpoint, bool nested = false, List<FilterData> filterData = null)
{
//....
}
public async Task<List<T>> ListAsync<T>(string endpoint, int start, int count, bool nested = false, List<FilterData> filterData = null)
{
//.....
}
хорошо, но каждый вызов требует sessionId, который мы можем получить, вызывая метод LoginAsync
раньше. Этот LoginAsync
метод может быть закрытым методом внутри этого ServiceCore
класса:
private void SetSessionId()
{
_sessionId = null;
LoginCore loginCore = new LoginCore(_configuration, _handler);
_sessionId = new Lazy<string>(() => LoginAsync().Result);
}
private async Task<string> LoginAsync()
{
но тогда, похоже, единичный ответственный принцип нарушается (потому что тогда ServiceCode
имеет 2 обязанности, получает (или помещает) данные в API и поддерживает сессию. Я произвел рефакторинг и переместил его в специальный класс:
internal class LoginCore
{
private readonly IConfiguration _configuration;
private readonly Func<HttpMessageHandler> _handler;
public LoginCore(IConfiguration configuration, Func<HttpMessageHandler> handler)
{
_configuration = configuration;
_handler = handler;
}
internal async Task<string> LoginAsync(string devKey)
{
// ....
}
}
Сейчас нет нарушений SRP, у каждого класса есть только одна обязанность (ServiceCore
- работа с API, LoginCore
- получение фактического sessionId), но я не уверен, что мне нужно это делать (отдельный рабочий процесс входа в систему в другой класс). Прямо сейчас мне нужно передать один параметр в LoginAsync (с закрытым методом мне не нужно это делать, потому что devKey
является частным свойством внутри ServiceCore
), я должен написать конструктор для LoginCore
и передать те же параметры внедрения зависимости, который я передал ServiceCore
. Я должен создать LoginCore
экземпляр перед вызовом LoginAsync
Я не буду использовать это LoginCore
где-то еще, только в ServiceCore
, мне не нужно вводить зависимости (поскольку мне не нужно заменять LoginCore
, метод LoginAsync
актуален для любых вызовов.
Я вижу только одно преимущество: я могу пометить LoginCore
как:
[assembly: InternalsVisibleTo("BillComRealTest")]
и написать модульный тест специально только для метода LoginAsync
, с макетом HttpMessageHandler
.
Должен ли я создать этот отдельный класс с одним методом для последующего SRP или достаточно, чтобы создать только приватный метод внутри ServiceCore
?