Я оцениваю точки использования зависимостей через линзу намерения / механизма: этот код четко сообщает свое намерение, или мне нужно извлечь это из кучи деталей реализации?
Если код действительно выглядит как куча деталей реализации, я определяю входные и выходные данные и создаю совершенно новую зависимость, представляющую , почему стоит за всеми как . Затем я добавляю сложность в новую зависимость, делая исходный код проще и понятнее.
Когда я читаю код в этом вопросе, я отчетливо вижу поиск пути к файлу на основе даты, за которым следует непрозрачный набор утверждений, которые не четко обозначают цель чтения объекта определенного типа в определенный путь. Я могу пройти через это, но это сломает мой шаг.
Я предлагаю вам поднять уровень абстракции второй половины расчета, после того как вы получите путь. Я бы начал с определения зависимости, которая реализует ввод / вывод кода:
public interface IEntityReader
{
IEnumerable<T> ReadEntities<T>(string path);
}
Затем перепишите исходный класс, используя этот интерфейс для выявления намерений:
public sealed class CompanyDetailProvider : ICompanyDetailProvider
{
private readonly IFilePathProvider _filePathProvider;
private readonly IEntityReader _entityReader;
public CompanyDetailProvider(IFilePathProvider filePathProvider, IEntityReader entityReader)
{
_filePathProvider = filePathProvider;
_entityReader = entityReader;
}
public IEnumerable<CompanyDetail> GetCompanyDetailsForDate(DateTime date)
{
var path = _filePathProvider.GetCompanyDetailsFilePathForDate(date);
return _entityReader.ReadEntities<CompanyDetail>(path);
}
}
Теперь вы можете помещать в песочницу кровавые детали, которые становятся достаточно сплоченными в отдельности:
public sealed class EntityReader : IEntityReader
{
private readonly IDataReaderFactory _dataReaderFactory;
public EntityReader(IDataReaderFactory dataReaderFactory)
{
_dataReaderFactory = dataReaderFactory;
}
public IEnumerable<T> ReadEntities<T>(string path)
{
Func<IDataReader> sourceProvider =
() => _dataReaderFactory.CreateReader(DataFileType.FlatFile, path);
return new Hydrator<T>(sourceProvider);
}
}
Как показано в этом примере, я думаю, что вы должны абстрагироваться от фабрики устройства чтения данных и напрямую создать экземпляр гидратора. Различие состоит в том, что EntityReader
использует фабрику чтения данных, в то время как только создает гидратор. На самом деле это вообще не зависит от экземпляра; вместо этого он служит гидраторным заводом.