How a Strategy Factory Refactors Complex HSF Checks for Cleaner Backend Code
This article explains how the smart‑auto testing tool’s tangled HSF interface validation logic was refactored using a strategy‑factory pattern, breaking long if‑else chains into modular strategies that improve readability, maintainability, and adherence to the Open/Closed principle.
Background
The smart‑auto tool has evolved over years and now handles a wide range of HSF interface calls, accounting for more than 55% of Taobao grocery automated tests. As features grew, the core validation code became large, tangled, and hard to maintain.
Problems with Existing Code
Four HSF validation methods (HsfCheck1‑4) are combined in a single handler using lengthy if‑else branches, reducing extensibility.
The implementation violates the Open/Closed principle; any new check requires modifying the existing handler.
All validation logic resides in one massive class, harming readability and maintainability.
Complex conditionals make it difficult to determine which HSF check is being executed.
Solution: Strategy Factory Pattern
Introduce a strategy‑factory that encapsulates each HSF check in its own class and selects the appropriate strategy at runtime, thereby decoupling the validation logic.
public class CheckStrategyFactory {
private final Map<CheckStrategySelector, HsfInterfaceCheck> strategyRegistry = new HashMap<>();
@Autowired
public CheckStrategyFactory(HsfAssertCheck hsfAssertCheck,
HsfCrossInterfaceAssertCompare hsfCrossInterfaceAssertCompare,
HsfFullCompareCheck hsfFullCompareCheck,
HsfMultipleJsonPathCompareCheck hsfMultipleJsonPathCompareCheck,
JsonPathCompareStrategySelector jsonPathCompareStrategySelector,
CrossInterfaceAssertCompareStrategySelector crossInterfaceAssertCompareStrategySelector,
FullCompareStrategySelector fullCompareStrategySelector,
AssertStrategySelector assertStrategySelector) {
strategyRegistry.put(assertStrategySelector, hsfAssertCheck);
strategyRegistry.put(crossInterfaceAssertCompareStrategySelector, hsfCrossInterfaceAssertCompare);
strategyRegistry.put(fullCompareStrategySelector, hsfFullCompareCheck);
strategyRegistry.put(jsonPathCompareStrategySelector, hsfMultipleJsonPathCompareCheck);
// ... register more strategies as needed
}
public HsfInterfaceCheck getStrategy(ThubNodeConfig node, JSONObject checkConfigStatusObject,
TestsuiteAttributeModel attributeModel, ExecuteResultModel executeResultModel) {
for (Map.Entry<CheckStrategySelector, HsfInterfaceCheck> entry : strategyRegistry.entrySet()) {
if (entry.getKey().matches(node, checkConfigStatusObject, attributeModel, executeResultModel)) {
return entry.getValue();
}
}
return null; // fallback when no strategy matches
}
}Define two core interfaces:
public interface CheckStrategySelector {
boolean matches(ThubNodeConfig node, JSONObject checkConfigStatusObject,
TestsuiteAttributeModel attributeModel, ExecuteResultModel executeResultModel);
}
public interface HsfInterfaceCheck {
CheckOutputModel check(CheckCaseModel caseParam, BuildTestsuiteModel checkRecordModel,
ExecuteResultModel executeResultModel);
}Example selector implementation (assert strategy):
public class AssertStrategySelector implements CheckStrategySelector {
@Override
public boolean matches(ThubNodeConfig node, JSONObject checkConfigStatusObject,
TestsuiteAttributeModel attributeModel, ExecuteResultModel executeResultModel) {
String assertExpectStr = StringEscapeUtils.unescapeJavaScript(
(String) executeResultModel.getValueByKey(CheckCaseInfoConst.EXPECT_RESULT));
return !(checkConfigStatusObject == null || checkConfigStatusObject.isEmpty() ||
checkConfigStatusObject.getBoolean("isCheck") == false) &&
(assertExpectStr == null || !node.isCustom());
}
}Concrete check class (simplified):
@Service("hsfAssertCheck")
public class HsfAssertCheck implements HsfInterfaceCheck {
@Resource
private CaseConfigHandlerService caseConfigHandlerService;
@Resource
private CheckDataCaseService checkDataCaseService;
@Override
public CheckOutputModel check(CheckCaseModel caseParam, BuildTestsuiteModel checkRecordModel,
ExecuteResultModel executeResultModel) {
// implementation omitted for brevity
return new CheckOutputModel();
}
}Refactored CommonCheckHandler now delegates to the factory:
@Service("commonCheckHandler")
public class CommonCheckHandler implements CheckHandler {
private final CheckStrategyFactory factory;
public CommonCheckHandler(CheckStrategyFactory factory) {
this.factory = factory;
}
@Override
public CheckOutputModel doHandle(CheckCaseModel caseParam, BuildTestsuiteModel checkRecordModel,
ExecuteResultModel executeResultModel) throws Exception {
ThubNodeConfig node = JSON.parseObject(checkRecordModel.getTestsuiteDO().getStepConfig(),
ThubNodeConfig.class);
TestsuiteAttributeModel attributeModel = JSON.parseObject(checkRecordModel.getAttributes(),
TestsuiteAttributeModel.class);
JSONObject checkConfigStatusObject = JSON.parseObject(
checkRecordModel.getTestsuiteDO().getCheckConfigStatus());
CheckOutputModel result = new CheckOutputModel();
if (node == null) {
result.setSuccess(false);
return result;
}
HsfInterfaceCheck strategy = factory.getStrategy(node, checkConfigStatusObject,
attributeModel, executeResultModel);
if (strategy != null) {
return strategy.check(caseParam, checkRecordModel, executeResultModel);
}
result.setSuccess(false);
result.setErrorCode("No matching validation strategy found");
return result;
}
}Benefits
The refactor follows the Open/Closed principle; new strategies can be added without touching existing code.
Validation logic is decoupled from the handler, dramatically improving readability and maintainability.
Each class now fits on a single screen, reducing cognitive load for developers.
Visual comparison of the original monolithic handler and the refactored architecture is shown below.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
