2010-10-17 6 views
0

В этом простом примере (конечно, моя проблема с реальным миром сложнее, хотя основы одинаковы), как я могу принудить вас не спрашивать max? Id нравится максимизировать, не спрашивайте в методе процесса, в его текущем состоянии его сложнее насмехаться и тестировать.Скажите, не спрашивайте и не делитесь состоянием между задачами

public class Processor 
{ 
    public void Process() 
    { 
     var data = new Task1().DoStuff(); 
     new Task2().DoStuffToData(data); 
    } 
} 

public class Task1 
{ 
    public Data DoStuff(){return new Data();} 
} 

public class Data {} 

public class Task2 
{ 
    public void DoStuffToData(Data data){} 
} 

EDIT: Обновленный образец более DIish

public class Processor 
    { 
public Processor(ITask1 task1, ITask2 task) {...} 
     public void Process() 
     { 
      var data = task1.DoStuff(); 
      task2.DoStuffToData(data); 
     } 
    } 

ответ

2

Этот код не кажется слишком плохим с точки зрения tell-don't-ask.

Tell-don't-ask в основном означает, что вы не должны запрашивать объект об этом состоянии, принимать решение на основе его состояния и , а затем сообщить тому же объекту, что делать до. Если объект имеет всю необходимую ему информацию, он должен сам решить.

Вы получаете данные от task1 и потребляете эту информацию с помощью task2, не сообщая task1 что делать. Поэтому я бы сказал, что это нормально с точки зрения не-спросите.

Что касается Processor.Process: там ничего плохого. Клиент будет звонить myProcessor.Process и тем самым сообщает ему, что делать, не спрашивая.

Скажите-don't-ask выглядит нормально, может быть, есть что-то еще о коде, который вам не нравится? Например, вы можете рассмотреть вопрос о помещении DoStuffToData в класс Data, тем самым сочетая состояние и поведение. Но зависит ли это от модели и ее контекста.

+0

Да, ты прав, с этой точки зрения это выглядит нормально, я думаю, что, возможно, задал неправильный вопрос. В то время я читал 9-ю точку http://binstock.blogspot.com/2008/04/perfecting-oos-small-classes-and-short.html, но, глядя из чистого рассказа, не спрашивайте перспективы. Ваше предложение - это один из способов решения моей проблемы, поэтому я думаю, что плохо попробуйте. – MatteS

+0

Кроме того, я где-то читал, что при написании тестов издевательства над другими маками обычно указывают на проблему с дизайном. Поэтому, если я напишу тест метода Process mocking task1 и task2, в моем примере напишите ожидание для задачи1, чтобы вернуть данные, хотя мой тест должен тестировать вызов task2. Представьте, что у вас 10 таких задач в разных комбинациях, и я должен настроить много из насмешек для каждого теста, хотя Im каждый раз проверяет каждую вещь. С другой стороны, если вы предлагаете свое предложение, им даже больше принуждаются к тому, чтобы оживить ожидание, возвращая еще один макет ... – MatteS

+0

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

0

Одним из вариантов является использование Depenancy Injection (DI). Однако убедитесь, что это не слишком усложняет ваш код. DI может быть полезен для unit testing and mocking, но это также может привести к слишком маленьким классам.

+1

DI сам по себе не приведет к слишком малым классам, разработчик может легко сделать это без DI. Удаление зависимостей от ваших классов - это * хорошая вещь * для избежания кода спагетти или классов, которые являются * большими *. И как очень хороший * побочный эффект *, ваш код будет намного проще для модульного теста. –

+0

Все хорошие моменты. Хорошее объяснение. У меня только недавно появилось видение в голове пучков интерфейсов, каждый с одним методом. И огромные длинные списки параметров конструктора. – cofiem

+0

Да, в коде реального мира я использую DI, но основная проблема такая же. Task1 возвращает данные, требуемые Task2. В основном id, как состояние, которое будет использоваться другим способом, который Task1 возвращает данные. Код сложнее проверить, потому что мне нужно настроить ожидания только для того, чтобы возвращать данные из Task1, хотя это ожидание действительно не требуется для рассматриваемого теста. Возможно, я ограничиваю проблему, но мне нужны новые идеи =) – MatteS