Нужно убрать 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. Проверяйте право доступа к организации до чтения или смены логотипа.