Как сохранить мои функции (объекты/методы) "скудные и средние",
во всех (Agile) статьях, которые я читал об этом: сохраняйте свой код и функции небольшими и легко проверяемыми.
Как мне это сделать с классом "контроллер" или "координатор"?
В моей ситуации мне нужно импортировать данные. В конце концов, у меня есть один объект, который координирует это, и мне было интересно, есть ли способ сохранить координатор lean (er) и mean (er).
Мой координатор теперь выполняет следующий (псевдокод)
//Write to the log that the import has started
Log.StartImport()
//Get the data in Excel sheet format
result = new Downloader().GetExcelFile()
//Log this step
Log.LogStep(result )
//convert the data to intern objects
result = new Converter().Convertdata(result);
//Log this step
Log.LogStep(result )
//write the data
result = Repository.SaveData(result);
//Log this step
Log.LogStep(result )
Имхо, это один из тех, кто знает все классы или, по крайней мере, одно из них "не тощий и скупой"?
Или я беру эту скудную и среднюю вещь далеко, и невозможно ли запрограммировать импорт без какого-либо "живого" импортера/координатора?
Мишель
ИЗМЕНИТЬ
это на самом деле вопрос два-в-одном: один из них, как проверить его, во-вторых, если это нормально, чтобы иметь координатор "знать все/клеить все вместе"
Ответы
Ответ 1
Я уверен, что многие люди не согласятся, но я думаю, что ваш метод в целом достаточно скуден. Важнейший бит, который вы здесь не видите, - это инъекция зависимостей (также называемая инверсией управления) - поэтому вместо новичка Downloader, Converter и т.д. Внутри вашего метода вы должны определить интерфейсы для этих классов и "вставить" их в конструктор вашего класс:
private Downloader downloader;
private Converter converter;
public MyClass(Downloader downloader, Converter converter)
{
this.downloader = downloader;
this.converter = converter;
//same with repository, it can't be a static class anymore
}
то вы просто используете эти экземпляры в своем методе:
//Write to the log that the import has started
Log.StartImport()
//Get the data in Excel sheet format
result = downloader.GetExcelFile()
//Log this step
Log.LogStep(result )
//convert the data to intern objects
result = converter.Convertdata(result);
//Log this step
Log.LogStep(result )
//write the data
result = repository.SaveData(result);
//Log this step
Log.LogStep(result )
Теперь, после этого изменения, в вашем тесте вы можете использовать одну из насмешливых фреймворков (я использую RhinoMocks), чтобы внедрить посмешиваемую реализацию зависимостей в ваш класс. Таким образом, вы можете просто проверить, что правильный метод был вызван в конвертере и загрузчике, не читая ничего с диска и не разбору каких-либо электронных таблиц.
Примеры использования RhinoMocks приведены в их документации: http://ayende.com/wiki/Rhino+Mocks+Documentation.ashx
Не стесняйтесь задавать другой вопрос, если вы застряли:)
Ответ 2
У меня была аналогичная проблема, и я решил, что это действительно нужно посмотреть на SRP (Single Responsibility Principal).
ExcelFileReader, который может читать файл excel и возвращать набор List (lines)
Parser Задача заключается в анализе строк, возвращаемых из ExcelFileReader с помощью разделителя
Импортер, который обрабатывает импорт DataSet, возвращаемого из FileParser, в правильные таблицы.
Это сохраняет его в проверяемой форме, поскольку ExcelFileReader не зависит от Parser или Importer. Это касается и Parser, а также его проверки, просто передав ему TextReader.
Помогает ли это?
Ответ 3
Очень часто существует класс, который делает то, что я считаю, шаблон посредника.
Один из способов, который я нашел для борьбы с классами, которые должны иметь коллаборационисты (к чему вы сейчас работаете), состоит в том, чтобы выполнить Mock Unit Testing.
Вы по существу сворачиваете своих коллаборационистов и устанавливаете ожидания для тех, кто сотрудничает.
К сожалению, вы используете С#, и я не знаю каких-либо Mock-библиотек для С#.
Однако я уверен, что Google может помочь вам найти макетную библиотеку.
Вместо макетной библиотеки вы можете просто реализовать или расширить классы соавторов и переопределить и реализовать методы, которые вы ожидаете вызвать, с помощью методов, которые производят ожидаемый результат.
Как было отмечено Майклом, это намного проще, если у вас есть приложения для встраивания в зависимости от ваших сотрудников.
Ответ 4
Ваши комментарии и регистратор (singleton?) слишком шумные:
Log.StartImport();
result = new Downloader().GetExcelFile()
Log.Step(result);
result = new Converter().Convertdata(result);
Log.Step(result);
result = Repository.SaveData(result);
Log.Step(result);
И поскольку у вас есть три шага, которые должны произойти вместе, оберните их в Converter
. Используя DI, войдите в Converter
a Downloader
и a Repository
. Теперь вы получаете:
Log.StartConvert();
convert.ExcelToRepository(); //passed in with DI
Обратите внимание, что все результаты шага журнала выполняются в соответствующих действиях.
Ответ 5
Я нашел эту статью особенно полезной при выборе того, был ли мой код действительно скудным и средним