Ревью кода и улучшение структуры сервиса организации

Нужно убрать ToList перед поиском организации, ожидать SaveChangesAsync и исправить проверку периода с OR на AND. Потоки и внешние операции требуют явного управления.

Короткий ответ

Что ответить на собеседовании

Нужно убрать ToList перед поиском организации, ожидать SaveChangesAsync и исправить проверку периода с OR на AND. Потоки и внешние операции требуют явного управления.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо провести ревью кода и выполнить рефакторинг представленного сервиса, улучшив читаемость, устранив лишние обращения к базе и исправив логические недочёты. Приведённый класс реализует методы получения и установки логотипа организации, а также расчёта суммарных расходов по проектам.

public class OrganizationService
{
    private readonly IStorageService _storage;
    private readonly IAlertService _alert;
    private readonly IProjectApi _projectApi;
    private readonly ApplicationDbContext _db;

    public OrganizationService(
        IStorageService storage,
        IAlertService alert,
        IProjectApi projectApi,
        ApplicationDbContext db)
    {
        _storage = storage;
        _alert = alert;
        _projectApi = projectApi;
        _db = db;
    }

    public byte[] GetOrganizationLogo(Guid organizationId)
    {
        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        var logoId = org.LogoId;

        var memoryStream = new MemoryStream();
        Stream image = _storage.GetByObjectId(logoId);
        image.CopyTo(memoryStream);

        return memoryStream.ToArray();
    }

    public void SetOrganizationLogo(Guid organizationId, Stream logo)
    {
        var logoId = _storage.UploadLogo(logo);

        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        org.LogoId = logoId;

        _db.SaveChangesAsync(default);

        _alert.NotifyLogoChanged(org.Id);
    }

    public async Task<long> Calculate(Guid organizationId, DateTime? start, DateTime? finished, CancellationToken ct)
    {
        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        var projects = await _projectApi.GetProjectsAsync(org.Id, default);

        var result = 0L;

        foreach (var project in projects)
        {
            if (project.CompleteDate > start || project.CompleteDate < finished)
            {
                result += project.Cost;
            }
        }

        return result;
    }
}

Ответ

Нужно убрать ToList перед поиском организации, ожидать SaveChangesAsync и исправить проверку периода с OR на AND. Потоки и внешние операции требуют явного управления.

Получайте одну организацию через SingleOrDefaultAsync с фильтром и CancellationToken, отдельно обрабатывайте отсутствие. Потоки, которыми сервис владеет, закрывайте через using; входной logo не закрывайте без согласованного контракта. SetOrganizationLogo должен возвращать Task и делать await сохранения до уведомления.

Условие периода при включительных границах:

if ((!start.HasValue || project.CompleteDate >= start.Value) &&
    (!finished.HasValue || project.CompleteDate <= finished.Value))
    result = checked(result + project.Cost);

Передайте ct в API и проверьте start <= finished. При провале сохранения загруженный файл нужно компенсировать; уведомление надёжнее доставлять через outbox. Проверяйте право доступа к организации до чтения или смены логотипа.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее