Переписывание фрагмента кода в соответствии с принципами SOLID

Разделите загрузку пользователей, построение поздравления и запись файлов; зависимости передавайте через конструктор, а асинхронный запрос ожидайте через await.

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

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

Разделите загрузку пользователей, построение поздравления и запись файлов; зависимости передавайте через конструктор, а асинхронный запрос ожидайте через await.

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

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

Условие

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

public class BirthdayTemplateProcessor
{
    public static UserDal UserRepository { get; set; } = new UserDal();

    public static void GenerateTemplates(int[] ids)
    {
        string[] names = UserRepository.Query()
            .Where(u => ids.Contains(u.Id))
            .Select(u => u.UserName)
            .ToArrayAsync().Result;

        string messageTemplate = "Hello, dear {0}. Happy Birthday!";
        string directoryPath = "C://templates/birthdays/";

        foreach (var name in names)
        {
            System.IO.File.WriteAllText(directoryPath + name, string.Format(messageTemplate, name));
        }
    }
}

Ответ

Разделите загрузку пользователей, построение поздравления и запись файлов; зависимости передавайте через конструктор, а асинхронный запрос ожидайте через await.

Минимальная схема оркестратора с явно заданными контрактами зависимостей:

public record Recipient(int Id, string Name);
public interface IRecipients {
    Task<IReadOnlyList<Recipient>> LoadAsync(int[] ids);
}
public interface ITemplateStore {
    Task SaveAsync(int id, string text);
}
public sealed class BirthdayProcessor(IRecipients users, ITemplateStore store)
{
    public async Task GenerateAsync(int[] ids)
    {
        foreach (var user in await users.LoadAsync(ids))
            await store.SaveAsync(user.Id,
                $"Hello, dear {user.Name}. Happy Birthday!");
    }
}

Хранилище получает каталог из конфигурации и формирует безопасное имя по ID, а не по пользовательскому имени. Так устраняются коллизии имён и обход каталогов. .Result и изменяемое static-свойство больше не нужны. Отдельный интерфейс форматтера полезен при нескольких шаблонах, но не обязателен ради самого SOLID.

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

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

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

Подробнее