[{"data":1,"prerenderedAt":908},["ShallowReactive",2],{"post:\u002Fposts\u002Fguide\u002Fguide-frontmatter":3,"posts:ordered":616},{"id":4,"title":5,"body":6,"category":601,"cover":602,"date":603,"description":604,"extension":605,"featured":606,"meta":607,"navigation":608,"path":609,"seo":610,"series":611,"seriesOrder":38,"stem":612,"tags":613,"__hash__":615},"posts\u002Fposts\u002Fguide\u002Fguide-frontmatter.md","frontmatter 每个字段是什么意思",{"type":7,"value":8,"toc":585},"minimark",[9,18,72,80,84,88,91,100,103,106,112,115,130,133,146,149,156,159,162,165,172,203,206,230,237,243,247,254,281,297,306,313,322,325,328,331,345,356,359,362,375,389,399,402,406,413,442,449,467,476,479,578,581],[10,11,12,13,17],"p",{},"每篇文章的开头都有一段被 ",[14,15,16],"code",{},"---"," 包起来的内容：",[19,20,25],"pre",{"className":21,"code":22,"language":23,"meta":24,"style":24},"language-markdown shiki shiki-themes github-light github-dark","---\ntitle: 文章标题\ndescription: 一句话摘要\ndate: 2026-10-10\ncategory: 指南\ntags: [写作, frontmatter]\n---\n","markdown","",[14,26,27,36,43,49,55,61,67],{"__ignoreMap":24},[28,29,32],"span",{"class":30,"line":31},"line",1,[28,33,35],{"class":34},"sq-ep","---\n",[28,37,39],{"class":30,"line":38},2,[28,40,42],{"class":41},"sVt8B","title: 文章标题\n",[28,44,46],{"class":30,"line":45},3,[28,47,48],{"class":41},"description: 一句话摘要\n",[28,50,52],{"class":30,"line":51},4,[28,53,54],{"class":41},"date: 2026-10-10\n",[28,56,58],{"class":30,"line":57},5,[28,59,60],{"class":41},"category: 指南\n",[28,62,64],{"class":30,"line":63},6,[28,65,66],{"class":41},"tags: [写作, frontmatter]\n",[28,68,70],{"class":30,"line":69},7,[28,71,35],{"class":34},[10,73,74,75,79],{},"这段叫 ",[76,77,78],"strong",{},"frontmatter","，用来描述这篇文章的元信息。下面的正文才是文章内容。",[81,82,83],"h2",{"id":83},"必填的三个",[85,86,87],"h3",{"id":87},"title",[10,89,90],{},"文章标题。会显示在文章页顶部、列表卡片里、浏览器标签页和搜索结果里。",[10,92,93,96,97,99],{},[76,94,95],{},"文件名和标题是两回事","——文件名决定网址，",[14,98,87],{}," 决定显示什么。所以文件名用英文、\n标题写中文完全没问题。",[85,101,102],{"id":102},"description",[10,104,105],{},"一句话摘要。它出现在三个地方：文章列表的卡片、首页的条目、以及搜索结果里的描述文字。",[10,107,108,111],{},[76,109,110],{},"别敷衍这一句","。搜索引擎结果里显示的就是它，写得清楚直接影响别人点不点进来。",[85,113,114],{"id":114},"date",[10,116,117,118,121,122,125,126,129],{},"发布日期，写成 ",[14,119,120],{},"2026-10-10"," 这种格式（",[76,123,124],{},"必须补零","，",[14,127,128],{},"2026-1-5"," 是不规范的）。",[10,131,132],{},"它决定：",[134,135,136,140,143],"ul",{},[137,138,139],"li",{},"文章在列表里的排序（新的在前）",[137,141,142],{},"首页「最新文章」的顺序",[137,144,145],{},"站点地图里的最后修改时间",[85,147,148],{"id":148},"category",[10,150,151,152,155],{},"分类，",[76,153,154],{},"一篇文章只能有一个","。",[10,157,158],{},"不写的话会被自动归到「未分类」，不会报错，但那篇文章就会显得像是忘了填。所以正经\n写文章时都该给一个。",[81,160,161],{"id":161},"可选的几个",[85,163,164],{"id":164},"tags",[10,166,167,168,171],{},"标签，",[76,169,170],{},"一篇可以有多个","，用数组写：",[19,173,177],{"className":174,"code":175,"language":176,"meta":24,"style":24},"language-yaml shiki shiki-themes github-light github-dark","tags:\n  - Git\n  - 版本控制\n","yaml",[14,178,179,187,196],{"__ignoreMap":24},[28,180,181,184],{"class":30,"line":31},[28,182,164],{"class":183},"s9eBZ",[28,185,186],{"class":41},":\n",[28,188,189,192],{"class":30,"line":38},[28,190,191],{"class":41},"  - ",[28,193,195],{"class":194},"sZZnC","Git\n",[28,197,198,200],{"class":30,"line":45},[28,199,191],{"class":41},[28,201,202],{"class":194},"版本控制\n",[10,204,205],{},"或者写成一行：",[19,207,209],{"className":174,"code":208,"language":176,"meta":24,"style":24},"tags: [Git, 版本控制]\n",[14,210,211],{"__ignoreMap":24},[28,212,213,215,218,221,224,227],{"class":30,"line":31},[28,214,164],{"class":183},[28,216,217],{"class":41},": [",[28,219,220],{"class":194},"Git",[28,222,223],{"class":41},", ",[28,225,226],{"class":194},"版本控制",[28,228,229],{"class":41},"]\n",[10,231,232,233,236],{},"和分类的区别：分类是「这篇属于哪一类」（互斥），标签是「这篇涉及什么」（可以交叉）。\n",[14,234,235],{},"#Git"," 这种标签能同时出现在「指南」和「工具」分类的文章上，分类就不行。",[10,238,239,242],{},[76,240,241],{},"不写就不写","，文章仍然会出现在「全部文章」和「按分类」视图里，只是不会出现在\n「按标签」视图。",[85,244,246],{"id":245},"series-和-seriesorder","series 和 seriesOrder",[10,248,249,250,253],{},"把几篇文章组成一个有阅读顺序的系列。",[76,251,252],{},"这两个要一起写","：",[19,255,257],{"className":174,"code":256,"language":176,"meta":24,"style":24},"series: 博客使用指南\nseriesOrder: 2\n",[14,258,259,270],{"__ignoreMap":24},[28,260,261,264,267],{"class":30,"line":31},[28,262,263],{"class":183},"series",[28,265,266],{"class":41},": ",[28,268,269],{"class":194},"博客使用指南\n",[28,271,272,275,277],{"class":30,"line":38},[28,273,274],{"class":183},"seriesOrder",[28,276,266],{"class":41},[28,278,280],{"class":279},"sj4cs","2\n",[134,282,283,288],{},[137,284,285,287],{},[14,286,263],{}," 是系列名，同名的文章会被归到一起",[137,289,290,292,293,296],{},[14,291,274],{}," 是",[76,294,295],{},"在这个系列里的阅读顺序","，从 1 开始",[10,298,299,300,305],{},"顺序",[76,301,302,303],{},"不看日期，只看 ",[14,304,274],{},"。这样你就算隔了几个月补写一篇中间章节，也能把它\n插到正确的位置。",[10,307,308,309,312],{},"文章页底部会出现「《系列名》上一篇 \u002F 下一篇」的导航，首页也会出现「系列专栏」卡片。\n",[76,310,311],{},"系列只有一篇文章时不算系列","，不会显示这些导航。",[10,314,315,316,318,319,321],{},"只有写了 ",[14,317,263],{}," 但没写 ",[14,320,274],{}," 时，那篇会被当作顺序 0，排在系列最前面。",[85,323,324],{"id":324},"cover",[10,326,327],{},"自定义封面。不写的话，系统会按文章的文件路径自动分配一张默认封面（同一篇文章每次\n都是同一张，不会变）。",[10,329,330],{},"想用自己的图：",[19,332,334],{"className":174,"code":333,"language":176,"meta":24,"style":24},"cover: \u002Fimages\u002Fmy-cover.png\n",[14,335,336],{"__ignoreMap":24},[28,337,338,340,342],{"class":30,"line":31},[28,339,324],{"class":183},[28,341,266],{"class":41},[28,343,344],{"class":194},"\u002Fimages\u002Fmy-cover.png\n",[10,346,347,348,351,352,355],{},"路径规则和正文里的图片一样——放在 ",[14,349,350],{},"public\u002Fimages\u002F"," 下，用 ",[14,353,354],{},"\u002Fimages\u002F..."," 引用。",[10,357,358],{},"封面出现在列表卡片、首页，以及分享到社交平台时的卡片缩略图上。",[85,360,361],{"id":361},"featured",[10,363,364,365,368,369,372,373,155],{},"是否精选，值只有 ",[14,366,367],{},"true"," 或 ",[14,370,371],{},"false","，默认 ",[14,374,371],{},[19,376,378],{"className":174,"code":377,"language":176,"meta":24,"style":24},"featured: true\n",[14,379,380],{"__ignoreMap":24},[28,381,382,384,386],{"class":30,"line":31},[28,383,361],{"class":183},[28,385,266],{"class":41},[28,387,388],{"class":279},"true\n",[10,390,391,398],{},[76,392,393,394,397],{},"首页的「精选文章」模块只显示标了 ",[14,395,396],{},"featured: true"," 的文章，没有任何自动兜底","。一篇\n都不标，那个模块就整个不显示。",[10,400,401],{},"所以它是纯手工挑选的：挑你希望访客第一眼看到的那几篇。别标太多，标多了就失去\"精选\"\n的意义了。",[81,403,405],{"id":404},"一个很容易踩的坑冒号要加引号","一个很容易踩的坑：冒号要加引号",[10,407,408,409,412],{},"YAML 里，",[76,410,411],{},"值里面如果出现「冒号加空格」，必须用引号包起来","，否则会被当成键值对：",[19,414,416],{"className":174,"code":415,"language":176,"meta":24,"style":24},"# 错的\ntags:\n  - Counter-Strike: Global Offensive\n",[14,417,418,424,430],{"__ignoreMap":24},[28,419,420],{"class":30,"line":31},[28,421,423],{"class":422},"sJ8bj","# 错的\n",[28,425,426,428],{"class":30,"line":38},[28,427,164],{"class":183},[28,429,186],{"class":41},[28,431,432,434,437,439],{"class":30,"line":45},[28,433,191],{"class":41},[28,435,436],{"class":183},"Counter-Strike",[28,438,266],{"class":41},[28,440,441],{"class":194},"Global Offensive\n",[10,443,444,445,448],{},"上面这样写，那个标签会变成一个对象 ",[14,446,447],{},"{ \"Counter-Strike\": \"Global Offensive\" }","，页面上\n就会原样显示出这串 JSON。正确写法：",[19,450,452],{"className":174,"code":451,"language":176,"meta":24,"style":24},"tags:\n  - \"Counter-Strike: Global Offensive\"\n",[14,453,454,460],{"__ignoreMap":24},[28,455,456,458],{"class":30,"line":31},[28,457,164],{"class":183},[28,459,186],{"class":41},[28,461,462,464],{"class":30,"line":38},[28,463,191],{"class":41},[28,465,466],{"class":194},"\"Counter-Strike: Global Offensive\"\n",[10,468,469,472,473,475],{},[76,470,471],{},"加了引号就正常了。"," 判断标准很简单：值里有 ",[14,474,266],{},"（冒号加空格）就加引号，没有就不用。",[81,477,478],{"id":478},"完整示例",[19,480,482],{"className":174,"code":481,"language":176,"meta":24,"style":24},"---\ntitle: Git 安装与基本使用\ndescription: 从装好 Git 到跑通日常提交流程，把最常用的几条命令讲清楚。\ndate: 2026-10-04\ncategory: 工具\ntags:\n  - Git\n  - 版本控制\nseries: Git 入门\nseriesOrder: 1\nfeatured: true\n---\n",[14,483,484,489,498,507,516,525,531,537,544,554,564,573],{"__ignoreMap":24},[28,485,486],{"class":30,"line":31},[28,487,35],{"class":488},"sScJk",[28,490,491,493,495],{"class":30,"line":38},[28,492,87],{"class":183},[28,494,266],{"class":41},[28,496,497],{"class":194},"Git 安装与基本使用\n",[28,499,500,502,504],{"class":30,"line":45},[28,501,102],{"class":183},[28,503,266],{"class":41},[28,505,506],{"class":194},"从装好 Git 到跑通日常提交流程，把最常用的几条命令讲清楚。\n",[28,508,509,511,513],{"class":30,"line":51},[28,510,114],{"class":183},[28,512,266],{"class":41},[28,514,515],{"class":279},"2026-10-04\n",[28,517,518,520,522],{"class":30,"line":57},[28,519,148],{"class":183},[28,521,266],{"class":41},[28,523,524],{"class":194},"工具\n",[28,526,527,529],{"class":30,"line":63},[28,528,164],{"class":183},[28,530,186],{"class":41},[28,532,533,535],{"class":30,"line":69},[28,534,191],{"class":41},[28,536,195],{"class":194},[28,538,540,542],{"class":30,"line":539},8,[28,541,191],{"class":41},[28,543,202],{"class":194},[28,545,547,549,551],{"class":30,"line":546},9,[28,548,263],{"class":183},[28,550,266],{"class":41},[28,552,553],{"class":194},"Git 入门\n",[28,555,557,559,561],{"class":30,"line":556},10,[28,558,274],{"class":183},[28,560,266],{"class":41},[28,562,563],{"class":279},"1\n",[28,565,567,569,571],{"class":30,"line":566},11,[28,568,361],{"class":183},[28,570,266],{"class":41},[28,572,388],{"class":279},[28,574,576],{"class":30,"line":575},12,[28,577,35],{"class":488},[10,579,580],{},"下一篇讲正文部分——Markdown 怎么写，以及本站对标题、链接、图片、代码块做了哪些处理。",[582,583,584],"style",{},"html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":24,"searchDepth":45,"depth":45,"links":586},[587,593,599,600],{"id":83,"depth":38,"text":83,"children":588},[589,590,591,592],{"id":87,"depth":45,"text":87},{"id":102,"depth":45,"text":102},{"id":114,"depth":45,"text":114},{"id":148,"depth":45,"text":148},{"id":161,"depth":38,"text":161,"children":594},[595,596,597,598],{"id":164,"depth":45,"text":164},{"id":245,"depth":45,"text":246},{"id":324,"depth":45,"text":324},{"id":361,"depth":45,"text":361},{"id":404,"depth":38,"text":405},{"id":478,"depth":38,"text":478},"指南",null,"2026-10-04","文章开头那段被横线包住的字段，逐个说明作用、默认行为和写错的后果。","md",false,{},true,"\u002Fposts\u002Fguide\u002Fguide-frontmatter",{"title":5,"description":604},"博客使用指南","posts\u002Fguide\u002Fguide-frontmatter",[614,78],"写作","sp0LlZYzQmCTeCjmPQMCaVQKY1iFgKTyyiI7QlKo1iI",[617,624,630,636,642,648,654,660,666,672,678,684,690,696,702,708,714,719,724,729,734,739,744,749,754,759,764,769,774,780,784,788,792,796,800,804,808,812,816,820,824,830,834,839,843,847,851,855,859,863,867,872,876,880,885,890,895,899,903,904],{"path":618,"title":619,"description":620,"date":621,"series":622,"seriesOrder":623},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-28","软件分析与设计笔记 28：draw.io 作图手册：五张图的符号位置、落笔顺序与自检","不模拟软件界面，只讲清三件事：每个 UML 符号在 draw.io 里搜什么词、一张图该按什么顺序落笔、画完拿什么标准自查。覆盖用例图、活动图、顺序图、类图、界面草图五种图纸，末尾附「最容易画反的十二笔」总检表。","2026-11-19","软件分析与设计笔记",28,{"path":625,"title":626,"description":627,"date":628,"series":622,"seriesOrder":629},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-27","软件分析与设计笔记 27：Paper 1 应试：从读案例到交卷的一次完整演算","拿一份完整的案例，从头到尾走一遍：怎么读案例列角色、怎么在四个小问之间分配时间、每一张图从哪一句话推出来、两张表怎么填、交卷前拿什么清单自查。附 C25 真题与样卷的题型分值对照。","2026-11-18",27,{"path":631,"title":632,"description":633,"date":634,"series":622,"seriesOrder":635},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-26","软件分析与设计笔记 26：总结：把整条链路串起来","系列收尾：从需求到代码的完整链路回顾、每一环的产出与验收方式、六条贯穿全系列的原则，以及一份可以直接拿去做项目自查的清单。","2026-11-17",26,{"path":637,"title":638,"description":639,"date":640,"series":622,"seriesOrder":641},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-25","软件分析与设计笔记 25：代码重构：坏味道与手法","重构不改变外部行为、只改善内部结构：四种常见坏味道与对应手法、为什么动手之前必须先有测试、什么时候该重构，以及重构和前面那些设计模型是什么关系。","2026-11-16",25,{"path":643,"title":644,"description":645,"date":646,"series":622,"seriesOrder":647},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-24","软件分析与设计笔记 24：设计原则：内聚、耦合与多态","好设计怎么衡量：内聚与耦合分别在说什么、一次从「差设计」到「多态重设计」的完整对照、抽象类与接口的选择依据，以及复用为什么会从优势变成风险。","2026-11-15",24,{"path":649,"title":650,"description":651,"date":652,"series":622,"seriesOrder":653},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-23","软件分析与设计笔记 23：设计建模：从对象模型到能实现的方案","分析模型能用但还不能直接开工：对象模型怎么映射到关系模型、继承映射的三种方案怎么选、数据访问层与 Data Broker 解决什么问题，以及三层架构与 MVC 的分工。","2026-11-14",23,{"path":655,"title":656,"description":657,"date":658,"series":622,"seriesOrder":659},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-22","软件分析与设计笔记 22：分析建模：边界、实体与控制对象","不经过分析直接写代码会踩什么坑、三种分析对象各管一段、怎么用顺序图完成一次用例实现，以及从顺序图导出类的属性、操作与关系的方法。","2026-11-13",22,{"path":661,"title":662,"description":663,"date":664,"series":622,"seriesOrder":665},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-21","软件分析与设计笔记 21：UML：类图与顺序图","为什么需要一种共同的画法：类符号三格怎么画、五种关系的符号与设计含义、每种关系落到 Java 是什么写法，顺序图的三要素怎么摆；以及这三种最容易找不到的符号在 draw.io 里各搜什么词。","2026-11-12",21,{"path":667,"title":668,"description":669,"date":670,"series":622,"seriesOrder":671},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-20","软件分析与设计笔记 20：面向对象概念：对象、关系与多态","面向对象不是「用某个语言写代码」：对象与类的区别、封装真正在保护什么、五种关系（依赖、关联、聚合、组合、继承）各自何时用，以及多态为什么能减少条件判断。","2026-11-11",20,{"path":673,"title":674,"description":675,"date":676,"series":622,"seriesOrder":677},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-19","软件分析与设计笔记 19：规范化与逻辑数据模型","一次改地址引发的数据不一致，讲清规范化的真正动机；UNF 到 3NF 每一步在解决什么问题，派生字段为什么不能存，优化为什么和规范化方向相反，以及逻辑数据模型在 3NF 之上补了什么。","2026-11-10",19,{"path":679,"title":680,"description":681,"date":682,"series":622,"seriesOrder":683},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-18","软件分析与设计笔记 18：数据库分析：实体、关系与数据字典","为什么不能拿到需求就动手建表：实体与关系怎么判定、基数为什么必须由业务方确认、数据命名要遵守什么规则，以及数据字典四列里最容易被空着的那一列。","2026-11-09",18,{"path":685,"title":686,"description":687,"date":688,"series":622,"seriesOrder":689},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-17","软件分析与设计笔记 17：用生成式 AI 做设计与开发：能用的场景与要防的坑","生成式 AI 在工作流里真正站得住的三个场景 —— 造示例数据、解释陌生代码、起草初稿；它为什么会复现社会偏见、为什么会编得像真的，以及哪些内容绝不能直接采用。","2026-11-08",17,{"path":691,"title":692,"description":693,"date":694,"series":622,"seriesOrder":695},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-16","软件分析与设计笔记 16：从 persona 到 URS：一份交付物的完整骨架","把前面十几篇串成一份能交出去的东西：用户需求规格说明书的九个部分、每一章来自哪个环节、由谁确认，以及面向决策者的提案该讲清哪三件事。","2026-11-07",16,{"path":697,"title":698,"description":699,"date":700,"series":622,"seriesOrder":701},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-15","软件分析与设计笔记 15：非功能需求：把「快、稳、安全」变成数字","为什么「系统要快」不是一条需求：非功能需求怎么量化，决定性能的用户量、交易量、数据量三张表怎么估，安全需求要写清什么，以及可靠性的「不可用」该怎么定义。","2026-11-06",15,{"path":703,"title":704,"description":705,"date":706,"series":622,"seriesOrder":707},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-14","软件分析与设计笔记 14：软件测试：层级、方法与等价类划分","「我们测过了」这句话问题在哪：为什么静态评审和动态测试缺一不可，五个测试层级各自验证什么，白盒与黑盒的差别，以及用等价类划分和边界值把无限输入变成有限用例的方法。","2026-11-05",14,{"path":709,"title":710,"description":711,"date":712,"series":622,"seriesOrder":713},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-13","软件分析与设计笔记 13：需求获取：五种调查方法与一场访谈","需求从哪里来：五种事实调查方法各自适合回答什么、代价是什么，访谈从准备到记录的全过程，问卷设计里最容易犯的错，以及访谈记录必须写下来的那几项信息。","2026-11-04",13,{"path":715,"title":716,"description":717,"date":718,"series":622,"seriesOrder":575},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-12","软件分析与设计笔记 12：前端设计：把流程变成屏幕","界面设计不是「画得好看」：从活动图走到屏幕的三步，CRUD 任务流怎么当检查表，界面必须回答的三个问题，信息架构与五种导航类型，视觉一致性与留白，以及移动端与 Web 端的差别。","2026-11-03",{"path":720,"title":721,"description":722,"date":723,"series":622,"seriesOrder":566},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-11","软件分析与设计笔记 11：Agentic AI 与业务流程自动化","AI agent 到底是什么：五项能力与四个核心组件，什么场景该用定时任务、什么该用程序、什么才值得用 agent，两种实现路径的差别，必须提前防住的四类失败模式，以及设计方法从提示词到编排的演进。","2026-11-02",{"path":725,"title":726,"description":727,"date":728,"series":622,"seriesOrder":556},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-10","软件分析与设计笔记 10：精炼用例模型：include、extend 与泛化","三种精炼用例关系的判断标准：include 什么时候用、它和 extend 的区别到底在哪、参与者泛化与用例泛化各解决什么问题，以及精炼到什么程度就该停手。","2026-11-01",{"path":730,"title":731,"description":732,"date":733,"series":622,"seriesOrder":546},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-09","软件分析与设计笔记 09：功能需求（二）：从流程到业务实体","活动图画完之后，怎么从流程里筛出真正的业务实体：三条判断标准、哪些名词其实不该建实体、属性从哪里来，以及领域模型和后面的数据模型分别负责什么。","2026-10-31",{"path":735,"title":736,"description":737,"date":738,"series":622,"seriesOrder":539},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-08","软件分析与设计笔记 08：功能需求（一）：用例模型与活动图","从用户故事到用例的翻译过程：什么才算「好」的参与者，系统边界怎么划，用例描述必须写清哪四件事，活动图怎么把分支、并行与泳道画清楚，以及这两个图在 draw.io 里各用哪个形状、最容易画错哪一笔。","2026-10-30",{"path":740,"title":741,"description":742,"date":743,"series":622,"seriesOrder":69},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-07","软件分析与设计笔记 07：用户故事：把需求写成可验收的一句话","用户故事的三段结构，怎么从用户画像和数据地图里把它提取出来，一条故事多大算合适、时序为什么也是需求的一部分，以及验收标准怎么写才算真的可验收。","2026-10-29",{"path":745,"title":746,"description":747,"date":748,"series":622,"seriesOrder":63},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-06","软件分析与设计笔记 06：范围界定（数据侧）：用数据校验你的判断","访谈结论和数字对不上时该怎么办：分析的四个层次分别在回答什么问题、为什么不能跳级、数据准备与搜集怎么做成一张应用地图，以及数据最容易在哪几个地方骗你。","2026-10-28",{"path":750,"title":751,"description":752,"date":753,"series":622,"seriesOrder":57},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-05","软件分析与设计笔记 05：范围界定（用户侧）：用户画像与客户旅程图","为什么「所有用户」是一个陷阱，项目边界该怎么划，用户画像要写哪五个要素、最容易写成什么废纸，客户旅程图怎么把阶段、想法和情绪画在同一张纸上，以及怎么从这两样东西一步步推到可验证的需求。","2026-10-27",{"path":755,"title":756,"description":757,"date":758,"series":622,"seriesOrder":51},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-04","软件分析与设计笔记 04：接手陌生案例的第一步：三问与一张表","拿到一个完全陌生的业务案例，怎么从零开始不跑偏：只问 Who、What、Why 三个问题，把「问题—事实—假设—理由」记成一张四列表，说清为什么假设必须写明理由，以及带着问题进访谈为什么比空手去有效得多。","2026-10-26",{"path":760,"title":761,"description":762,"date":763,"series":622,"seriesOrder":45},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-03","软件分析与设计笔记 03：Agile 与 Scrum：迭代、角色与产出物","从「三周做完交付，客户说这不是我要的」讲起，说清瀑布式与迭代式的根本差别，Scrum 的三个角色和三种产出物，一个 sprint 里四次固定活动各自在解决什么问题，以及敏捷里最常见的几个误解。","2026-10-25",{"path":765,"title":766,"description":767,"date":768,"series":622,"seriesOrder":38},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-02","软件分析与设计笔记 02：设计思维、用户驱动与数据驱动","从「客服要一个能一次看完所有排期的界面」这个翻车案例讲起，说清设计思维到底是什么、用户驱动与数据驱动各自能看见什么又看不见什么、为什么真正的落点是把两者合起来的 data-informed design，以及访谈中怎么问出有用的信息。","2026-10-24",{"path":770,"title":771,"description":772,"date":773,"series":622,"seriesOrder":31},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-01","软件分析与设计笔记 01：课程地图与从需求到设计的主干","这一篇不写具体方法，先把整条链路铺开：软件分析与设计到底要解决什么问题，从需求到设计分成哪两段，中间有哪十几个环节，一份完整的交付物里应该有什么，以及后面 27 篇笔记怎么排、新人该按什么顺序读。","2026-10-23",{"path":775,"title":776,"description":777,"date":778,"series":779,"seriesOrder":31},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-01","Spring 学习笔记 01：IoC、依赖注入与第一个 Spring Boot 应用","从「手写 new 出来的三层结构」的痛点讲起，说清 IoC 容器、Bean 与依赖注入是怎么回事，再用 Maven 与 Spring Initializr 跑起第一个能返回 JSON 的应用。","2026-10-15","Spring 学习笔记",{"path":781,"title":782,"description":783,"date":778,"series":779,"seriesOrder":38},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-02","Spring 学习笔记 02：Spring Data JPA 基础——实体映射与 Repository","用 ORM 把类映射到表：@Entity、@Id、@GeneratedValue 怎么用，CrudRepository 三层接口怎么选，H2 与 MySQL 怎么配，以及 ddl-auto 到底该写哪个值。",{"path":785,"title":786,"description":787,"date":778,"series":779,"seriesOrder":45},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-03","Spring 学习笔记 03：JPA 查询——派生方法、JPQL 与分页排序","Repository 自带的方法只够按主键查，这篇讲三种自己造查询的方式：方法名派生、@Query 写 JPQL、原生 SQL，以及 Pageable 分页排序和投影返回。",{"path":789,"title":790,"description":791,"date":778,"series":779,"seriesOrder":51},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-04","Spring 学习笔记 04：JPA 关联映射与仓储测试","一对多、多对多怎么映射，谁负责维护外键，FetchType 与 CascadeType 该怎么选，顺带用 @DataJpaTest 与 AssertJ 把仓储层测起来。",{"path":793,"title":794,"description":795,"date":778,"series":779,"seriesOrder":57},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-05","Spring 学习笔记 05：Spring MVC 与 Thymeleaf 入门","一次页面请求在 Spring MVC 里走了哪几步，@Controller 怎么把数据交给模板，@PathVariable 与 @RequestParam 怎么取参数，以及控制器为什么必须是无状态的。",{"path":797,"title":798,"description":799,"date":778,"series":779,"seriesOrder":63},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-06","Spring 学习笔记 06：表单绑定与服务端校验","把表单字段绑到对象上，用 Bean Validation 注解做服务端校验，把错误信息显示回用户刚填的那一页，再补上自定义校验注解与全局异常处理。",{"path":801,"title":802,"description":803,"date":778,"series":779,"seriesOrder":69},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-07","Spring 学习笔记 07：Thymeleaf 片段复用与国际化","用 th:fragment 与 th:insert\u002Fth:replace 把导航栏、页脚抽成片段，页面套用统一布局，再用 messages.properties 与 LocaleResolver 做中英文切换。",{"path":805,"title":806,"description":807,"date":778,"series":779,"seriesOrder":539},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-08","Spring 学习笔记 08：HTTP Session 与会话状态管理","HTTP 无状态带来的问题，Cookie 与 Session 怎么分工，Spring 里读写会话的几种方式，以及会话固定、超时、多实例共享这些必须想清楚的事。",{"path":809,"title":810,"description":811,"date":778,"series":779,"seriesOrder":546},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-09","Spring 学习笔记 09：拦截器 HandlerInterceptor","登录检查、权限判断、请求耗时统计这类横切逻辑该放哪：HandlerInterceptor 的三个回调各在什么时机执行，怎么注册与排除路径，以及它和过滤器的分工。",{"path":813,"title":814,"description":815,"date":778,"series":779,"seriesOrder":556},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-10","Spring 学习笔记 10：Service 层与事务","一组数据库操作要么全成功要么全失败，靠 @Transactional 怎么做到；传播行为、隔离级别、回滚规则怎么选，以及自调用失效、乐观锁悲观锁这些实战里的坑。",{"path":817,"title":818,"description":819,"date":778,"series":779,"seriesOrder":566},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-11","Spring 学习笔记 11：REST API 基础——把 Service 暴露成接口","同一套 Service 怎么同时服务页面和客户端：@RestController 的路由与方法语义、状态码怎么给、DTO 怎么定，以及 MockMvc 端到端和切片测试的两种写法与各自的坑。",{"path":821,"title":822,"description":823,"date":778,"series":779,"seriesOrder":575},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-12","Spring 学习笔记 12：REST 进阶——版本、更新、跨域与文档化","接口能跑通之后要处理的几件事：URL 与响应结构怎么定、版本怎么演进、更新怎么做到可安全重试、CORS 怎么配、HATEOAS 与 Spring Data REST 该不该用。",{"path":825,"title":826,"description":827,"date":828,"series":829,"seriesOrder":51},"\u002Fposts\u002Fjava\u002Fjava-functionalprogramming-notes","Java 函数式编程笔记：Lambda、函数式接口与 Streams","学习 Java 函数式编程时的个人笔记：Lambda 表达式的五步简写与方法引用、常见函数式接口、Stream 流水线与惰性求值，以及创建流、中间操作、终止操作与收集器的用法。示例代码均为自写，运行结果来自本地实测。","2026-10-13","Java 学习笔记",{"path":831,"title":832,"description":833,"date":828,"series":829,"seriesOrder":45},"\u002Fposts\u002Fjava\u002Fjava-generics-notes","Java 泛型笔记：泛型方法、有界类型与泛型类","学习 Java 泛型时的个人笔记：从重复的重载方法与多态尝试讲起，再到泛型方法与类型推断、有界泛型类型、Comparable 与 Number 边界，以及泛型类在集合中的用法。示例代码均为自写，运行结果来自本地实测。",{"path":835,"title":836,"description":837,"date":120,"series":838,"seriesOrder":51},"\u002Fposts\u002Fmysql\u002Fmysql-learning-04","MySQL 学习笔记 04：数据操纵（增删改）","MySQL 学习笔记第四篇：INSERT 插入（含批量插入与 INSERT ... SELECT）、UPDATE 更新、DELETE 删除，以及各自的坑。","SQL 学习笔记",{"path":840,"title":841,"description":842,"date":120,"series":838,"seriesOrder":57},"\u002Fposts\u002Fmysql\u002Fmysql-learning-05","MySQL 学习笔记 05：DDL 概览","MySQL 学习笔记第五篇：数据定义语言概览——Schema、Table、View、Index、Constraints 这几类对象分别对应哪些 CREATE \u002F ALTER \u002F DROP 命令。",{"path":844,"title":845,"description":846,"date":120,"series":838,"seriesOrder":63},"\u002Fposts\u002Fmysql\u002Fmysql-learning-06","MySQL 学习笔记 06：CREATE TABLE 与数据类型","MySQL 学习笔记第六篇：CREATE TABLE 的完整语法、常用数据类型的选型建议，以及外键的两种定义方式。",{"path":848,"title":849,"description":850,"date":120,"series":838,"seriesOrder":69},"\u002Fposts\u002Fmysql\u002Fmysql-learning-07","MySQL 学习笔记 07：索引","MySQL 学习笔记第七篇：索引的作用与 B+ 树结构、单列与复合索引的创建、索引的代价与适用场景。",{"path":852,"title":853,"description":854,"date":120,"series":838,"seriesOrder":539},"\u002Fposts\u002Fmysql\u002Fmysql-learning-08","MySQL 学习笔记 08：DROP 与 ALTER","MySQL 学习笔记第八篇：DROP 删除数据库对象、ALTER 修改表结构，以及常见的坑。",{"path":856,"title":857,"description":858,"date":120,"series":838,"seriesOrder":546},"\u002Fposts\u002Fmysql\u002Fmysql-learning-09","MySQL 学习笔记 09：约束与数据完整性","MySQL 学习笔记第九篇：SQL 约束——NOT NULL、CHECK、PRIMARY KEY、FOREIGN KEY 等如何保证数据完整性，以及它们的对比。",{"path":860,"title":861,"description":862,"date":120,"series":838,"seriesOrder":556},"\u002Fposts\u002Fmysql\u002Fmysql-learning-10","MySQL 学习笔记 10：视图","MySQL 学习笔记第十篇：视图（Views）的定义与特性、和表的对比、创建与使用，以及可更新视图的限制。",{"path":864,"title":865,"description":866,"date":120,"series":838,"seriesOrder":566},"\u002Fposts\u002Fmysql\u002Fmysql-learning-11","MySQL 学习笔记 11：存储过程","MySQL 学习笔记第十一篇：存储过程（Stored Procedures）的概念、创建与调用、带参数的写法，以及优缺点。",{"path":868,"title":869,"description":870,"date":871,"series":838,"seriesOrder":31},"\u002Fposts\u002Fmysql\u002Fmysql-learning-01","MySQL 学习笔记 01：MySQL 基础知识","MySQL 学习笔记第一篇：MySQL Server 与 Workbench 的安装，数据库与 DBMS 的基本概念，关系模型、ACID 事务、常见数据类型，以及后续的学习路线。","2026-10-09",{"path":873,"title":874,"description":875,"date":871,"series":838,"seriesOrder":38},"\u002Fposts\u002Fmysql\u002Fmysql-learning-02","MySQL 学习笔记 02：SELECT 查询与过滤","MySQL 学习笔记第二篇：SELECT 的基本语法与逻辑执行顺序，WHERE 过滤（比较、LIKE、IN、BETWEEN、NULL）、各种 JOIN、UNION 与子查询。",{"path":877,"title":878,"description":879,"date":871,"series":838,"seriesOrder":45},"\u002Fposts\u002Fmysql\u002Fmysql-learning-03","MySQL 学习笔记 03：聚合、分组与输出控制","MySQL 学习笔记第三篇：COUNT\u002FSUM\u002FAVG 等聚合函数、GROUP BY 分组、HAVING 过滤、ORDER BY 与 LIMIT，以及一条 SELECT 的完整逻辑执行顺序。",{"path":881,"title":882,"description":883,"date":884,"series":829,"seriesOrder":38},"\u002Fposts\u002Fjava\u002Fjava-oop-notes","Java 面向对象笔记：类、继承、多态与异常","学习 Java 面向对象编程时的个人笔记：类与对象、封装与访问修饰符、继承与多态、集合、抽象类与接口、异常处理。示例代码均为自写，运行结果来自本地实测。","2026-10-06",{"path":886,"title":887,"description":888,"date":889,"series":829,"seriesOrder":31},"\u002Fposts\u002Fjava\u002Fjava-basics-notes","Java 基础语法笔记：从环境安装到方法与数组","学习 Java 基础语法时的个人笔记：JDK 安装、输入输出、变量与运算符、条件与循环、字符串、数组与方法。示例代码均为自写，运行结果来自本地实测。","2026-10-05",{"path":891,"title":892,"description":893,"date":603,"series":894,"seriesOrder":31},"\u002Fposts\u002Fgit\u002Fgit-install-and-basics","Git 安装与基本使用","从装好 Git 到跑通日常提交流程，把最常用的几条命令和它们背后的三个区域讲清楚。","Git 入门",{"path":896,"title":897,"description":898,"date":603,"series":894,"seriesOrder":38},"\u002Fposts\u002Fgit\u002Flocal-remote-repository","本地远程仓库的部署","用自己的机器当 Git 服务器：建一个裸仓库、走 SSH 连上去，把本地提交推上去。",{"path":900,"title":901,"description":902,"date":603,"series":611,"seriesOrder":31},"\u002Fposts\u002Fguide\u002Fguide-file-layout","文件都放在哪","文章、图片、封面分别放在仓库的什么位置，哪些目录可以放手改、哪些碰了会出问题。",{"path":609,"title":5,"description":604,"date":603,"series":611,"seriesOrder":38},{"path":905,"title":906,"description":907,"date":603,"series":611,"seriesOrder":45},"\u002Fposts\u002Fguide\u002Fguide-markdown","正文怎么写 —— Markdown 与排版效果","标题、链接、图片、代码、表格分别怎么写，以及本站对它们做了哪些自定义处理。",1793268151014]