How Gaode’s GBF Framework Eliminates Glue Code with Domain‑Driven Design
This article explains how Gaode's Information Business team tackled fragmented portal implementations across multiple industries by adopting the Gaode Business Framework (GBF) and domain‑driven design, achieving unified architecture, reduced duplication, improved reusability, and enhanced system stability and maintainability.
Background
The Gaode Information Business US team maintains portal pages for various industries (food, hotel, travel, entertainment, real estate, etc.). Each portal evolves independently, resulting in isolated development, glue code, inconsistent solution chains, duplicated logic, and rising maintenance costs.
Goals
Provide stable, unified implementations for fixed scenarios.
Improve design quality, maintainability, and reduce failure risk.
Eliminate duplicate work and lower development cost.
Enhance knowledge management and team collaboration.
Clarify system boundaries to reduce internal friction.
Design Overview
GBF (Gaode Business Framework) adopts domain‑driven design (DDD) to structure business logic into clear domains, abilities, and services, enabling cross‑industry and cross‑scenario reuse.
1. What is GBF?
GBF is a lightweight framework that bridges business identity and scene strategy, inspired by TMF, and provides a standardized way to define domains, abilities, and processes.
2. Why Use GBF?
Higher precision in problem analysis through domain segmentation.
Facilitates knowledge sharing and evolution.
Improves code reuse and reduces development cost.
Enhances system stability by isolating domains.
Implementation Steps
0. Define GBF
GBF introduces concepts of Domain , Ability , and Process Node to organize code.
1. Repository Layer
@FetcherClient(name = "sug-fetcher")
public interface SugFetcher {
@FetcherMethod(name = "quicklink")
QuerySugResult<QuickLinkPO> getQuickLink(@RequestParam QuickLinkReqParam reqParam);
} public interface QuickLinkRepo {
@Annotation(title = "获取金刚位")
QuickLinkPO getQuickLink(QuickLinkReqParam reqParam);
}
@Service
public class QuickLinkRepoImpl implements QuickLinkRepo {
@Resource
SugFetcher sugFetcher;
@Override
public QuickLinkPO getQuickLink(QuickLinkReqParam reqParam) {
return Optional.ofNullable(sugFetcher.getQuickLink(reqParam))
.map(QuerySugResult::getData)
.orElse(null);
}
}2. Domain Service
@DomainService(name = "运营领域金刚位服务", domain = OperationDomain.class)
public interface IQuickLinkDomainService {
QuickLinkDO getQuickLink(BaseRequest baseRequest);
}
@Service
public class QuickLinkDomainService implements IQuickLinkDomainService {
@Resource
QuickLinkRepo quickLinkRepo;
@Resource
IQuickLinkAbility quickLinkAbility;
@Override
public QuickLinkDO getQuickLink(BaseRequest baseRequest) {
QuickLinkReqParam param = quickLinkAbility.buildQueryParam(baseRequest);
QuickLinkPO po = quickLinkRepo.getQuickLink(param);
return quickLinkAbility.buildQuickLinkDO(po);
}
}3. Ability Definition
@DomainAbility(name = "金刚位ability", domain = OperationDomain.class)
public interface IQuickLinkAbility {
@ActionExtensible(name = "构建金刚位请求参数")
QuickLinkReqParam buildQueryParam(BaseRequest request);
@ActionExtensible(name = "构建金刚位DO")
QuickLinkDO buildQuickLinkDO(QuickLinkPO po);
} @Component
public class DefaultQuickLinkAction implements IQuickLinkAbility {
@Override
@Action(name = "构建金刚位请求参数")
public QuickLinkReqParam buildQueryParam(BaseRequest request) {
return new QuickLinkReqParam(request);
}
@Override
@Action(name = "构建金刚位DO")
public QuickLinkDO buildQuickLinkDO(QuickLinkPO po) {
return Optional.ofNullable(po)
.map(QuickLinkPO::getItems)
.map(Collection::stream)
.map(stream -> stream.map(p -> QuickLinkDO.ItemDO.builder()
.title(p.getTitle())
.icon(p.getIcon())
.iconHeight(p.getIconHeight())
.iconWidth(p.getIconWidth())
.logInfo(p.getLogInfo())
.toolTips(p.getToolTips())
.schema(p.getSchema())
.build())
.collect(Collectors.toList()))
.map(QuickLinkDO::new)
.orElse(null);
}
}4. Node Service
@ProcessNode(name = "QuickLinkService")
public class QuickLinkNodeService extends AbstractCommonNodeService<QuickLinkDO, BaseRequest> {
@Autowired
IQuickLinkDomainService quickLinkDomainService;
@Override
public QuickLinkDO doInvoke(BaseRequest request) {
return quickLinkDomainService.getQuickLink(request);
}
}5. Process Registration
// In ProcessConfig
BaseNodeConfigBuilder quickLinkNode = new NodeConfigBuilder()
.preJoinPoint(new JoinPoint<PortalParam, BaseRequest>() {
@Override
public BaseRequest join(PortalParam request) { return request; }
})
.nodeBeanName(BeanUtil.getBeanName(QuickLinkNodeService.class));
@Bean
public ProcessConfig portalProcess() {
return new ProcessConfigBuilder()
.request(Request.class)
.response(CommonResponse.class)
.nodes(userNode)
.nodes(filterTabNode)
.nodes(feedNode)
.nodes(bannerNode)
.nodes(quickLinkNode)
.build();
}6. Controller
@RestController
@RequestMapping("/process")
public class ProcessController {
@GetMapping("/portal/{biz}")
@ResponseBody
public Result<Response> portal(@PathVariable String biz, PortalParam param) {
NodeService<Response, Request> process = BeanUtil.getSpringBean(ProcessRegister.genericBeanName(PortalProcessConfig.BEAN_NAME));
param.setBizId(biz);
return process == null ? ProcessResult.fail("未找到流程") : process.invoke(param);
}
}Conclusion
By applying domain‑driven design through GBF, the US team achieved unified system design, reduced glue code, improved reuse, lowered development and maintenance costs, and enhanced knowledge sharing and stability across multiple industry portals.
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.
