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