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