今天我在想“告诉!不要问!” 并尝试使用此代码。
接口:
interface IValidationContext
{
void AddMessage(string text);
bool IsValid { set; }
}
interface IValidation
{
void ValidateInput(Input input, IValidationContext context);
void ValidateOutput(Output output, IValidationContext context);
}
interface ICalculator
{
Output Calculate(Input input);
}
实现:
class CalculationService
{
private readonly ICalulator _calculator;
private readonly IValidation _validation;
public CalculationService(ICalculator calculator, IValidation validation)
{
_calculator = calculator;
_validation = validation;
}
public Output Calculate(Input input)
{
var context = new CalculationContext();
_validation.ValidateInput(input, context);
if (context.IsValid)
{
var output = _calculator.Calculate(input);
_validation.ValidateOutput(output, context);
return output
}
return null;
}
}
class CalculationContext : IValidationContext
{
public CalculationContext()
{
Messages = new List<string>();
}
public IList<string> Messages { get; private set; }
public void AddMessage(string text)
{
Messages.Add(text);
}
public bool IsValid { set; get; }
}
我知道并不总是可能符合设计原则。但最后我坚持使用这段代码,我问一个对象:
if (context.IsValid)
{
var output = _calculator.Calculate(input);
_validation.ValidateOutput(output, context);
}
是否有可能解决它是否实用?
编辑1:
如果我修改我的IValidationContext
并重命名它:
interface ICalculationContext
{
void AddMessage(string text);
Output Calculate(ICalculator calculator, Input input);
bool IsValid { set; }
}
不需要询问上下文:
public Output Calculate(Input input)
{
_validation.ValidateInput(input, context);
var output = context.Calculate(_calculator, input);
_validation.ValidateOutput(output, context);
return output;
}
现在上下文负责根据其内部状态调用计算。……感觉不对……
编辑2:
我读了一篇关于“告诉!不要问!”的小文章。它指出:询问一个对象的内部状态,然后根据该状态告诉该对象一些事情,这将违反“告诉!不要问!” 但是可以告诉另一个对象一些事情。这适用于这里吗?
顺便提一句。ValidateInput
为和引入一个布尔值有效结果ValidateOutput
。可以将代码更改为此,这很好,没有人被“询问”一些东西:
public Output Calculate(Input input)
{
var isValid = _validation.ValidateInput(input, context);
if (isValid)
{
var output = _calculator.Calculate(input);
_validation.ValidateOutput(output, context);
return output
}
return null;
}