[{"data":1,"prerenderedAt":1041},["ShallowReactive",2],{"post:\u002Fposts\u002Fswdesign\u002Fsw-design-notes-17":3,"posts:ordered":739},{"id":4,"title":5,"body":6,"category":721,"cover":722,"date":723,"description":724,"extension":725,"featured":726,"meta":727,"navigation":728,"path":729,"seo":730,"series":731,"seriesOrder":732,"stem":733,"tags":734,"__hash__":738},"posts\u002Fposts\u002FswDesign\u002Fsw-design-notes-17.md","软件分析与设计笔记 17：用生成式 AI 做设计与开发：能用的场景与要防的坑",{"type":7,"value":8,"toc":698},"minimark",[9,16,25,30,36,42,49,53,119,125,132,136,141,144,147,180,187,197,201,208,214,218,224,227,231,238,242,246,249,256,263,270,284,288,294,301,311,322,325,329,332,372,379,383,390,397,429,435,442,445,469,472,525,528],[10,11,12],"blockquote",{},[13,14,15],"p",{},"这是我在学习软件分析与设计时整理的系列笔记。概念部分是我按自己的理解写的，示例与图示都是自己编、自己画的。理解有偏差的地方欢迎指出。",[10,17,18],{},[13,19,20,24],{},[21,22,23],"strong",{},"贯穿案例","：片区家电维修派单系统。这一篇讲怎么把生成式 AI 用在这个项目的具体环节上 —— 以及在哪些环节绝不能用。",[26,27,29],"h2",{"id":28},"_0-从帮我写个函数说起","0 从「帮我写个函数」说起",[13,31,32,33],{},"很多人用生成式 AI（generative AI）的第一个场景是补全代码。用久了会发现一个规律：",[21,34,35],{},"它在「有明确目标、缺具体实现」的地方非常好用；在「目标本身还没想清」的地方基本帮不上忙，甚至会帮倒忙。",[13,37,38,39],{},"这个规律在本例里可以验证。如果你问它「帮我设计一个家电维修派单系统」，它会给你一份听起来很专业的方案 —— 但那份方案和你真正的问题（小林不知道谁有空、老陈白跑、王姐手工汇总）没有任何关系。",[21,40,41],{},"因为它在猜「一个派单系统通常长什么样」，而不是在理解你的业务。",[13,43,44,45,48],{},"原因不难理解：它的工作方式是",[21,46,47],{},"根据上下文（context）生成最可能的续写","。上下文清楚，续写就准；上下文含糊，它只能给你一个听起来合理的猜测 —— 而听起来合理，恰恰是最危险的部分。这里说的「模型」，通常指大语言模型（large language model, LLM）。",[26,50,52],{"id":51},"_1-它擅长什么不擅长什么","1 它擅长什么、不擅长什么",[54,55,56,71],"table",{},[57,58,59],"thead",{},[60,61,62,65,68],"tr",{},[63,64],"th",{},[63,66,67],{},"擅长的",[63,69,70],{},"不擅长的",[72,73,74,86,97,108],"tbody",{},[60,75,76,80,83],{},[77,78,79],"td",{},"任务类型",[77,81,82],{},"有明确约束的生成、改写、解释、翻译",[77,84,85],{},"判断哪个方案更适合你的业务",[60,87,88,91,94],{},[77,89,90],{},"输入要求",[77,92,93],{},"上下文给得越具体越好",[77,95,96],{},"信息不足时也能「自信地」编",[60,98,99,102,105],{},[77,100,101],{},"产出性质",[77,103,104],{},"候选方案、初稿、多个变体",[77,106,107],{},"结论、决策、事实性数据",[60,109,110,113,116],{},[77,111,112],{},"适合的角色",[77,114,115],{},"帮你把想法变快的助手",[77,117,118],{},"替你负责的决策者",[13,120,121,122],{},"一句话概括：",[21,123,124],{},"它是「候选生成器」，不是「判断者」。",[13,126,127],{},[128,129],"img",{"alt":130,"src":131},"用生成式 AI 辅助设计开发的五步流程：描述问题与约束、让模型给候选、人工筛选、迭代细化、回到真实用户验证；下方提示两类用法各自要注意的地方，包括三个站得住的场景与两个必须警惕的坑","\u002Fimages\u002Fsw-design-notes-17-genai-workflow.svg",[26,133,135],{"id":134},"_2-三个站得住的场景","2 三个站得住的场景",[137,138,140],"h3",{"id":139},"_21-造示例数据sample-data","2.1 造示例数据（sample data）",[13,142,143],{},"做线框图（wireframe）和原型（prototype）时，最枯燥的活之一就是编几十条看起来合理的数据。让模型按你给的结构批量生成，能省掉大量时间。",[13,145,146],{},"本例里最典型的一次：画派单台线框时需要 20 条工单数据。有效的问法是 ——",[10,148,149],{},[13,150,151,152,156,157,160,161,164,165,168,169,172,173,175,176,179],{},"按这个结构生成 20 条工单数据：",[153,154,155],"code",{},"order_no","（格式 WO-yyyyMMdd-nnn）、",[153,158,159],{},"appliance_type","（只能从空调\u002F冰箱\u002F洗衣机\u002F热水器里选）、",[153,162,163],{},"fault_desc","（10–25 字，口语化，像客户自己说的话）、",[153,166,167],{},"status","（CREATED\u002FASSIGNED\u002FIN_PROGRESS\u002FPENDING_PARTS\u002FCOMPLETED 之一）、",[153,170,171],{},"created_at","（近 7 天内）。其中至少 3 条 ",[153,174,167],{}," 为 ",[153,177,178],{},"PENDING_PARTS","。",[13,181,182,183,186],{},"有效做法是：",[21,184,185],{},"给出一个带注释的骨架","，把每个字段的要求写在旁边（取值范围、从哪些选项里选、长度限制），再要求它按这个结构生成。约束越具体，结果越可用。",[13,188,189,190,193,194,179],{},"注意最后那句「至少 3 条 PENDING_PARTS」——",[21,191,192],{},"它保证了数据能覆盖到你关心的那个状态","，而不是 20 条全是 ",[153,195,196],{},"CREATED",[137,198,200],{"id":199},"_22-解释陌生的代码或文档","2.2 解释陌生的代码或文档",[13,202,203,204,207],{},"拿到一段别人的实现、一份陌生的接口文档，先让模型讲清结构，再要求它",[21,205,206],{},"按你的场景","改写。这一步的价值不在于它写得多好，而在于它帮你跳过了「读懂」的冷启动阶段。",[13,209,210,211],{},"本例里的用法：供应商库存接口的文档只有一份 PDF，用模型先把它讲成「这个接口能回答什么问题、有哪些必填参数、错误码有哪几类」，然后再自己判断 —— ",[21,212,213],{},"后面那个判断不能交给它。",[137,215,217],{"id":216},"_23-起草初稿","2.3 起草初稿",[13,219,220,221,179],{},"访谈提纲（interview script）、问卷初稿、界面上的文案措辞、报告的开头段落 —— 这些东西",[21,222,223],{},"从一版草稿改起，永远比从空白页起步快",[13,225,226],{},"本例里 13 篇那份问卷，第一版就是让模型按「五个问题、覆盖缺料频率与影响」起草的，然后逐条改成现在的版本（把二选一改成填数字、把选项补全）。",[137,228,230],{"id":229},"_24-三者的共同点","2.4 三者的共同点",[13,232,233,234,237],{},"这三者的共同点是：",[21,235,236],{},"产出是一个「候选」，后面一定要有人筛","。一旦跳过筛选环节，它就从助力变成了风险。",[26,239,241],{"id":240},"_3-两个必须警惕的地方","3 两个必须警惕的地方",[137,243,245],{"id":244},"_31-它会复现训练数据里的偏见bias","3.1 它会复现训练数据里的偏见（bias）",[13,247,248],{},"这是最容易被忽视、后果又最严重的一点。",[13,250,251,252,255],{},"让模型生成「一张典型的店铺老板头像」或「一位数据科学家的画像」，你会看到高度一致的结果：某个性别、某个年龄段、某种肤色。",[21,253,254],{},"换个措辞，结果就跟着变"," —— 这正说明这些特征不是来自你的需求，而是来自训练数据里的分布。",[13,257,258,259,262],{},"对做需求分析的人，这里有个直接的推论：",[21,260,261],{},"不要让模型替你生成用户画像（persona）的人物特征","。画像的价值在于「这个人真实的行为与痛点」，而不是「他的性别年龄收入」。让它画头像做示意图没问题，把它当成用户研究结论就出问题了。",[13,264,265,266,269],{},"本例里的具体做法：05 篇那份小林画像里的「行为」那一栏 —— 「先记进 Excel 第 37 行、再翻便签本逐个打电话、没接就记下回头再打第二次」—— ",[21,267,268],{},"这三句只能来自观察，模型编不出来","。它编出来的是「小林，28 岁，大专学历，工作认真负责」，那种东西对设计零价值。",[13,271,272,273,276,277,280,281],{},"这个问题在业界被归到",[21,274,275],{},"负责任 AI（responsible AI）"," 与 ",[21,278,279],{},"AI 治理（AI governance）"," 的范畴里 —— 核心要求是：",[21,282,283],{},"系统性的偏见要在流程上被检查，而不是靠使用者临时留意。",[137,285,287],{"id":286},"_32-它会编得很像真的","3.2 它会编得很像真的",[13,289,290,291,179],{},"模型会生成看起来很权威但完全错误的内容：不存在的条款、对不上的数字、看似真实的引用。这类现象通常叫",[21,292,293],{},"幻觉（hallucination）",[13,295,296,297,300],{},"危险之处在于",[21,298,299],{},"它错得很流畅","。一段编造的说明读起来比一段正确的说明还顺，因为它就是按「读起来顺」的目标生成的。",[13,302,303,304,307,308],{},"本例里有个具体的风险点：",[21,305,306],{},"如果你问它「家电维修行业的标准响应时间是多少」，它会给你一个像模像样的数字（比如「行业标准是 4 小时」）","。而这个数字会直接变成 15 篇里那条「2 秒响应」之外的业务指标 —— ",[21,309,310],{},"但它可能是编的。",[13,312,313,314,317,318,321],{},"对应的纪律很简单：",[21,315,316],{},"凡是会进入需求文档的事实性内容（政策条款、数据口径、行业规范），必须回到原始来源核对"," —— 也就是回到基准事实（ground truth），不能拿模型的输出当依据。本例里真正的 ground truth 是",[21,319,320],{},"小林那 80 通电话的统计","，不是任何「行业标准」。",[13,323,324],{},"如果你的系统是让模型基于内部资料回答，那就用检索增强生成（RAG）把答案锚定在这些资料上，而不是依赖模型自己的记忆。",[26,326,328],{"id":327},"_4-提问的几条实践","4 提问的几条实践",[13,330,331],{},"设计提示词（prompt）这件事本身就是一门手艺，通常叫提示工程（prompt engineering）。下面几条是其中最有用的，每条都配上本例的用法：",[333,334,335,342,348,354,360,366],"ul",{},[336,337,338,341],"li",{},[21,339,340],{},"先交代角色和约束。"," 「你是一位熟悉 UML 的分析师，现在要为家电维修派单系统写「申请配件」的用例描述，约束是：只写主流程 + 三个例外，不要写界面细节」——比直接问问题有效得多；",[336,343,344,347],{},[21,345,346],{},"给几个例子（few-shot）。"," 把「好的输出长什么样」示范一两个，比用文字描述要求准确得多。本例里贴一条已经写好的用例描述当模板；",[336,349,350,353],{},[21,351,352],{},"要多个候选，不要一个答案。"," 「给三种不同的工单状态机设计，并说明各自的取舍」—— 你才能比较；",[336,355,356,359],{},[21,357,358],{},"要它说明理由。"," 让它解释「为什么这么设计」，你才能判断它是不是在套模板；",[336,361,362,365],{},[21,363,364],{},"给它你的上下文。"," 把真实的流程、字段、限制贴进去，让它针对你的场景改写；",[336,367,368,371],{},[21,369,370],{},"让它自己找反例。"," 「这个设计在什么情况下会失效」—— 用来补充你的负面场景（negative scenario）。本例里这一问帮我们想到了「两个客服同时派同一单」。",[13,373,374,375,378],{},"最后一条特别值得常用：",[21,376,377],{},"它找反例比找方案更靠谱","。因为找反例的本质是枚举，而找方案需要判断。",[26,380,382],{"id":381},"_5-把它用在产品里时的额外要求","5 把它用在产品里时的额外要求",[13,384,385,386,389],{},"如果生成式 AI 不只是你的工具，而是",[21,387,388],{},"产品的一部分","，那要求会高一个量级 —— 这也回到笔记 11 讲的 agent 那套。",[13,391,392,393,396],{},"本例里有个真实的场景可以对照：",[21,394,395],{},"如果给客户做一个「智能报修助手」","（用自然语言描述故障，模型判断是空调还是冰箱、可能是什么问题），那下面这五条就全部适用：",[333,398,399,405,411,417,423],{},[336,400,401,404],{},[21,402,403],{},"护栏（guardrail）"," —— 明确它不能说、不能做什么。比如不能给诊断结论（那是医疗\u002F安全问题），只能建议报修类别；",[336,406,407,410],{},[21,408,409],{},"人工复核（human review）"," —— 关键输出必须有人确认才能生效。比如模型判定的故障类别，要允许客服改；",[336,412,413,416],{},[21,414,415],{},"可追溯"," —— 每个输出都能查到依据。比如「判定为空调用的是哪几个关键词」；",[336,418,419,422],{},[21,420,421],{},"回退路径"," —— 模型不可用或答不上来时，界面该怎么表现。降级为「请选择家电类型」的表单；",[336,424,425,428],{},[21,426,427],{},"对用户的预期管理"," —— 让用户知道这是模型的输出、可能有误，而不是权威结论。",[13,430,431,432],{},"尤其最后一条：",[21,433,434],{},"把模型输出包装成「标准答案」而不加说明，是产品设计上的不负责任。",[13,436,437,438,441],{},"第一条在本例里还有一层意思：",[21,439,440],{},"护栏要写进需求文档","，而不是写在代码注释里。因为它是需求（「系统不得给出诊断结论」），不是实现细节。",[26,443,444],{"id":444},"本节自测",[446,447,448,451,454,457,460,463,466],"ol",{},[336,449,450],{},"为什么说生成式 AI 是「候选生成器」而不是「判断者」？",[336,452,453],{},"让模型生成示例数据时，怎么提高可用性？本例中怎么保证数据能覆盖关心的状态？",[336,455,456],{},"为什么不该用模型生成用户画像的人物特征？它可能带来什么后果？",[336,458,459],{},"什么是幻觉？为什么它特别危险？举出本例中一个具体的幻觉风险。",[336,461,462],{},"如果要把模型输出直接展示给最终用户，至少需要补哪三件事？",[336,464,465],{},"为什么说「让它找反例比找方案更靠谱」？",[336,467,468],{},"本例里「智能报修助手」的护栏应该写在哪里？为什么？",[137,470,471],{"id":471},"参考答案",[446,473,474,481,488,495,504,511,518],{},[336,475,476,477,480],{},"因为它",[21,478,479],{},"根据上下文生成最可能的续写","，产出的是「听起来合理」的候选，而不是对业务的判断。上下文含糊时它会给一个听起来专业但与你的问题无关的方案（§0、§1）。",[336,482,483,484,487],{},"给出",[21,485,486],{},"带注释的骨架","（每个字段的取值范围、选项、长度、时间范围），约束越具体越可用。本例加一句「至少 3 条 status 为 PENDING_PARTS」，保证数据覆盖到关心的状态而不是全是 CREATED（§2.1）。",[336,489,490,491,494],{},"因为那些特征来自",[21,492,493],{},"训练数据里的分布","，不是来自你的需求。后果是画像变成人口统计表，对设计零价值 —— 画像真正值钱的是「行为」栏（本例小林那三句只能来自观察）（§3.1）。",[336,496,497,500,501,503],{},[21,498,499],{},"幻觉","是模型生成看似合理但错误的内容。危险在于",[21,502,299],{},"（按「读起来顺」的目标生成）。本例风险：「家电维修行业标准响应时间是 4 小时」这类数字可能是编的，而它会被写进需求（§3.2）。",[336,505,506,507,510],{},"至少补：",[21,508,509],{},"护栏（不能说\u002F不能做什么）、人工复核（关键输出有人确认）、可追溯（输出能查到依据）","，此外还需要回退路径与预期管理（§5）。",[336,512,513,514,517],{},"因为",[21,515,516],{},"找反例的本质是枚举，找方案需要判断","。本例让它找「这个设计在什么情况下会失效」，帮我们想到了「两个客服同时派同一单」（§4）。",[336,519,520,521,524],{},"应该写进",[21,522,523],{},"需求文档","，而不是代码注释。因为「系统不得给出诊断结论」是需求（约束），不是实现细节 —— 写在代码里，需求评审时没人看得见（§5）。",[26,526,527],{"id":527},"术语表",[54,529,530,543],{},[57,531,532],{},[60,533,534,537,540],{},[63,535,536],{},"术语",[63,538,539],{},"中文",[63,541,542],{},"一句话解释",[72,544,545,556,567,578,589,600,611,621,632,643,654,665,676,687],{},[60,546,547,550,553],{},[77,548,549],{},"generative AI",[77,551,552],{},"生成式 AI",[77,554,555],{},"能生成文本、图像等新内容的模型",[60,557,558,561,564],{},[77,559,560],{},"large language model（LLM）",[77,562,563],{},"大语言模型",[77,565,566],{},"以文本为输入输出的生成式模型",[60,568,569,572,575],{},[77,570,571],{},"prompt",[77,573,574],{},"提示词",[77,576,577],{},"交给模型的输入，包括指令与上下文",[60,579,580,583,586],{},[77,581,582],{},"prompt engineering",[77,584,585],{},"提示工程",[77,587,588],{},"通过设计提示词提高输出质量的做法",[60,590,591,594,597],{},[77,592,593],{},"context",[77,595,596],{},"上下文",[77,598,599],{},"模型生成时能看到的全部输入信息",[60,601,602,605,608],{},[77,603,604],{},"sample data",[77,606,607],{},"示例数据",[77,609,610],{},"用于原型与线框图的假数据",[60,612,613,616,618],{},[77,614,615],{},"hallucination",[77,617,499],{},[77,619,620],{},"模型生成看似合理但错误的内容",[60,622,623,626,629],{},[77,624,625],{},"bias",[77,627,628],{},"偏见",[77,630,631],{},"训练数据带来的系统性倾向",[60,633,634,637,640],{},[77,635,636],{},"responsible AI",[77,638,639],{},"负责任 AI",[77,641,642],{},"把公平、透明、可问责纳入 AI 应用的实践",[60,644,645,648,651],{},[77,646,647],{},"AI governance",[77,649,650],{},"AI 治理",[77,652,653],{},"组织层面对 AI 使用制定规则与检查机制",[60,655,656,659,662],{},[77,657,658],{},"human review",[77,660,661],{},"人工复核",[77,663,664],{},"关键输出必须由人确认",[60,666,667,670,673],{},[77,668,669],{},"RAG",[77,671,672],{},"检索增强生成",[77,674,675],{},"先检索资料再生成答案，减少幻觉",[60,677,678,681,684],{},[77,679,680],{},"few-shot",[77,682,683],{},"少样本示例",[77,685,686],{},"在提示里给几个例子，让模型照着做",[60,688,689,692,695],{},[77,690,691],{},"ground truth",[77,693,694],{},"基准事实",[77,696,697],{},"用来核对模型输出是否正确的真实来源",{"title":699,"searchDepth":700,"depth":700,"links":701},"",3,[702,704,705,711,715,716,717,720],{"id":28,"depth":703,"text":29},2,{"id":51,"depth":703,"text":52},{"id":134,"depth":703,"text":135,"children":706},[707,708,709,710],{"id":139,"depth":700,"text":140},{"id":199,"depth":700,"text":200},{"id":216,"depth":700,"text":217},{"id":229,"depth":700,"text":230},{"id":240,"depth":703,"text":241,"children":712},[713,714],{"id":244,"depth":700,"text":245},{"id":286,"depth":700,"text":287},{"id":327,"depth":703,"text":328},{"id":381,"depth":703,"text":382},{"id":444,"depth":703,"text":444,"children":718},[719],{"id":471,"depth":700,"text":471},{"id":527,"depth":703,"text":527},"学习",null,"2026-11-08","生成式 AI 在工作流里真正站得住的三个场景 —— 造示例数据、解释陌生代码、起草初稿；它为什么会复现社会偏见、为什么会编得像真的，以及哪些内容绝不能直接采用。","md",false,{},true,"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-17",{"title":5,"description":724},"软件分析与设计笔记",17,"posts\u002FswDesign\u002Fsw-design-notes-17",[552,735,736,737],"设计工具","工作流","学习笔记","Qjq9lKc3SecN-DbEHKGxJ5LbGtTShliDObQ7QNpWNGs",[740,746,752,758,764,770,776,782,788,794,800,806,807,813,819,825,831,837,843,849,855,861,867,873,879,885,890,895,901,907,911,915,919,923,927,931,935,939,943,947,951,957,961,967,971,975,979,983,987,991,995,1000,1004,1008,1013,1018,1024,1028,1033,1037],{"path":741,"title":742,"description":743,"date":744,"series":731,"seriesOrder":745},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-28","软件分析与设计笔记 28：draw.io 作图手册：五张图的符号位置、落笔顺序与自检","不模拟软件界面，只讲清三件事：每个 UML 符号在 draw.io 里搜什么词、一张图该按什么顺序落笔、画完拿什么标准自查。覆盖用例图、活动图、顺序图、类图、界面草图五种图纸，末尾附「最容易画反的十二笔」总检表。","2026-11-19",28,{"path":747,"title":748,"description":749,"date":750,"series":731,"seriesOrder":751},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-27","软件分析与设计笔记 27：Paper 1 应试：从读案例到交卷的一次完整演算","拿一份完整的案例，从头到尾走一遍：怎么读案例列角色、怎么在四个小问之间分配时间、每一张图从哪一句话推出来、两张表怎么填、交卷前拿什么清单自查。附 C25 真题与样卷的题型分值对照。","2026-11-18",27,{"path":753,"title":754,"description":755,"date":756,"series":731,"seriesOrder":757},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-26","软件分析与设计笔记 26：总结：把整条链路串起来","系列收尾：从需求到代码的完整链路回顾、每一环的产出与验收方式、六条贯穿全系列的原则，以及一份可以直接拿去做项目自查的清单。","2026-11-17",26,{"path":759,"title":760,"description":761,"date":762,"series":731,"seriesOrder":763},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-25","软件分析与设计笔记 25：代码重构：坏味道与手法","重构不改变外部行为、只改善内部结构：四种常见坏味道与对应手法、为什么动手之前必须先有测试、什么时候该重构，以及重构和前面那些设计模型是什么关系。","2026-11-16",25,{"path":765,"title":766,"description":767,"date":768,"series":731,"seriesOrder":769},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-24","软件分析与设计笔记 24：设计原则：内聚、耦合与多态","好设计怎么衡量：内聚与耦合分别在说什么、一次从「差设计」到「多态重设计」的完整对照、抽象类与接口的选择依据，以及复用为什么会从优势变成风险。","2026-11-15",24,{"path":771,"title":772,"description":773,"date":774,"series":731,"seriesOrder":775},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-23","软件分析与设计笔记 23：设计建模：从对象模型到能实现的方案","分析模型能用但还不能直接开工：对象模型怎么映射到关系模型、继承映射的三种方案怎么选、数据访问层与 Data Broker 解决什么问题，以及三层架构与 MVC 的分工。","2026-11-14",23,{"path":777,"title":778,"description":779,"date":780,"series":731,"seriesOrder":781},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-22","软件分析与设计笔记 22：分析建模：边界、实体与控制对象","不经过分析直接写代码会踩什么坑、三种分析对象各管一段、怎么用顺序图完成一次用例实现，以及从顺序图导出类的属性、操作与关系的方法。","2026-11-13",22,{"path":783,"title":784,"description":785,"date":786,"series":731,"seriesOrder":787},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-21","软件分析与设计笔记 21：UML：类图与顺序图","为什么需要一种共同的画法：类符号三格怎么画、五种关系的符号与设计含义、每种关系落到 Java 是什么写法，顺序图的三要素怎么摆；以及这三种最容易找不到的符号在 draw.io 里各搜什么词。","2026-11-12",21,{"path":789,"title":790,"description":791,"date":792,"series":731,"seriesOrder":793},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-20","软件分析与设计笔记 20：面向对象概念：对象、关系与多态","面向对象不是「用某个语言写代码」：对象与类的区别、封装真正在保护什么、五种关系（依赖、关联、聚合、组合、继承）各自何时用，以及多态为什么能减少条件判断。","2026-11-11",20,{"path":795,"title":796,"description":797,"date":798,"series":731,"seriesOrder":799},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-19","软件分析与设计笔记 19：规范化与逻辑数据模型","一次改地址引发的数据不一致，讲清规范化的真正动机；UNF 到 3NF 每一步在解决什么问题，派生字段为什么不能存，优化为什么和规范化方向相反，以及逻辑数据模型在 3NF 之上补了什么。","2026-11-10",19,{"path":801,"title":802,"description":803,"date":804,"series":731,"seriesOrder":805},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-18","软件分析与设计笔记 18：数据库分析：实体、关系与数据字典","为什么不能拿到需求就动手建表：实体与关系怎么判定、基数为什么必须由业务方确认、数据命名要遵守什么规则，以及数据字典四列里最容易被空着的那一列。","2026-11-09",18,{"path":729,"title":5,"description":724,"date":723,"series":731,"seriesOrder":732},{"path":808,"title":809,"description":810,"date":811,"series":731,"seriesOrder":812},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-16","软件分析与设计笔记 16：从 persona 到 URS：一份交付物的完整骨架","把前面十几篇串成一份能交出去的东西：用户需求规格说明书的九个部分、每一章来自哪个环节、由谁确认，以及面向决策者的提案该讲清哪三件事。","2026-11-07",16,{"path":814,"title":815,"description":816,"date":817,"series":731,"seriesOrder":818},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-15","软件分析与设计笔记 15：非功能需求：把「快、稳、安全」变成数字","为什么「系统要快」不是一条需求：非功能需求怎么量化，决定性能的用户量、交易量、数据量三张表怎么估，安全需求要写清什么，以及可靠性的「不可用」该怎么定义。","2026-11-06",15,{"path":820,"title":821,"description":822,"date":823,"series":731,"seriesOrder":824},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-14","软件分析与设计笔记 14：软件测试：层级、方法与等价类划分","「我们测过了」这句话问题在哪：为什么静态评审和动态测试缺一不可，五个测试层级各自验证什么，白盒与黑盒的差别，以及用等价类划分和边界值把无限输入变成有限用例的方法。","2026-11-05",14,{"path":826,"title":827,"description":828,"date":829,"series":731,"seriesOrder":830},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-13","软件分析与设计笔记 13：需求获取：五种调查方法与一场访谈","需求从哪里来：五种事实调查方法各自适合回答什么、代价是什么，访谈从准备到记录的全过程，问卷设计里最容易犯的错，以及访谈记录必须写下来的那几项信息。","2026-11-04",13,{"path":832,"title":833,"description":834,"date":835,"series":731,"seriesOrder":836},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-12","软件分析与设计笔记 12：前端设计：把流程变成屏幕","界面设计不是「画得好看」：从活动图走到屏幕的三步，CRUD 任务流怎么当检查表，界面必须回答的三个问题，信息架构与五种导航类型，视觉一致性与留白，以及移动端与 Web 端的差别。","2026-11-03",12,{"path":838,"title":839,"description":840,"date":841,"series":731,"seriesOrder":842},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-11","软件分析与设计笔记 11：Agentic AI 与业务流程自动化","AI agent 到底是什么：五项能力与四个核心组件，什么场景该用定时任务、什么该用程序、什么才值得用 agent，两种实现路径的差别，必须提前防住的四类失败模式，以及设计方法从提示词到编排的演进。","2026-11-02",11,{"path":844,"title":845,"description":846,"date":847,"series":731,"seriesOrder":848},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-10","软件分析与设计笔记 10：精炼用例模型：include、extend 与泛化","三种精炼用例关系的判断标准：include 什么时候用、它和 extend 的区别到底在哪、参与者泛化与用例泛化各解决什么问题，以及精炼到什么程度就该停手。","2026-11-01",10,{"path":850,"title":851,"description":852,"date":853,"series":731,"seriesOrder":854},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-09","软件分析与设计笔记 09：功能需求（二）：从流程到业务实体","活动图画完之后，怎么从流程里筛出真正的业务实体：三条判断标准、哪些名词其实不该建实体、属性从哪里来，以及领域模型和后面的数据模型分别负责什么。","2026-10-31",9,{"path":856,"title":857,"description":858,"date":859,"series":731,"seriesOrder":860},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-08","软件分析与设计笔记 08：功能需求（一）：用例模型与活动图","从用户故事到用例的翻译过程：什么才算「好」的参与者，系统边界怎么划，用例描述必须写清哪四件事，活动图怎么把分支、并行与泳道画清楚，以及这两个图在 draw.io 里各用哪个形状、最容易画错哪一笔。","2026-10-30",8,{"path":862,"title":863,"description":864,"date":865,"series":731,"seriesOrder":866},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-07","软件分析与设计笔记 07：用户故事：把需求写成可验收的一句话","用户故事的三段结构，怎么从用户画像和数据地图里把它提取出来，一条故事多大算合适、时序为什么也是需求的一部分，以及验收标准怎么写才算真的可验收。","2026-10-29",7,{"path":868,"title":869,"description":870,"date":871,"series":731,"seriesOrder":872},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-06","软件分析与设计笔记 06：范围界定（数据侧）：用数据校验你的判断","访谈结论和数字对不上时该怎么办：分析的四个层次分别在回答什么问题、为什么不能跳级、数据准备与搜集怎么做成一张应用地图，以及数据最容易在哪几个地方骗你。","2026-10-28",6,{"path":874,"title":875,"description":876,"date":877,"series":731,"seriesOrder":878},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-05","软件分析与设计笔记 05：范围界定（用户侧）：用户画像与客户旅程图","为什么「所有用户」是一个陷阱，项目边界该怎么划，用户画像要写哪五个要素、最容易写成什么废纸，客户旅程图怎么把阶段、想法和情绪画在同一张纸上，以及怎么从这两样东西一步步推到可验证的需求。","2026-10-27",5,{"path":880,"title":881,"description":882,"date":883,"series":731,"seriesOrder":884},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-04","软件分析与设计笔记 04：接手陌生案例的第一步：三问与一张表","拿到一个完全陌生的业务案例，怎么从零开始不跑偏：只问 Who、What、Why 三个问题，把「问题—事实—假设—理由」记成一张四列表，说清为什么假设必须写明理由，以及带着问题进访谈为什么比空手去有效得多。","2026-10-26",4,{"path":886,"title":887,"description":888,"date":889,"series":731,"seriesOrder":700},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-03","软件分析与设计笔记 03：Agile 与 Scrum：迭代、角色与产出物","从「三周做完交付，客户说这不是我要的」讲起，说清瀑布式与迭代式的根本差别，Scrum 的三个角色和三种产出物，一个 sprint 里四次固定活动各自在解决什么问题，以及敏捷里最常见的几个误解。","2026-10-25",{"path":891,"title":892,"description":893,"date":894,"series":731,"seriesOrder":703},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-02","软件分析与设计笔记 02：设计思维、用户驱动与数据驱动","从「客服要一个能一次看完所有排期的界面」这个翻车案例讲起，说清设计思维到底是什么、用户驱动与数据驱动各自能看见什么又看不见什么、为什么真正的落点是把两者合起来的 data-informed design，以及访谈中怎么问出有用的信息。","2026-10-24",{"path":896,"title":897,"description":898,"date":899,"series":731,"seriesOrder":900},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-01","软件分析与设计笔记 01：课程地图与从需求到设计的主干","这一篇不写具体方法，先把整条链路铺开：软件分析与设计到底要解决什么问题，从需求到设计分成哪两段，中间有哪十几个环节，一份完整的交付物里应该有什么，以及后面 27 篇笔记怎么排、新人该按什么顺序读。","2026-10-23",1,{"path":902,"title":903,"description":904,"date":905,"series":906,"seriesOrder":900},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-01","Spring 学习笔记 01：IoC、依赖注入与第一个 Spring Boot 应用","从「手写 new 出来的三层结构」的痛点讲起，说清 IoC 容器、Bean 与依赖注入是怎么回事，再用 Maven 与 Spring Initializr 跑起第一个能返回 JSON 的应用。","2026-10-15","Spring 学习笔记",{"path":908,"title":909,"description":910,"date":905,"series":906,"seriesOrder":703},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-02","Spring 学习笔记 02：Spring Data JPA 基础——实体映射与 Repository","用 ORM 把类映射到表：@Entity、@Id、@GeneratedValue 怎么用，CrudRepository 三层接口怎么选，H2 与 MySQL 怎么配，以及 ddl-auto 到底该写哪个值。",{"path":912,"title":913,"description":914,"date":905,"series":906,"seriesOrder":700},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-03","Spring 学习笔记 03：JPA 查询——派生方法、JPQL 与分页排序","Repository 自带的方法只够按主键查，这篇讲三种自己造查询的方式：方法名派生、@Query 写 JPQL、原生 SQL，以及 Pageable 分页排序和投影返回。",{"path":916,"title":917,"description":918,"date":905,"series":906,"seriesOrder":884},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-04","Spring 学习笔记 04：JPA 关联映射与仓储测试","一对多、多对多怎么映射，谁负责维护外键，FetchType 与 CascadeType 该怎么选，顺带用 @DataJpaTest 与 AssertJ 把仓储层测起来。",{"path":920,"title":921,"description":922,"date":905,"series":906,"seriesOrder":878},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-05","Spring 学习笔记 05：Spring MVC 与 Thymeleaf 入门","一次页面请求在 Spring MVC 里走了哪几步，@Controller 怎么把数据交给模板，@PathVariable 与 @RequestParam 怎么取参数，以及控制器为什么必须是无状态的。",{"path":924,"title":925,"description":926,"date":905,"series":906,"seriesOrder":872},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-06","Spring 学习笔记 06：表单绑定与服务端校验","把表单字段绑到对象上，用 Bean Validation 注解做服务端校验，把错误信息显示回用户刚填的那一页，再补上自定义校验注解与全局异常处理。",{"path":928,"title":929,"description":930,"date":905,"series":906,"seriesOrder":866},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-07","Spring 学习笔记 07：Thymeleaf 片段复用与国际化","用 th:fragment 与 th:insert\u002Fth:replace 把导航栏、页脚抽成片段，页面套用统一布局，再用 messages.properties 与 LocaleResolver 做中英文切换。",{"path":932,"title":933,"description":934,"date":905,"series":906,"seriesOrder":860},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-08","Spring 学习笔记 08：HTTP Session 与会话状态管理","HTTP 无状态带来的问题，Cookie 与 Session 怎么分工，Spring 里读写会话的几种方式，以及会话固定、超时、多实例共享这些必须想清楚的事。",{"path":936,"title":937,"description":938,"date":905,"series":906,"seriesOrder":854},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-09","Spring 学习笔记 09：拦截器 HandlerInterceptor","登录检查、权限判断、请求耗时统计这类横切逻辑该放哪：HandlerInterceptor 的三个回调各在什么时机执行，怎么注册与排除路径，以及它和过滤器的分工。",{"path":940,"title":941,"description":942,"date":905,"series":906,"seriesOrder":848},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-10","Spring 学习笔记 10：Service 层与事务","一组数据库操作要么全成功要么全失败，靠 @Transactional 怎么做到；传播行为、隔离级别、回滚规则怎么选，以及自调用失效、乐观锁悲观锁这些实战里的坑。",{"path":944,"title":945,"description":946,"date":905,"series":906,"seriesOrder":842},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-11","Spring 学习笔记 11：REST API 基础——把 Service 暴露成接口","同一套 Service 怎么同时服务页面和客户端：@RestController 的路由与方法语义、状态码怎么给、DTO 怎么定，以及 MockMvc 端到端和切片测试的两种写法与各自的坑。",{"path":948,"title":949,"description":950,"date":905,"series":906,"seriesOrder":836},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-12","Spring 学习笔记 12：REST 进阶——版本、更新、跨域与文档化","接口能跑通之后要处理的几件事：URL 与响应结构怎么定、版本怎么演进、更新怎么做到可安全重试、CORS 怎么配、HATEOAS 与 Spring Data REST 该不该用。",{"path":952,"title":953,"description":954,"date":955,"series":956,"seriesOrder":884},"\u002Fposts\u002Fjava\u002Fjava-functionalprogramming-notes","Java 函数式编程笔记：Lambda、函数式接口与 Streams","学习 Java 函数式编程时的个人笔记：Lambda 表达式的五步简写与方法引用、常见函数式接口、Stream 流水线与惰性求值，以及创建流、中间操作、终止操作与收集器的用法。示例代码均为自写，运行结果来自本地实测。","2026-10-13","Java 学习笔记",{"path":958,"title":959,"description":960,"date":955,"series":956,"seriesOrder":700},"\u002Fposts\u002Fjava\u002Fjava-generics-notes","Java 泛型笔记：泛型方法、有界类型与泛型类","学习 Java 泛型时的个人笔记：从重复的重载方法与多态尝试讲起，再到泛型方法与类型推断、有界泛型类型、Comparable 与 Number 边界，以及泛型类在集合中的用法。示例代码均为自写，运行结果来自本地实测。",{"path":962,"title":963,"description":964,"date":965,"series":966,"seriesOrder":884},"\u002Fposts\u002Fmysql\u002Fmysql-learning-04","MySQL 学习笔记 04：数据操纵（增删改）","MySQL 学习笔记第四篇：INSERT 插入（含批量插入与 INSERT ... SELECT）、UPDATE 更新、DELETE 删除，以及各自的坑。","2026-10-10","SQL 学习笔记",{"path":968,"title":969,"description":970,"date":965,"series":966,"seriesOrder":878},"\u002Fposts\u002Fmysql\u002Fmysql-learning-05","MySQL 学习笔记 05：DDL 概览","MySQL 学习笔记第五篇：数据定义语言概览——Schema、Table、View、Index、Constraints 这几类对象分别对应哪些 CREATE \u002F ALTER \u002F DROP 命令。",{"path":972,"title":973,"description":974,"date":965,"series":966,"seriesOrder":872},"\u002Fposts\u002Fmysql\u002Fmysql-learning-06","MySQL 学习笔记 06：CREATE TABLE 与数据类型","MySQL 学习笔记第六篇：CREATE TABLE 的完整语法、常用数据类型的选型建议，以及外键的两种定义方式。",{"path":976,"title":977,"description":978,"date":965,"series":966,"seriesOrder":866},"\u002Fposts\u002Fmysql\u002Fmysql-learning-07","MySQL 学习笔记 07：索引","MySQL 学习笔记第七篇：索引的作用与 B+ 树结构、单列与复合索引的创建、索引的代价与适用场景。",{"path":980,"title":981,"description":982,"date":965,"series":966,"seriesOrder":860},"\u002Fposts\u002Fmysql\u002Fmysql-learning-08","MySQL 学习笔记 08：DROP 与 ALTER","MySQL 学习笔记第八篇：DROP 删除数据库对象、ALTER 修改表结构，以及常见的坑。",{"path":984,"title":985,"description":986,"date":965,"series":966,"seriesOrder":854},"\u002Fposts\u002Fmysql\u002Fmysql-learning-09","MySQL 学习笔记 09：约束与数据完整性","MySQL 学习笔记第九篇：SQL 约束——NOT NULL、CHECK、PRIMARY KEY、FOREIGN KEY 等如何保证数据完整性，以及它们的对比。",{"path":988,"title":989,"description":990,"date":965,"series":966,"seriesOrder":848},"\u002Fposts\u002Fmysql\u002Fmysql-learning-10","MySQL 学习笔记 10：视图","MySQL 学习笔记第十篇：视图（Views）的定义与特性、和表的对比、创建与使用，以及可更新视图的限制。",{"path":992,"title":993,"description":994,"date":965,"series":966,"seriesOrder":842},"\u002Fposts\u002Fmysql\u002Fmysql-learning-11","MySQL 学习笔记 11：存储过程","MySQL 学习笔记第十一篇：存储过程（Stored Procedures）的概念、创建与调用、带参数的写法，以及优缺点。",{"path":996,"title":997,"description":998,"date":999,"series":966,"seriesOrder":900},"\u002Fposts\u002Fmysql\u002Fmysql-learning-01","MySQL 学习笔记 01：MySQL 基础知识","MySQL 学习笔记第一篇：MySQL Server 与 Workbench 的安装，数据库与 DBMS 的基本概念，关系模型、ACID 事务、常见数据类型，以及后续的学习路线。","2026-10-09",{"path":1001,"title":1002,"description":1003,"date":999,"series":966,"seriesOrder":703},"\u002Fposts\u002Fmysql\u002Fmysql-learning-02","MySQL 学习笔记 02：SELECT 查询与过滤","MySQL 学习笔记第二篇：SELECT 的基本语法与逻辑执行顺序，WHERE 过滤（比较、LIKE、IN、BETWEEN、NULL）、各种 JOIN、UNION 与子查询。",{"path":1005,"title":1006,"description":1007,"date":999,"series":966,"seriesOrder":700},"\u002Fposts\u002Fmysql\u002Fmysql-learning-03","MySQL 学习笔记 03：聚合、分组与输出控制","MySQL 学习笔记第三篇：COUNT\u002FSUM\u002FAVG 等聚合函数、GROUP BY 分组、HAVING 过滤、ORDER BY 与 LIMIT，以及一条 SELECT 的完整逻辑执行顺序。",{"path":1009,"title":1010,"description":1011,"date":1012,"series":956,"seriesOrder":703},"\u002Fposts\u002Fjava\u002Fjava-oop-notes","Java 面向对象笔记：类、继承、多态与异常","学习 Java 面向对象编程时的个人笔记：类与对象、封装与访问修饰符、继承与多态、集合、抽象类与接口、异常处理。示例代码均为自写，运行结果来自本地实测。","2026-10-06",{"path":1014,"title":1015,"description":1016,"date":1017,"series":956,"seriesOrder":900},"\u002Fposts\u002Fjava\u002Fjava-basics-notes","Java 基础语法笔记：从环境安装到方法与数组","学习 Java 基础语法时的个人笔记：JDK 安装、输入输出、变量与运算符、条件与循环、字符串、数组与方法。示例代码均为自写，运行结果来自本地实测。","2026-10-05",{"path":1019,"title":1020,"description":1021,"date":1022,"series":1023,"seriesOrder":900},"\u002Fposts\u002Fgit\u002Fgit-install-and-basics","Git 安装与基本使用","从装好 Git 到跑通日常提交流程，把最常用的几条命令和它们背后的三个区域讲清楚。","2026-10-04","Git 入门",{"path":1025,"title":1026,"description":1027,"date":1022,"series":1023,"seriesOrder":703},"\u002Fposts\u002Fgit\u002Flocal-remote-repository","本地远程仓库的部署","用自己的机器当 Git 服务器：建一个裸仓库、走 SSH 连上去，把本地提交推上去。",{"path":1029,"title":1030,"description":1031,"date":1022,"series":1032,"seriesOrder":900},"\u002Fposts\u002Fguide\u002Fguide-file-layout","文件都放在哪","文章、图片、封面分别放在仓库的什么位置，哪些目录可以放手改、哪些碰了会出问题。","博客使用指南",{"path":1034,"title":1035,"description":1036,"date":1022,"series":1032,"seriesOrder":703},"\u002Fposts\u002Fguide\u002Fguide-frontmatter","frontmatter 每个字段是什么意思","文章开头那段被横线包住的字段，逐个说明作用、默认行为和写错的后果。",{"path":1038,"title":1039,"description":1040,"date":1022,"series":1032,"seriesOrder":700},"\u002Fposts\u002Fguide\u002Fguide-markdown","正文怎么写 —— Markdown 与排版效果","标题、链接、图片、代码、表格分别怎么写，以及本站对它们做了哪些自定义处理。",1793268185322]