Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
lang lang/java/pipeline-style/extract-converter-validator.md medium

java-extract-converter-validator

防 ServiceImpl 膨胀 — 数据转换抽 Converter、参数校验抽 Validator、外部调用返回值校验下沉,编排方法每类只留一行调用。Use when ServiceImpl 堆转换/校验代码 / 拆臃肿 Service / 评审职责分层时。

converter 转换类validator 校验类结果校验serviceimpl 膨胀职责抽取assembler业务校验下沉
paths
  • *.java

Java · 抽 Converter / Validator

本条只管「臃肿逻辑抽到哪个专属类」。编排方法本身怎么写见 orchestration-method.md

规则

ServiceImpl 只做编排,以下三类逻辑必须抽到专属类,让编排层每类只留一行调用:

逻辑 抽到 编排层留
DO→DTO/VO、多源聚合转换 XxxConverter/XxxConvert(MapStruct) 一行 convert(...)
入参合法性校验(格式/范围/依赖) XxxValidator(@Component) 一行 validator.validateXxx(req)
外部调用返回值校验(空判/状态断言/错误码) XxxValidator 静态方法 一行 XxxValidator.assertExists(...)

正例

// ✅ 参数校验抽到 Validator
@Component
public class ArticleValidator {
    public void validateCreate(ArticleCreateReq req) {
        Assert.notBlank(req.getTitle(), "标题不能为空");
        Assert.isTrue(req.getWordCount() > 0, "字数必须大于 0");
    }
    // ✅ 结果校验:静态断言
    public static void assertExists(ArticleDO article, Long id) {
        if (article == null) {
            throw new BizException("文章不存在: " + id);
        }
    }
}

// 编排方法里各留一行
articleValidator.validateCreate(req);
ArticleValidator.assertExists(article, id);

反例

// ❌ 转换 + 校验全堆在 ServiceImpl
public ArticleVO getArticle(Long id) {
    ArticleDO article = mapper.selectById(id);
    if (article == null) {                       // 结果校验该下沉
        throw new BizException("文章不存在: " + id);
    }
    ArticleVO vo = new ArticleVO();
    vo.setTitle(article.getTitle());             // 20 行转换该交 Converter
    // ...
}

自检

  • [ ] ServiceImpl 没有 5 行以上的转换逻辑(应在 XxxConverter)?
  • [ ] 参数校验集中在 XxxValidator,没散落在 ServiceImpl?
  • [ ] 外部调用返回值校验(null/状态/错误码)用 Validator 静态方法,编排层只一行?
  • [ ] Converter 是无状态 @Component / MapStruct 接口,不掺业务判断?

相关