我打算将验证移到单独的函数中以获得粒度并且易于维护单元测试。但是,我需要一些在Validate方法中命中数据库的变量,以便在Process方法中重用,并确保它是可单元测试的。
当前实施
interface ICustomerService
{
void Process();
}
public class CustomerService: ICustomerService
{
ICustomerDbService db;
public CustomerService(ICustomerDbService customerDbService)
{
db = customerDbService;
}
public void Process()
{
//validations
var customer = db.GetCustomer(customerId);
if(customer == null)
return "Not found";
//processing
}
}
//Usage
ICustomerService service = new CustomerService(dbService);
service.Process();
未来实施
interface ICustomerService
{
bool Validate(int customerId);
void Process();
}
public class CustomerService: ICustomerService
{
ICustomerDbService db;
public CustomerService(ICustomerDbService customerDbService)
{
db = customerDbService;
}
public bool Validate(int customerId)
{
var customer = db.GetCustomer(customerId);
if(customer == null)
return "Not found";
//other processing with multiple(3-4) common variables
}
public void Process()
{
var customer = db.GetCustomer(customerId); // How to avoid this call
}
}
//Usage
ICustomerService service = new CustomerService(dbService);
bool isValid = service.Validate(10)
if(isValid)
{
service.Process();
}
答案 0 :(得分:1)
好像你的CustomerService
有多个职责
- 验证客户
- 处理验证结果
您可以介绍三个职责分类
- 客户验证
- 处理客户数据
- 结合验证和处理
并使Validation
方法返回Process
方法所需的数据,这使您可以分离逻辑并避免共享类的状态/变量的可能“问题”。
public class CustomerValidation
{
public Customer Validate(int customerId)
{
// Validation logic which "produce" instance of customer by given id
return customer;
}
}
public class CustomerProcess
{
public void Process(Customer customer)
{
// Process given customer
}
}
public class CustomerService
{
private CustomerValidation _validation;
private CustomerProcess _process;
public CustomerService(CustomerValidation validation, CustomerProcess process)
{
_validation = validation;
_process = process;
}
public void DoStaff(int customerId)
{
var customer = _validation.Validate(customerId);
if (customer != null)
{
_process.Process(customer);
}
}
}
将像这样使用
var validation = new CustomerValidation();
var process = new CustomerProcess();
var service = new CustomerService(validation, process);
service.DoStaff(customerId);
而不是Validation
和Process
类的“实际”实现,您可以引入抽象(接口),这使您可以替换不同的验证实现并编写单元测试来测试服务的实际逻辑class - 将验证和流程逻辑结合起来。
答案 1 :(得分:0)
这就是我最接近你想做的事情的模式
public class CustomerService: ICustomerService
{
ICustomerDbService db;
public CustomerService(ICustomerDbService customerDbService)
{
db = customerDbService;
}
public bool Validate(int customerId)
{
var customer = db.GetCustomer(customerId);
return Validate(customer);
}
public void Process(int customerId)
{
var customer = db.GetCustomer(customerId);
if(Validate(customer))
{
//do processing...
}
}
private bool Validate(Customer customer, /*other args*/)
{
if(customer == null)
return "Not found";
//other processing with multiple(3-4) common variables
}
}