SRP и дополнительная логика внутри класса - PullRequest
0 голосов
/ 21 марта 2019

Например, у меня есть класс, который выполняет различные запросы к некоторому внешнему 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?

...