条件型业务规则的抽象与实现——从Spring Profile得到的灵感
当我们更倾向于使用具体的场景沟通的时候,团队更不容易意识到需要从中寻找稳定的抽象。那么我们需要花费精力去改变用户的思维方式吗,如果需要又应该使用什么样的方式?又或者我们需要使用更抽象的方式来撰写用户故事吗?
(经过简化的用户故事——火车票预订)
作为用户,当我预订火车票时,我应该被告知配送地址无法送达,以便我调整配送地址或选择上门取票
public class AddressIsAvailableToDelivery implements PlaceOrderRule {
@Override
public void verify(PlaceOrderCommand command) {
if (command.getProduct().isTypeOf(RAILWAY)) {
// check if the adress is available for delivery the ticket
} else {
// hotel, makes no sense of deliering tickets
}
}
}
PlaceOrderRule
,并由各个PlaceOrderRule
的实现决定需要对哪些产品生效。(经过简化的用户故事——门票预订)
作为用户,当我预订景点门票时,我应该被告知配送地址无法送达,以便我调整配送地址或选择上门取票
public class AddressIsAvailableToDelivery implements PlaceOrderRule {
@Override
public void verify(PlaceOrderCommand command) {
if (command.getProduct().isTypeOf(RAILWAY) || command.getProduct().isTypeOf(SIGHTSEEING)) {
// check if the adress is available for delivery the ticket
} else {
// hotel, makes no sense of deliering tickets
}
}
}
找到稳定的抽象
检测当前情况是否需要验证给定的业务规则
如需要,执行验证;如不需要则略过
AddressIsAvailableToDelivery
修改为:public class AddressIsAvailableToDelivery implements PlaceOrderRule {
@Override
public void verify(PlaceOrderCommand command) {
if (command.getProduct().isDeliverableAddressRequired()) {
// check if the adress is available for delivery the ticket
} else {
// hotel, makes no sense of deliering tickets
}
}
}
但这样好难用
(经过简化的用户故事——产品预订)
作为用户,当我预订需要检查配送地址是否可达的产品时,我应该被告知配送地址无法送达,以便我调整配送地址或选择上门取票
作为运营人员,我可以设置产品在预订时是否需要检查配送地址,以避免预订后无法配送凭证的情况
在这个实现方案中,平台运营团队需要为不同的产品设置不同的规则吗?如果规则数量很多,配置起来是不是很麻烦?因为对于某个产品类型,几乎不需要做规则的调整,要求运营团队去配置这些功能在现阶段反而使他们的工作变复杂了
平台运营团队在平时的工作中,还是按照产品类型的思维在工作的,他们更习惯于”如果产品类型是火车,那么。。。”这样的沟通方式,想要改变这样的思维方式不是那么容易
修改后的用户故事似乎太抽象了,这样能否帮助团队有效地理解真实的业务场景?
(大量规则的时候,细粒度的产品配置方式可能需要”配置专家”才能搞定)
意外的灵感
if (isSmsEnabled()) {
//enable sms sending
}
if (isEmailEnabled()) {
//enable email sending
}
// application.properties
sms.enabled: false
email.enabled: false
// application-dev.properties
sms.enabled: false
email.enabled: false
// application-qa.properties
sms.enabled: false
email.enabled: true
// application-prod.properties
sms.enabled: true
email.enabled: true
spring boot
提供的Profile
机制。在启动应用的时候,并不需要一一指定各个配置项的值,而是指定粗粒度的profile
即可: --spring.profiles.active=prod
Profile
呢?AddressIsAvailableToDelivery依赖稳定的isDeliverableAddressRequired
:public class AddressIsAvailableToDelivery implements PlaceOrderRule {
@Override
public void verify(PlaceOrderCommand command) {
if (command.getProduct().isDeliverableAddressRequired()) {
// check if the adress is available for delivery the ticket
} else {
// hotel, makes no sense of deliering tickets
}
}
}
Product
时,注入预先设置的配置项,将产品类型和配置项的转换从核心的规则校验中剥离出去。# railway
placeOrderRule.RAILWAY.deliverableAddressRequired=true
placeOrderRule.RAILWAY.anotherConstraint1=false
placeOrderRule.RAILWAY.anotherConstraint2=false
# sightseeing
placeOrderRule.SIGHTSEEING.deliverableAddressRequired=true
placeOrderRule.SIGHTSEEING.anotherConstraint1=false
placeOrderRule.SIGHTSEEING.anotherConstraint2=true
遗留的问题
平台运营团队在平时的工作中,还是按照产品类型的思维在工作的,他们更习惯于”如果产品类型是火车,那么。。。”这样的沟通方式,想要改变这样的思维方式不是那么容易。
修改后的用户故事感觉太抽象了,这样能否帮助团队有效地理解真实的业务场景?
点击【阅读原文】可至洞见网站查看原文&绿色字体部分的相关链接。
本文版权属ThoughtWorks公司所有,如需转载请在后台留言联系。