[{"data":1,"prerenderedAt":2923},["ShallowReactive",2],{"post:\u002Fposts\u002Fswdesign\u002Fsw-design-notes-28":3,"posts:ordered":2621},{"id":4,"title":5,"body":6,"category":2604,"cover":2605,"date":2606,"description":2607,"extension":2608,"featured":2609,"meta":2610,"navigation":1135,"path":2611,"seo":2612,"series":2613,"seriesOrder":2614,"stem":2615,"tags":2616,"__hash__":2620},"posts\u002Fposts\u002FswDesign\u002Fsw-design-notes-28.md","软件分析与设计笔记 28：draw.io 作图手册：五张图的符号位置、落笔顺序与自检",{"type":7,"value":8,"toc":2560},"minimark",[9,21,26,41,48,51,73,76,80,85,88,98,123,127,178,181,185,192,203,279,289,295,298,302,305,387,394,401,408,412,416,487,490,516,519,531,535,538,553,560,567,571,574,649,652,677,705,709,712,727,730,734,748,751,759,815,821,824,840,844,848,958,976,983,991,995,1002,1044,1050,1057,1061,1064,1106,1120,1124,1162,1166,1170,1222,1235,1261,1265,1268,1274,1277,1300,1311,1315,1325,1329,1362,1366,1370,1435,1446,1470,1474,1556,1559,1582,1586,1662,1669,1673,1676,1729,1733,1773,1777,1780,1804,1815,1846,1850,1853,1859,1862,2065,2069,2072,2105,2119,2122,2152,2155,2251,2254],[10,11,12],"blockquote",{},[13,14,15,16,20],"p",{},"这是我把课程里所有画图要求整理成的一份作图手册。符号与方向规则来自课程讲义、workshop 批改批注与 UML 规范；draw.io 的操作要点是我自己在用的路径。工具版本更新后菜单文字可能变，所以",[17,18,19],"strong",{},"优先给搜索词和属性名，而不是菜单路径","。理解有偏差的地方欢迎指出。",[22,23,25],"h2",{"id":24},"_0-画对了但被扣分了","0 画对了，但被扣分了",[13,27,28,29,33,34,33,37,40],{},"一份作业交上去，回来的批注往往只有几个词：",[30,31,32],"code",{},"Wrong notation","、",[30,35,36],{},"Wrong direction",[30,38,39],{},"Wrong access","。",[13,42,43,44,47],{},"问题不在「不会画」—— 大多数人看图是看得懂的。",[17,45,46],{},"问题在于画的时候没有区分「读」和「写」、「包含」和「扩展」、「聚合」和「组合」","。这些差别在口语里都可以含糊过去，但图上差一笔就是差一笔的分。",[13,49,50],{},"这篇不模拟软件界面（那种图一改版就废），只解决三个具体问题：",[52,53,54,61,67],"ol",{},[55,56,57,60],"li",{},[17,58,59],{},"这个符号在哪里？"," —— 每个 UML 元素给一个搜索词，搜到就能拖；",[55,62,63,66],{},[17,64,65],{},"先画什么后画什么？"," —— 每种图的落笔顺序，照做不会返工；",[55,68,69,72],{},[17,70,71],{},"画完怎么自查？"," —— 一张对照表，逐条打勾。",[13,74,75],{},"三件事对上了，画图就不再是「凭感觉」。",[22,77,79],{"id":78},"_1-开始之前两个位置和一套属性","1 开始之前：两个位置和一套属性",[81,82,84],"h3",{"id":83},"_11-形状库在哪里","1.1 形状库在哪里",[13,86,87],{},"draw.io 的界面只有三个位置需要记。不需要记菜单文字，只需要记住形状库在左边、格式面板在右边：",[89,90,95],"pre",{"className":91,"code":93,"language":94},[92],"language-text","┌────────────────────────────────────────────┐\n│  工具栏（撤销、导出、缩放）                  │\n├────────────┬───────────────────────────────┤\n│            │                               │\n│  形状库     │           画布                 │\n│  ◄ 在这里   │                               │\n│            │                               │\n│  [搜索框]   │                               │\n├────────────┴───────────────────────────────┤\n│  格式面板（选中对象后才出现）◄ 在这里         │\n└────────────────────────────────────────────┘\n","text",[30,96,93],{"__ignoreMap":97},"",[13,99,100,103,104,107,108,111,112,115,116,33,119,122],{},[17,101,102],{},"第一步永远是打开 UML 形状库","：左下角 ",[30,105,106],{},"More Shapes","（有的版本叫 ",[30,109,110],{},"+ More Shapes","）→ 勾选 ",[17,113,114],{},"UML"," → 应用。没勾之前，左侧搜不到 ",[30,117,118],{},"actor",[30,120,121],{},"boundary"," 这些词。",[81,124,126],{"id":125},"_12-三个动作覆盖-90-的操作","1.2 三个动作覆盖 90% 的操作",[128,129,130,143],"table",{},[131,132,133],"thead",{},[134,135,136,140],"tr",{},[137,138,139],"th",{},"想做什么",[137,141,142],{},"怎么做",[144,145,146,155,166],"tbody",{},[134,147,148,152],{},[149,150,151],"td",{},"加一个形状",[149,153,154],{},"在搜索框打词 → 拖进画布",[134,156,157,160],{},[149,158,159],{},"改文字",[149,161,162,165],{},[17,163,164],{},"双击","形状（不是单击）→ 直接打字",[134,167,168,171],{},[149,169,170],{},"连一条线",[149,172,173,174,177],{},"鼠标移到形状",[17,175,176],{},"边缘","，出现小箭头 → 拖到目标形状",[13,179,180],{},"连线的关键是「出现小箭头」。如果拖出来的是虚线框，说明点到形状内部了，不是边缘。",[81,182,184],{"id":183},"_13-端点样式菱形和三角都靠它","1.3 端点样式：菱形和三角都靠它",[13,186,187,188,191],{},"这是全篇最值钱的一条。",[17,189,190],{},"聚合、组合、继承这三种符号不在形状库里","，它们都是通过改连线的端点样式画出来的。",[13,193,194,195,198,199,202],{},"选中一条线后，右侧格式面板找到 ",[30,196,197],{},"Line"," 一栏（找不到就点面板底部的 ",[30,200,201],{},"+"," 展开）：",[128,204,205,215],{},[131,206,207],{},[134,208,209,212],{},[137,210,211],{},"想要的符号",[137,213,214],{},"操作",[144,216,217,236,249,261,270],{},[134,218,219,222],{},[149,220,221],{},"空心三角（继承）",[149,223,224,225,228,229,232,233],{},"端点选 ",[30,226,227],{},"block"," 或 ",[30,230,231],{},"open arrow","，然后设 ",[30,234,235],{},"filled = 0",[134,237,238,241],{},[149,239,240],{},"空心菱形（聚合）",[149,242,224,243,246,247],{},[30,244,245],{},"diamond","，设 ",[30,248,235],{},[134,250,251,254],{},[149,252,253],{},"实心菱形（组合）",[149,255,224,256,246,258],{},[30,257,245],{},[30,259,260],{},"filled = 1",[134,262,263,266],{},[149,264,265],{},"开放箭头（依赖\u002F转移）",[149,267,224,268],{},[30,269,231],{},[134,271,272,275],{},[149,273,274],{},"实心箭头（消息）",[149,276,224,277],{},[30,278,227],{},[13,280,281,284,285,288],{},[17,282,283],{},"记不住菜单就记属性名","。在格式面板底部点 ",[30,286,287],{},"Edit Style","，直接打进这串：",[89,290,293],{"className":291,"code":292,"language":94},[92],"endArrow=block;endFill=0;      ← 空心三角\nendArrow=diamond;endFill=0;    ← 空心菱形\nendArrow=diamond;endFill=1;    ← 实心菱形\n",[30,294,292],{"__ignoreMap":97},[13,296,297],{},"属性名比菜单文字稳定得多，跨版本都认。",[22,299,301],{"id":300},"_2-先决定画哪张图","2 先决定画哪张图",[13,303,304],{},"六个题型对应五类图纸（坏味道那题最终也落成一张类图），选错图纸等于答错题：",[128,306,307,320],{},[131,308,309],{},[134,310,311,314,317],{},[137,312,313],{},"题目问的是",[137,315,316],{},"该画的图",[137,318,319],{},"不该画的图",[144,321,322,333,344,355,365,376],{},[134,323,324,327,330],{},[149,325,326],{},"系统做什么、谁在用",[149,328,329],{},"用例图",[149,331,332],{},"类图（静态结构答不了「谁用」）",[134,334,335,338,341],{},[149,336,337],{},"一个用例的流程怎么走",[149,339,340],{},"活动图",[149,342,343],{},"顺序图（顺序图看不到分支和泳道）",[134,345,346,349,352],{},[149,347,348],{},"一次交互由哪些对象按什么顺序协作",[149,350,351],{},"顺序图",[149,353,354],{},"活动图（活动图没有对象职责）",[134,356,357,360,363],{},[149,358,359],{},"有哪些类、它们什么关系",[149,361,362],{},"类图",[149,364,340],{},[134,366,367,370,373],{},[149,368,369],{},"界面长什么样",[149,371,372],{},"界面草图 + 隐喻说明",[149,374,375],{},"UML 任何图",[134,377,378,381,384],{},[149,379,380],{},"这段代码哪里不对",[149,382,383],{},"坏味道说明 + 重构后的类图",[149,385,386],{},"顺序图（问题不在交互）",[13,388,389,390,393],{},"有一条容易忽略的规律：",[17,391,392],{},"同一份需求，这五类图是逐层细化的关系，不是五种并列的画法","。用例给出边界，活动图给出流程，实体来自流程，顺序图把流程摊到对象上，类图再从顺序图机械导出，最后界面把流程落到屏幕上。",[13,395,396],{},[397,398],"img",{"alt":399,"src":400},"从需求到图纸的推导链：用例图确定边界与角色，活动图展开流程与泳道，业务实体从流程中提取并挂回活动图，顺序图把流程摊到边界、控制、实体三类对象上，类图从顺序图机械导出，界面草图把流程映射到屏幕；箭头表示每一层的输入来自上一层","\u002Fimages\u002Fsw-design-notes-28-diagram-chain.svg",[13,402,403,404,407],{},"这条链在实操上有直接用处：",[17,405,406],{},"如果一张图卡住了，往往是因为上一层的产物没想清楚","。做不出顺序图，通常是 basic flow 没读透；抽不出实体，通常是活动图里的步骤写得太粗。",[22,409,411],{"id":410},"_3-用例图四个地方会扣分","3 用例图：四个地方会扣分",[81,413,415],{"id":414},"_31-符号与落笔顺序","3.1 符号与落笔顺序",[128,417,418,431],{},[131,419,420],{},[134,421,422,425,428],{},[137,423,424],{},"元素",[137,426,427],{},"搜索词",[137,429,430],{},"关键要求",[144,432,433,448,464,476],{},[134,434,435,438,442],{},[149,436,437],{},"参与者（actor）",[149,439,440],{},[30,441,118],{},[149,443,444,445],{},"火柴人，",[17,446,447],{},"一律在系统边界外",[134,449,450,453,458],{},[149,451,452],{},"用例（use case）",[149,454,455],{},[30,456,457],{},"use case",[149,459,460,461],{},"椭圆，名字用",[17,462,463],{},"动宾短语",[134,465,466,469,473],{},[149,467,468],{},"系统边界（system boundary）",[149,470,471],{},[30,472,121],{},[149,474,475],{},"矩形框，所有用例在框内",[134,477,478,481,484],{},[149,479,480],{},"关联（communication association）",[149,482,483],{},"直接连线",[149,485,486],{},"实线，多数情况不带箭头",[13,488,489],{},"落笔顺序（按这个顺序不会返工）：",[52,491,492,498,504,510],{},[55,493,494,497],{},[17,495,496],{},"先画边界框","，拉大一点（要装下 8–12 个椭圆）；",[55,499,500,503],{},[17,501,502],{},"再摆 actor","，全部放在框外左右两侧；",[55,505,506,509],{},[17,507,508],{},"然后放用例","，一列排或两列排，同类用例靠近；",[55,511,512,515],{},[17,513,514],{},"最后连线"," —— 先连主体角色，再连例外角色。",[13,517,518],{},"如果把连线留到最后，改布局时线会跟着乱；反过来先连线再挪形状，容易连错对象。",[10,520,521],{},[13,522,523,526,527,530],{},[17,524,525],{},"一个省力技巧","：画完第一个 actor 后按 ",[30,528,529],{},"Ctrl+D"," 复制，比重新搜快。复制出来的形状位置会偏一点，用方向键微调比拖更准。",[81,532,534],{"id":533},"_32-箭头方向什么时候才需要箭头","3.2 箭头方向：什么时候才需要箭头",[13,536,537],{},"这是用例图上最容易被忽略的细节。讲义的原话是：",[539,540,541,547],"ul",{},[55,542,543,546],{},[17,544,545],{},"箭头由 actor 指向用例"," —— 参与者主动触发，也就是用户点了什么；",[55,548,549,552],{},[17,550,551],{},"箭头由用例指向 actor"," —— 用例先启动，去唤醒参与者，通常是定时器或传感器触发的通知、邮件、告警。",[13,554,555,556,559],{},"所以大多数线其实",[17,557,558],{},"不需要箭头","（画实线即可）。只有当这条交互是「系统主动推送」时，才要把箭头画向 actor。一句提醒：如果一张用例图上每一根线都带箭头，那这张图基本可以确定画错了。",[13,561,562,563,566],{},"在贯穿案例里，「每日 9 点给当日有单的工程师发排期提醒」这一条，箭头就该由用例指向 ",[30,564,565],{},"Engineer","——是系统主动推的。",[81,568,570],{"id":569},"_33-三种精炼关系的方向","3.3 三种精炼关系的方向",[13,572,573],{},"这是全卷最集中的扣分点，一定要记成条件反射：",[128,575,576,592],{},[131,577,578],{},[134,579,580,583,586,589],{},[137,581,582],{},"关系",[137,584,585],{},"箭头方向",[137,587,588],{},"线上的标注",[137,590,591],{},"条件写法",[144,593,594,612,633],{},[134,595,596,599,604,609],{},[149,597,598],{},"include",[149,600,601],{},[17,602,603],{},"基用例 → 被包含用例",[149,605,606],{},[30,607,608],{},"«include»",[149,610,611],{},"无条件（每次必执行）",[134,613,614,617,622,627],{},[149,615,616],{},"extend",[149,618,619],{},[17,620,621],{},"扩展用例 → 基用例",[149,623,624],{},[30,625,626],{},"«extend»",[149,628,629,630],{},"条件写在箭头旁，",[17,631,632],{},"不加方括号",[134,634,635,638,644,647],{},[149,636,637],{},"泛化（用例\u002Factor）",[149,639,640,643],{},[17,641,642],{},"子 → 父","，空心三角",[149,645,646],{},"无",[149,648,646],{},[13,650,651],{},"三个判断要点：",[52,653,654,660,671],{},[55,655,656,659],{},[17,657,658],{},"include 和 extend 的箭头方向是相反的","，这是唯一的记忆锚点。记法：include 是「我需要它」（箭头朝被需要的一方），extend 是「我附加到它」（箭头朝被附加的一方）；",[55,661,662,663,666,667,670],{},"线是实线还是虚线",[17,664,665],{},"都可以","，讲义明确说两种都行 —— 所以不要在这上面纠结，",[17,668,669],{},"方向才是分","；",[55,672,673,674,676],{},"extend 的条件",[17,675,632],{},"（那是活动图 guard 的写法）。",[10,678,679],{},[13,680,681,686,687,689,690,693,694,697,698,701,702,704],{},[17,682,683,685],{},[30,684,608],{}," 标签怎么加","：画好连线后双击线的中间位置，打 ",[30,688,608],{},"。尖括号可以直接打中文输入法的 ",[30,691,692],{},"«"," ",[30,695,696],{},"»","，或者用 ",[30,699,700],{},"\u003C\u003Cinclude>>","（两个小于号），draw.io 都识别。\n如果打出来显示成方块，说明字体缺字，换 ",[30,703,700],{}," 写法即可。",[81,706,708],{"id":707},"_34-参与者的合并与拆分","3.4 参与者的合并与拆分",[13,710,711],{},"讲义给了两条方向相反的判断：",[539,713,714,721],{},[55,715,716,717,720],{},"用同一套用例、只是",[17,718,719],{},"权限或待遇不同","的 → 合并成一个 actor，差异写成业务规则（放在活动图里）；",[55,722,723,726],{},[17,724,725],{},"访问的用例集不同"," → 拆成两个 actor（或做泛化）。",[13,728,729],{},"案例里如果出现「普通客户」和「延保客户」这类区分，先别急着建两个 actor：问一句「他们做的事一样吗」。一样就合并。",[81,731,733],{"id":732},"_35-一个用例连两个火柴人合规但有前提","3.5 一个用例连两个火柴人：合规，但有前提",[13,735,736,739,740,743,744,747],{},[17,737,738],{},"同一个椭圆上连两条线到两个不同的 actor，是标准画法","，它表示这两个角色",[17,741,742],{},"触发并执行这个用例的方式完全一致","（讲义原话 ",[30,745,746],{},"both will trigger and execute the use case in the same way","）。",[13,749,750],{},"它不是「两个角色都会用到这个功能」—— 这两件事差很远。讲义接着给了反向判断：",[10,752,753],{},[13,754,755,756],{},"create a separate use case for each of the actors ",[17,757,758],{},"if they are not using the use case identically",[128,760,761,771],{},[131,762,763],{},[134,764,765,768],{},[137,766,767],{},"情况",[137,769,770],{},"怎么画",[144,772,773,787,800],{},[134,774,775,782],{},[149,776,777,778,781],{},"两人",[17,779,780],{},"用法一致","（同一界面、同一套步骤）",[149,783,784],{},[17,785,786],{},"一个用例连两根线",[134,788,789,794],{},[149,790,777,791],{},[17,792,793],{},"用法不同",[149,795,796,799],{},[17,797,798],{},"拆成两个用例","，哪怕名字听起来像",[134,801,802,809],{},[149,803,804,805,808],{},"共用的是",[17,806,807],{},"一整批","用例、只是权限不同",[149,810,811,814],{},[17,812,813],{},"参与者泛化","（空心三角子→父）",[13,816,817,818],{},"判据一句话：",[17,819,820],{},"这两个角色点进去之后，看到的是同一个界面、走的是同一套步骤吗？",[13,822,823],{},"本例的对照：「客服」与「片区经理」看待派单的方式一样 → 可以连同一个用例；「客服派单」与「工程师接单」一个发起一个响应 → 必须拆成两个。",[10,825,826],{},[13,827,828,831,832,835,836,839],{},[17,829,830],{},"画这一笔","：从第二个 actor 直接拖一条",[17,833,834],{},"实线","到这个已有椭圆即可。",[17,837,838],{},"不要加箭头"," —— 关联线表示 actor 主动触发；带箭头只在「系统主动推送」时才用。",[22,841,843],{"id":842},"_4-活动图符号-泳道","4 活动图：符号 + 泳道",[81,845,847],{"id":846},"_41-七个符号","4.1 七个符号",[128,849,850,861],{},[131,851,852],{},[134,853,854,856,858],{},[137,855,424],{},[137,857,427],{},[137,859,860],{},"说明",[144,862,863,879,892,905,915,931,944],{},[134,864,865,868,873],{},[149,866,867],{},"开始状态（start state）",[149,869,870],{},[30,871,872],{},"start",[149,874,875,876],{},"实心黑圆，",[17,877,878],{},"只能有一个",[134,880,881,884,889],{},[149,882,883],{},"结束状态（final state）",[149,885,886],{},[30,887,888],{},"end",[149,890,891],{},"黑圆外套一个白圆，可以有多个",[134,893,894,897,902],{},[149,895,896],{},"动作（activity）",[149,898,899],{},[30,900,901],{},"rounded rectangle",[149,903,904],{},"两端圆角的矩形，名字是动词短语",[134,906,907,910,912],{},[149,908,909],{},"转移（transition）",[149,911,483],{},[149,913,914],{},"开放箭头的实线",[134,916,917,920,925],{},[149,918,919],{},"判断（decision）",[149,921,922],{},[30,923,924],{},"decision",[149,926,927,928],{},"菱形，分支处标 ",[30,929,930],{},"[guard]",[134,932,933,936,941],{},[149,934,935],{},"同步条（synchronization bar）",[149,937,938],{},[30,939,940],{},"horizontal bar",[149,942,943],{},"粗黑横线，表示并行分叉或汇合",[134,945,946,949,955],{},[149,947,948],{},"泳道（swimlane）",[149,950,951,954],{},[30,952,953],{},"lane"," 或手画矩形",[149,956,957],{},"竖直分区，顶部写角色",[13,959,960,961,964,965,693,968,971,972,975],{},"两个常被忘的细节：",[17,962,963],{},"判断的 guard 要写在方括号里","（",[30,966,967],{},"[yes]",[30,969,970],{},"[no]","），以及",[17,973,974],{},"一个菱形可以有三条以上分支","（讲义特意提了这一点，因为很多人以为只能二分）。",[13,977,978,979,982],{},"另外，讲义明确要求：",[17,980,981],{},"这一阶段忽略异常","。不要画「是否输入有误」「是否重复提交」这类校验分支，也不要画「操作成功」的确认框 —— 只保留业务决策。",[10,984,985],{},[13,986,987,990],{},[17,988,989],{},"guard 打在线上，不是文本框","：双击连线的中间位置直接打字，得到的是「线的标签」，会跟着线走。如果用文本框单独摆，线一挪就跟标签分离了。",[81,992,994],{"id":993},"_42-泳道drawio-里最别扭的一个","4.2 泳道：draw.io 里最别扭的一个",[13,996,997,998,1001],{},"泳道在 draw.io 里",[17,999,1000],{},"不会自动吸附","。两条路都可以走，各有代价：",[128,1003,1004,1017],{},[131,1005,1006],{},[134,1007,1008,1011,1014],{},[137,1009,1010],{},"做法",[137,1012,1013],{},"优点",[137,1015,1016],{},"缺点",[144,1018,1019,1033],{},[134,1020,1021,1027,1030],{},[149,1022,1023,1024,1026],{},"用 ",[30,1025,953],{},"（Pool \u002F Lane 形状）",[149,1028,1029],{},"顶部有标题带，看起来正规",[149,1031,1032],{},"拖活动进去时容易变成「泳道的子元素」，整体挪动会连坐",[134,1034,1035,1038,1041],{},[149,1036,1037],{},"手画矩形 + 竖分隔线",[149,1039,1040],{},"完全自由，活动怎么摆都行",[149,1042,1043],{},"移动时框不会跟着走，得手动调整",[13,1045,1046,1049],{},[17,1047,1048],{},"推荐手画矩形","，理由很实际：考场上你要频繁改布局，泳道框如果吸附了活动，每次挪动都要重新解绑，反而更慢。",[13,1051,1052,1053,1056],{},"手画顺序也有讲究 —— ",[17,1054,1055],{},"先排活动，最后画泳道框","。因为活动位置定下来之后，泳道框只需要照着边界拉一次；反过来先画框，框一改就要重排活动。",[81,1058,1060],{"id":1059},"_43-含实体时的那一支箭头","4.3 含实体时的那一支箭头",[13,1062,1063],{},"题目写「include entities」时，多半是 8 分题，其中相当一部分分在实体上。做法是：",[52,1065,1066,1069,1080],{},[55,1067,1068],{},"在图的右侧（或每条泳道内）画实体符号（矩形\u002F类符号），写上实体名；",[55,1070,1071,1072,1075,1076,1079],{},"从",[17,1073,1074],{},"动作","连线到",[17,1077,1078],{},"实体","，标出这次操作用到了哪个实体；",[55,1081,1082,1085,1086],{},[17,1083,1084],{},"方向取决于读还是写","：\n",[539,1087,1088,1097],{},[55,1089,1090,1093,1094,670],{},[17,1091,1092],{},"读","（查档案、取余额）→ 箭头",[17,1095,1096],{},"由实体指向动作",[55,1098,1099,1102,1103,40],{},[17,1100,1101],{},"写","（更新状态、新增记录）→ 箭头",[17,1104,1105],{},"由动作指向实体",[13,1107,1108,1109,1111,1112,1115,1116,1119],{},"这一笔在 workshop 批改里被反复标成 ",[30,1110,39],{}," \u002F ",[30,1113,1114],{},"Should be read","。有个简单记法：",[17,1117,1118],{},"数据流向动作 = 读，动作流向数据 = 写","。如果实在分不清，在图旁边加一行文字注释说明「此步读取 WorkOrder」—— 至少不会因为符号歧义白丢分。",[81,1121,1123],{"id":1122},"_44-自查这张图","4.4 自查这张图",[539,1125,1128,1138,1144,1150,1156],{"className":1126},[1127],"contains-task-list",[55,1129,1132,1137],{"className":1130},[1131],"task-list-item",[1133,1134],"input",{"disabled":1135,"type":1136},true,"checkbox"," 只有一个开始状态？",[55,1139,1141,1143],{"className":1140},[1131],[1133,1142],{"disabled":1135,"type":1136}," 每个判断都有方括号条件？",[55,1145,1147,1149],{"className":1146},[1131],[1133,1148],{"disabled":1135,"type":1136}," 判断的每条出口都能走到结束状态（没有悬空分支）？",[55,1151,1153,1155],{"className":1152},[1131],[1133,1154],{"disabled":1135,"type":1136}," 泳道数量和角色数量对得上？",[55,1157,1159,1161],{"className":1158},[1131],[1133,1160],{"disabled":1135,"type":1136}," 实体画了，读\u002F写箭头方向正确？",[22,1163,1165],{"id":1164},"_5-顺序图把-basic-flow-一行一行摊开","5 顺序图：把 basic flow 一行一行摊开",[81,1167,1169],{"id":1168},"_51-四个元素","5.1 四个元素",[128,1171,1172,1181],{},[131,1173,1174],{},[134,1175,1176,1178],{},[137,1177,424],{},[137,1179,1180],{},"搜索词 \u002F 操作",[144,1182,1183,1198,1206,1214],{},[134,1184,1185,1188],{},[149,1186,1187],{},"对象\u002F生命线（lifeline）",[149,1189,1190,1191,1194,1195],{},"搜 ",[30,1192,1193],{},"sequence"," 拖出预置组，或手画：矩形 + 竖虚线，写法 ",[30,1196,1197],{},":ClassName",[134,1199,1200,1203],{},[149,1201,1202],{},"消息（message）",[149,1204,1205],{},"连线的实心箭头，标消息名与参数",[134,1207,1208,1211],{},[149,1209,1210],{},"返回（return）",[149,1212,1213],{},"虚线 + 开放箭头（讲义说「返回可以假定、不画也行」，但画了更清楚）",[134,1215,1216,1219],{},[149,1217,1218],{},"激活条（activation bar）",[149,1220,1221],{},"生命线上的细长矩形，表示这段在处理",[13,1223,1224,1225,964,1228,693,1231,1234],{},"纵向就是时间，从上往下读。",[17,1226,1227],{},"消息编号",[30,1229,1230],{},"1:",[30,1232,1233],{},"2:"," …）是可选的，但强烈建议画 —— 它让「我覆盖了 basic flow 的每一步」这件事一眼可见。",[10,1236,1237],{},[13,1238,1239,1242,1243,1245,1246,1249,1250,1252,1253,1256,1257,1260],{},[17,1240,1241],{},"返回线怎么变虚线","：选中消息线 → 格式面板 ",[30,1244,197],{}," → 勾 ",[30,1247,1248],{},"dashed","。或者 ",[30,1251,287],{}," 打 ",[30,1254,1255],{},"dashed=1;endArrow=open;","。\n",[17,1258,1259],{},"激活条如果没自动出现","：预置的 sequence 形状拖出来时自带，手画的生命线没有。直接拉一个细矩形叠在虚线上就行，不用找专用形状。",[81,1262,1264],{"id":1263},"_52-生命线怎么摆","5.2 生命线怎么摆",[13,1266,1267],{},"分析模型的顺序图里，生命线的顺序基本是固定的：",[89,1269,1272],{"className":1270,"code":1271,"language":94},[92],": Actor  |  :Boundary（界面）  |  :Control（控制器）  |  :Entity…  |  :ExternalSystem\n",[30,1273,1271],{"__ignoreMap":97},[13,1275,1276],{},"按这个顺序摆，消息箭头大部分从左指向右，交叉线最少。三类分析对象各自的职责不能串（笔记 22）：",[539,1278,1279,1288,1294],{},[55,1280,1281,1284,1285,670],{},[17,1282,1283],{},"边界对象（boundary）"," 只负责与外部交互：收输入、显示结果、对接外部系统。",[17,1286,1287],{},"不做业务判断",[55,1289,1290,1293],{},[17,1291,1292],{},"控制对象（control）"," 负责协调流程：收到请求，决定交给谁，汇总结果；",[55,1295,1296,1299],{},[17,1297,1298],{},"实体对象（entity）"," 承载数据与规则，通常对应到数据表。",[13,1301,1302,1303,1306,1307,1310],{},"一个很具体的判分点：",[17,1304,1305],{},"「系统显示列表」这类步骤是两件事"," —— entity 返回数据（虚线返回），boundary 负责显示（发给边界对象或标 ",[30,1308,1309],{},"display()","）。把显示画成 control 自己完成，是职责错位的典型。",[81,1312,1314],{"id":1313},"_53-外部系统是边界对象不是实体","5.3 外部系统是边界对象，不是实体",[13,1316,1317,1318,1321,1322],{},"basic flow 里出现「系统把资料送给 Payment Gateway \u002F 供应商库存系统」时，接收方要画成",[17,1319,1320],{},"边界对象","，不是实体。讲义给的判断很直接：",[17,1323,1324],{},"你需要写代码去和它对接，那它是系统外部接口。",[81,1326,1328],{"id":1327},"_54-自查这张图","5.4 自查这张图",[539,1330,1332,1338,1344,1350,1356],{"className":1331},[1127],[55,1333,1335,1337],{"className":1334},[1131],[1133,1336],{"disabled":1135,"type":1136}," basic flow 的每个编号都至少对应一条消息？",[55,1339,1341,1343],{"className":1340},[1131],[1133,1342],{"disabled":1135,"type":1136}," 每个参与对象都有生命线头？",[55,1345,1347,1349],{"className":1346},[1131],[1133,1348],{"disabled":1135,"type":1136}," 四条生命线的顺序是 Actor → Boundary → Control → Entity？",[55,1351,1353,1355],{"className":1352},[1131],[1133,1354],{"disabled":1135,"type":1136}," 返回用虚线？消息用实线？",[55,1357,1359,1361],{"className":1358},[1131],[1133,1360],{"disabled":1135,"type":1136}," 「显示」这一步是由 boundary 做的，不是 control 自己完成？",[22,1363,1365],{"id":1364},"_6-类图三格五种符号一个方向","6 类图：三格、五种符号、一个方向",[81,1367,1369],{"id":1368},"_61-类符号与可见性","6.1 类符号与可见性",[128,1371,1372,1381],{},[131,1373,1374],{},[134,1375,1376,1378],{},[137,1377,424],{},[137,1379,1380],{},"写法",[144,1382,1383,1391,1405,1417],{},[134,1384,1385,1388],{},[149,1386,1387],{},"三格",[149,1389,1390],{},"类名 \u002F 属性 \u002F 操作，从上到下",[134,1392,1393,1396],{},[149,1394,1395],{},"属性",[149,1397,1398,1401,1402],{},[30,1399,1400],{},"visibility name : type [= init]","，如 ",[30,1403,1404],{},"-name : String",[134,1406,1407,1409],{},[149,1408,214],{},[149,1410,1411,1401,1414],{},[30,1412,1413],{},"visibility name(param : type) : type",[30,1415,1416],{},"+getId() : String",[134,1418,1419,1422],{},[149,1420,1421],{},"可见性",[149,1423,1424,1427,1428,1431,1432,1434],{},[30,1425,1426],{},"-"," private、",[30,1429,1430],{},"#"," protected、",[30,1433,201],{}," public",[13,1436,1437,1438,1441,1442,1445],{},"题目如果写「not required to define the attributes or methods」，就",[17,1439,1440],{},"只画类名 + 关系","，把时间省下来检查箭头。属性只对",[17,1443,1444],{},"实体类","定义（讲义明确说 boundary 与 control 不列属性）。",[10,1447,1448],{},[13,1449,1450,1453,1454,1457,1458,1461,1462,1111,1465,1111,1467,40],{},[17,1451,1452],{},"三格的横线不用画","：搜 ",[30,1455,1456],{},"class"," 拖进去就是三格，横线自动生成。双击任意一格打字。\n想把某一格留空？直接留空，别删线。\n加构造型：双击类名上方，会出现一行 ",[30,1459,1460],{},"«»","，填 ",[30,1463,1464],{},"entity",[30,1466,121],{},[30,1468,1469],{},"control",[81,1471,1473],{"id":1472},"_62-五种关系的符号","6.2 五种关系的符号",[128,1475,1476,1488],{},[131,1477,1478],{},[134,1479,1480,1482,1485],{},[137,1481,582],{},[137,1483,1484],{},"符号",[137,1486,1487],{},"落到 Java",[144,1489,1490,1501,1512,1527,1540],{},[134,1491,1492,1495,1498],{},[149,1493,1494],{},"dependency 依赖",[149,1496,1497],{},"虚线 + 开放箭头",[149,1499,1500],{},"方法参数、局部变量、返回值",[134,1502,1503,1506,1509],{},[149,1504,1505],{},"association 关联",[149,1507,1508],{},"实线（可带重数）",[149,1510,1511],{},"字段持有引用",[134,1513,1514,1517,1524],{},[149,1515,1516],{},"aggregation 聚合",[149,1518,1519,1520,1523],{},"空心菱形（菱形在",[17,1521,1522],{},"整体","一侧）",[149,1525,1526],{},"集合字段，元素由外部传入",[134,1528,1529,1532,1537],{},[149,1530,1531],{},"composition 组合",[149,1533,1534,1535,1523],{},"实心菱形（菱形在",[17,1536,1522],{},[149,1538,1539],{},"集合字段，元素在内部创建与管理",[134,1541,1542,1545,1551],{},[149,1543,1544],{},"inheritance 继承",[149,1546,1547,1548],{},"实线 + 空心三角，",[17,1549,1550],{},"指向父类",[149,1552,1553],{},[30,1554,1555],{},"extends",[13,1557,1558],{},"三个必查的地方：",[52,1560,1561,1567,1573],{},[55,1562,1563,1566],{},[17,1564,1565],{},"菱形画在「整体」那一端","，不是部分那一端；",[55,1568,1569,1572],{},[17,1570,1571],{},"空心三角指向父类","，不是指向子类（这个每年都有人画反）；",[55,1574,1575,1576,1579,1580,40],{},"依赖用",[17,1577,1578],{},"虚线","，关联用",[17,1581,834],{},[81,1583,1585],{"id":1584},"_63-重数写法","6.3 重数写法",[128,1587,1588,1597],{},[131,1589,1590],{},[134,1591,1592,1594],{},[137,1593,1380],{},[137,1595,1596],{},"含义",[144,1598,1599,1609,1619,1632,1642,1652],{},[134,1600,1601,1606],{},[149,1602,1603],{},[30,1604,1605],{},"1",[149,1607,1608],{},"恰好一个",[134,1610,1611,1616],{},[149,1612,1613],{},[30,1614,1615],{},"0..1",[149,1617,1618],{},"零或一个",[134,1620,1621,1629],{},[149,1622,1623,228,1626],{},[30,1624,1625],{},"*",[30,1627,1628],{},"0..*",[149,1630,1631],{},"零或多个",[134,1633,1634,1639],{},[149,1635,1636],{},[30,1637,1638],{},"1..*",[149,1640,1641],{},"一个或多个",[134,1643,1644,1649],{},[149,1645,1646],{},[30,1647,1648],{},"4..6",[149,1650,1651],{},"4 到 6",[134,1653,1654,1659],{},[149,1655,1656],{},[30,1657,1658],{},"2, 6..8",[149,1660,1661],{},"2，或 6 到 8",[13,1663,1664,1665,1668],{},"重数标在线的",[17,1666,1667],{},"端点附近","（靠目标类那一头）。draw.io 里双击线的端点位置打字即可。",[81,1670,1672],{"id":1671},"_64-分析模型里的关系限制","6.4 分析模型里的关系限制",[13,1674,1675],{},"这一张表是从讲义里直接抄下来的，属于「画了就扣分」的类型：",[128,1677,1678,1688],{},[131,1679,1680],{},[134,1681,1682,1685],{},[137,1683,1684],{},"想画的关系",[137,1686,1687],{},"允许吗",[144,1689,1690,1697,1705,1713,1721],{},[134,1691,1692,1695],{},[149,1693,1694],{},"同一构造型之间：关联 \u002F 依赖 \u002F 继承 \u002F 聚合 \u002F 组合",[149,1696,665],{},[134,1698,1699,1702],{},[149,1700,1701],{},"不同构造型之间做继承",[149,1703,1704],{},"无意义",[134,1706,1707,1710],{},[149,1708,1709],{},"不同构造型之间做聚合 \u002F 组合",[149,1711,1712],{},"一般无意义",[134,1714,1715,1718],{},[149,1716,1717],{},"boundary 直接关联 entity",[149,1719,1720],{},"不推荐（中间应隔着 control）",[134,1722,1723,1726],{},[149,1724,1725],{},"actor 与 entity \u002F control 直接关联",[149,1727,1728],{},"不推荐（actor 只接触 boundary）",[81,1730,1732],{"id":1731},"_65-自查这张图","6.5 自查这张图",[539,1734,1736,1742,1748,1754,1760],{"className":1735},[1127],[55,1737,1739,1741],{"className":1738},[1131],[1133,1740],{"disabled":1135,"type":1136}," 菱形在整体那一端？",[55,1743,1745,1747],{"className":1744},[1131],[1133,1746],{"disabled":1135,"type":1136}," 空心三角指向父类？",[55,1749,1751,1753],{"className":1750},[1131],[1133,1752],{"disabled":1135,"type":1136}," 依赖是虚线、关联是实线？",[55,1755,1757,1759],{"className":1756},[1131],[1133,1758],{"disabled":1135,"type":1136}," 属性只出现在实体类上？",[55,1761,1763,1765,1766,33,1769,1772],{"className":1762},[1131],[1133,1764],{"disabled":1135,"type":1136}," 类名是业务术语，没有 ",[30,1767,1768],{},"Table",[30,1770,1771],{},"DTO"," 这类技术后缀？",[22,1774,1776],{"id":1775},"_7-界面草图4-分的题只要-3-样东西","7 界面草图：4 分的题只要 3 样东西",[13,1778,1779],{},"界面草图不考画功，考的是「信息选对了没有」。三个必查项：",[52,1781,1782,1788,1798],{},[55,1783,1784,1787],{},[17,1785,1786],{},"题目提到的每个角色，都能在图上找到他要的信息","。题目说「让客服、工程师和仓管都能排期」，那至少要出现：工单列表、时段可用性、待办请求、配件库存；",[55,1789,1790,1793,1794,1797],{},[17,1791,1792],{},"隐喻明确标出","。日历（排期）、看板列（状态流转）、红黄绿灯（紧急度）、地图（上门路线）都是可以用的隐喻。",[17,1795,1796],{},"在图旁写一句「以周历隐喻呈现工程师可用时段」","，否则阅卷人不知道那是隐喻还是随手画的格子；",[55,1799,1800,1803],{},[17,1801,1802],{},"一屏只有一个主结构","。把三种隐喻堆在一起，既讲不清也扣分。",[13,1805,1806,1807,1810,1811,1814],{},"再加两个加分动作：给区块加",[17,1808,1809],{},"标题","（让主次一眼可辨），在图下写 ",[17,1812,1813],{},"3 行说明","，逐条对上题目要求。",[10,1816,1817],{},[13,1818,1819,1822,1823,1826,1827,1829,1830,1833,1834,33,1837,33,1840,33,1842,1845],{},[17,1820,1821],{},"用哪套形状","：draw.io 搜 ",[30,1824,1825],{},"wireframe","，或 ",[30,1828,106],{}," 里勾选 ",[17,1831,1832],{},"Mockup \u002F Wireframe","。里面的 ",[30,1835,1836],{},"Button",[30,1838,1839],{},"Input",[30,1841,1768],{},[30,1843,1844],{},"Window"," 是够用的。\n但 4 分题不建议花时间美化 —— 用普通矩形 + 文字，十分钟内画完，得分差别不大。",[22,1847,1849],{"id":1848},"_8-一张速查表最容易画反的几笔","8 一张速查表：最容易画反的几笔",[13,1851,1852],{},"把上面所有「方向性」的规则抽出来，就是下面这张图。它按三张图分成三列，红字全是「画反就失分」的地方：",[13,1854,1855],{},[397,1856],{"alt":1857,"src":1858},"考场符号速查：左列是用例图的参与者、用例、系统边界与 include、extend、泛化三种关系的箭头方向；中列是活动图的开始与结束状态、动作、判断菱形、同步条，以及读实体和写实体两种相反的箭头；右列是类图的依赖、关联、聚合、组合、继承五种符号，并标出菱形贴在整体一端、空心三角指向父类","\u002Fimages\u002Fsw-design-notes-28-notation-sheet.svg",[13,1860,1861],{},"如果只想要文字版，就是下面十二行 —— 考前一晚过一遍就够：",[128,1863,1864,1879],{},[131,1865,1866],{},[134,1867,1868,1870,1873,1876],{},[137,1869,1430],{},[137,1871,1872],{},"画什么",[137,1874,1875],{},"正确方向",[137,1877,1878],{},"画反的后果",[144,1880,1881,1895,1909,1922,1939,1957,1972,1989,2003,2017,2033,2050],{},[134,1882,1883,1885,1890,1892],{},[149,1884,1605],{},[149,1886,1887,1889],{},[30,1888,608],{}," 箭头",[149,1891,603],{},[149,1893,1894],{},"语义变成「被包含用例依赖基用例」，判错",[134,1896,1897,1900,1904,1906],{},[149,1898,1899],{},"2",[149,1901,1902,1889],{},[30,1903,626],{},[149,1905,621],{},[149,1907,1908],{},"与 include 混淆，整题失分",[134,1910,1911,1914,1917,1919],{},[149,1912,1913],{},"3",[149,1915,1916],{},"泛化空心三角",[149,1918,642],{},[149,1920,1921],{},"继承方向反了，类图整题失分",[134,1923,1924,1927,1930,1936],{},[149,1925,1926],{},"4",[149,1928,1929],{},"聚合 \u002F 组合菱形",[149,1931,1932,1933,1935],{},"菱形贴着",[17,1934,1522],{},"那一端",[149,1937,1938],{},"整体部分关系反了",[134,1940,1941,1944,1947,1954],{},[149,1942,1943],{},"5",[149,1945,1946],{},"活动图 guard",[149,1948,1949,1950,1953],{},"写在",[17,1951,1952],{},"方括号","里",[149,1955,1956],{},"写成 extend 的裸条件，符号不规范",[134,1958,1959,1962,1964,1969],{},[149,1960,1961],{},"6",[149,1963,673],{},[149,1965,1966,1952],{},[17,1967,1968],{},"不加",[149,1970,1971],{},"与活动图 guard 混用",[134,1973,1974,1977,1980,1983],{},[149,1975,1976],{},"7",[149,1978,1979],{},"活动图读实体",[149,1981,1982],{},"实体 → 动作",[149,1984,1985,1986],{},"被批 ",[30,1987,1988],{},"wrong access \u002F should be read",[134,1990,1991,1994,1997,2000],{},[149,1992,1993],{},"8",[149,1995,1996],{},"活动图写实体",[149,1998,1999],{},"动作 → 实体",[149,2001,2002],{},"同上",[134,2004,2005,2008,2011,2014],{},[149,2006,2007],{},"9",[149,2009,2010],{},"用例图箭头",[149,2012,2013],{},"只在「系统主动推送」时才画向 actor",[149,2015,2016],{},"满图箭头，说明没理解触发方向",[134,2018,2019,2022,2025,2030],{},[149,2020,2021],{},"10",[149,2023,2024],{},"顺序图返回",[149,2026,2027,2029],{},[17,2028,1578],{}," + 开放箭头",[149,2031,2032],{},"用实线会被当成新消息",[134,2034,2035,2038,2041,2047],{},[149,2036,2037],{},"11",[149,2039,2040],{},"actor 与用例的线",[149,2042,2043,2044],{},"实线，actor 在边界",[17,2045,2046],{},"外",[149,2048,2049],{},"画进框内，边界失效",[134,2051,2052,2055,2058,2062],{},[149,2053,2054],{},"12",[149,2056,2057],{},"依赖关系",[149,2059,2060],{},[17,2061,1578],{},[149,2063,2064],{},"用实线会被读成关联",[22,2066,2068],{"id":2067},"_9-工具与交付别在最后十分钟翻车","9 工具与交付：别在最后十分钟翻车",[13,2070,2071],{},"讲义那句「know how to draw all the UML diagrams using online tool」是硬要求，因为答卷是电子稿。所以考前必须练熟三件事：",[52,2073,2074,2085,2091],{},[55,2075,2076,2079,2080,1111,2082,2084],{},[17,2077,2078],{},"找到每个符号在哪","。特别是 ",[30,2081,608],{},[30,2083,626],{}," 的标注、空心菱形、实心菱形、空心三角 —— 这几个在多数工具里都藏在二级菜单（或者像这篇 §1.3 说的，要改端点样式）；",[55,2086,2087,2090],{},[17,2088,2089],{},"改图要快","。需求阶段改图是常态，工具里改一次要重画的话，考场上就会开始少改；",[55,2092,2093,2096,2097,2100,2101,2104],{},[17,2094,2095],{},"导出清晰","。知道怎么导出 PNG（",[30,2098,2099],{},"File → Export as → PNG","，把 ",[30,2102,2103],{},"Zoom"," 调到 200% 以上），而不是截图。",[13,2106,2107,2108,964,2111,2114,2115,2118],{},"图纸命名与呈现还有两条小事：",[17,2109,2110],{},"每张图都要有标题",[30,2112,2113],{},"Figure 2: Activity Diagram – Process Home Repair","），并且",[17,2116,2117],{},"标明对应哪一小问","。阅卷人找图的时间越短，越可能给到你应得的分。",[22,2120,2121],{"id":2121},"本节自测",[52,2123,2124,2127,2130,2137,2140,2143,2146,2149],{},[55,2125,2126],{},"用例图里，什么时候才需要把箭头画向 actor？大多数线为什么不带箭头？",[55,2128,2129],{},"include 和 extend 的箭头方向分别指向哪一方？extend 的条件写法与活动图的 guard 差在哪？",[55,2131,2132,2133,2136],{},"活动图里「读实体」和「写实体」的箭头有什么区别？为什么 workshop 会批 ",[30,2134,2135],{},"wrong access","？",[55,2138,2139],{},"顺序图里「系统显示列表」这一步应该由几个对象完成？分别做什么？",[55,2141,2142],{},"聚合和组合的菱形画在哪一端？空心三角指向父类还是子类？",[55,2144,2145],{},"分析模型里，为什么 boundary 直接关联 entity 是「不推荐」的？",[55,2147,2148],{},"聚合、组合、继承这三种符号在 draw.io 的形状库里搜不到，该怎么画出来？",[55,2150,2151],{},"画活动图时，为什么建议「最后再画泳道框」？",[81,2153,2154],{"id":2154},"参考答案",[52,2156,2157,2164,2183,2197,2203,2214,2217,2245],{},[55,2158,2159,2160,2163],{},"只有当",[17,2161,2162],{},"用例先启动、去唤醒 actor"," 时才画箭头向 actor（定时器\u002F传感器触发的通知、邮件、告警）。因为绝大多数交互是 actor 主动触发的，画实线就够；满图箭头反而说明没理解触发方向（§3.2）。",[55,2165,2166,2168,2169,2171,2172,2175,2176,2178,2179,2182],{},[17,2167,598],{},"：基用例 → 被包含用例；",[17,2170,616],{},"：扩展用例 → 基用例 —— ",[17,2173,2174],{},"两者相反","。extend 的条件写在箭头旁、",[17,2177,632],{},"；活动图的 guard ",[17,2180,2181],{},"必须","写方括号（§3.3 \u002F §4.1）。",[55,2184,2185,2187,2188,2190,2191,228,2193,2196],{},[17,2186,1092],{},"：箭头由实体指向动作；",[17,2189,1101],{},"：箭头由动作指向实体。判分依据是数据流向 —— 数据流向动作=读，动作流向数据=写。画反会被批 ",[30,2192,2135],{},[30,2194,2195],{},"should be read","（§4.3）。",[55,2198,2199,2202],{},[17,2200,2201],{},"两个对象","：entity 返回数据（虚线返回箭头），boundary 负责把数据显示出来。画成 control 自己完成就是职责错位（§5.2）。",[55,2204,2205,2206,2209,2210,2213],{},"菱形",[17,2207,2208],{},"永远贴着整体那一端","（不是部分那一端）；空心三角",[17,2211,2212],{},"必须指向父类","（不是子类）。这两笔是最常画反的（§6.2）。",[55,2215,2216],{},"因为 actor 只应接触 boundary，boundary 又不应做业务判断 —— 中间必须隔着 control 来协调。直连会把「谁能访问数据」这件事画乱（§6.4）。",[55,2218,2219,2220,2223,2224,2226,2227,1111,2229,2231,2232,228,2235,2237,2238,2240,2241,2244],{},"它们不是独立形状，而是",[17,2221,2222],{},"连线的端点样式","：选中线 → 格式面板 ",[30,2225,197],{}," → 选 ",[30,2228,245],{},[30,2230,227],{}," → 设 ",[30,2233,2234],{},"filled=0",[30,2236,1605],{},"。也可以 ",[30,2239,287],{}," 直接写 ",[30,2242,2243],{},"endArrow=diamond;endFill=0;","（§1.3）。",[55,2246,2247,2248,2250],{},"因为 draw.io 的泳道",[17,2249,1000],{},"活动框，先画框的话，一旦调整框的大小或位置，里面的活动就要重排。先排好活动、再照边界拉一次泳道框，返工最少（§4.2）。",[22,2252,2253],{"id":2253},"术语表",[128,2255,2256,2269],{},[131,2257,2258],{},[134,2259,2260,2263,2266],{},[137,2261,2262],{},"术语",[137,2264,2265],{},"中文",[137,2267,2268],{},"一句话解释",[144,2270,2271,2282,2293,2304,2315,2326,2337,2348,2359,2370,2381,2392,2402,2413,2424,2435,2446,2462,2473,2484,2495,2506,2517,2528,2538,2549],{},[134,2272,2273,2276,2279],{},[149,2274,2275],{},"notation",[149,2277,2278],{},"符号体系",[149,2280,2281],{},"UML 规定的图形元素写法",[134,2283,2284,2287,2290],{},[149,2285,2286],{},"system boundary",[149,2288,2289],{},"系统边界",[149,2291,2292],{},"用例图上框住所有用例的矩形，actor 在框外",[134,2294,2295,2298,2301],{},[149,2296,2297],{},"communication association",[149,2299,2300],{},"通信关联",[149,2302,2303],{},"actor 与用例之间的实线",[134,2305,2306,2309,2312],{},[149,2307,2308],{},"include relationship",[149,2310,2311],{},"包含关系",[149,2313,2314],{},"每次必执行的公共步骤，箭头由基用例指向被包含用例",[134,2316,2317,2320,2323],{},[149,2318,2319],{},"extend relationship",[149,2321,2322],{},"扩展关系",[149,2324,2325],{},"条件发生时才叠加的行为，箭头由扩展用例指向基用例",[134,2327,2328,2331,2334],{},[149,2329,2330],{},"generalization",[149,2332,2333],{},"泛化",[149,2335,2336],{},"子级指向父级的空心三角关系",[134,2338,2339,2342,2345],{},[149,2340,2341],{},"start state \u002F final state",[149,2343,2344],{},"开始 \u002F 结束状态",[149,2346,2347],{},"实心黑圆 \u002F 黑圆套白圆",[134,2349,2350,2353,2356],{},[149,2351,2352],{},"decision node",[149,2354,2355],{},"判断节点",[149,2357,2358],{},"菱形，分支处标方括号条件",[134,2360,2361,2364,2367],{},[149,2362,2363],{},"guard condition",[149,2365,2366],{},"守卫条件",[149,2368,2369],{},"活动图分支上的方括号条件",[134,2371,2372,2375,2378],{},[149,2373,2374],{},"synchronization bar",[149,2376,2377],{},"同步条",[149,2379,2380],{},"粗黑线，表示并行分叉或汇合",[134,2382,2383,2386,2389],{},[149,2384,2385],{},"swimlane",[149,2387,2388],{},"泳道",[149,2390,2391],{},"按执行者划分的竖直分区",[134,2393,2394,2396,2399],{},[149,2395,2135],{},[149,2397,2398],{},"读写方向错误",[149,2400,2401],{},"实体读写箭头画反，workshop 常见批注",[134,2403,2404,2407,2410],{},[149,2405,2406],{},"lifeline",[149,2408,2409],{},"生命线",[149,2411,2412],{},"顺序图里对象的竖直虚线",[134,2414,2415,2418,2421],{},[149,2416,2417],{},"message",[149,2419,2420],{},"消息",[149,2422,2423],{},"对象间的一次调用，实线箭头",[134,2425,2426,2429,2432],{},[149,2427,2428],{},"activation bar",[149,2430,2431],{},"激活条",[149,2433,2434],{},"表示对象正在处理的时间段",[134,2436,2437,2440,2443],{},[149,2438,2439],{},"return",[149,2441,2442],{},"返回",[149,2444,2445],{},"用虚线箭头表示的结果回传",[134,2447,2448,2451,2453],{},[149,2449,2450],{},"visibility",[149,2452,1421],{},[149,2454,2455,33,2457,33,2459,2461],{},[30,2456,1426],{},[30,2458,1430],{},[30,2460,201],{}," 表示成员开放程度",[134,2463,2464,2467,2470],{},[149,2465,2466],{},"dependency",[149,2468,2469],{},"依赖",[149,2471,2472],{},"虚线箭头，表示临时使用",[134,2474,2475,2478,2481],{},[149,2476,2477],{},"association",[149,2479,2480],{},"关联",[149,2482,2483],{},"实线，表示长期持有引用",[134,2485,2486,2489,2492],{},[149,2487,2488],{},"aggregation",[149,2490,2491],{},"聚合",[149,2493,2494],{},"空心菱形，部分可独立存在",[134,2496,2497,2500,2503],{},[149,2498,2499],{},"composition",[149,2501,2502],{},"组合",[149,2504,2505],{},"实心菱形，部分随整体消亡",[134,2507,2508,2511,2514],{},[149,2509,2510],{},"multiplicity",[149,2512,2513],{},"重数",[149,2515,2516],{},"关系一端可对应的实例个数",[134,2518,2519,2522,2525],{},[149,2520,2521],{},"endArrow \u002F endFill",[149,2523,2524],{},"端点箭头 \u002F 是否填充",[149,2526,2527],{},"draw.io 里画菱形与三角的两个关键属性",[134,2529,2530,2532,2535],{},[149,2531,287],{},[149,2533,2534],{},"编辑样式",[149,2536,2537],{},"draw.io 格式面板里直接写属性的入口",[134,2539,2540,2543,2546],{},[149,2541,2542],{},"metaphor",[149,2544,2545],{},"隐喻",[149,2547,2548],{},"借真实世界形态组织界面信息",[134,2550,2551,2554,2557],{},[149,2552,2553],{},"assumption",[149,2555,2556],{},"假设",[149,2558,2559],{},"信息不足时写明的前提",{"title":97,"searchDepth":2561,"depth":2561,"links":2562},3,[2563,2565,2570,2571,2578,2584,2590,2597,2598,2599,2600,2603],{"id":24,"depth":2564,"text":25},2,{"id":78,"depth":2564,"text":79,"children":2566},[2567,2568,2569],{"id":83,"depth":2561,"text":84},{"id":125,"depth":2561,"text":126},{"id":183,"depth":2561,"text":184},{"id":300,"depth":2564,"text":301},{"id":410,"depth":2564,"text":411,"children":2572},[2573,2574,2575,2576,2577],{"id":414,"depth":2561,"text":415},{"id":533,"depth":2561,"text":534},{"id":569,"depth":2561,"text":570},{"id":707,"depth":2561,"text":708},{"id":732,"depth":2561,"text":733},{"id":842,"depth":2564,"text":843,"children":2579},[2580,2581,2582,2583],{"id":846,"depth":2561,"text":847},{"id":993,"depth":2561,"text":994},{"id":1059,"depth":2561,"text":1060},{"id":1122,"depth":2561,"text":1123},{"id":1164,"depth":2564,"text":1165,"children":2585},[2586,2587,2588,2589],{"id":1168,"depth":2561,"text":1169},{"id":1263,"depth":2561,"text":1264},{"id":1313,"depth":2561,"text":1314},{"id":1327,"depth":2561,"text":1328},{"id":1364,"depth":2564,"text":1365,"children":2591},[2592,2593,2594,2595,2596],{"id":1368,"depth":2561,"text":1369},{"id":1472,"depth":2561,"text":1473},{"id":1584,"depth":2561,"text":1585},{"id":1671,"depth":2561,"text":1672},{"id":1731,"depth":2561,"text":1732},{"id":1775,"depth":2564,"text":1776},{"id":1848,"depth":2564,"text":1849},{"id":2067,"depth":2564,"text":2068},{"id":2121,"depth":2564,"text":2121,"children":2601},[2602],{"id":2154,"depth":2561,"text":2154},{"id":2253,"depth":2564,"text":2253},"学习",null,"2026-11-19","不模拟软件界面，只讲清三件事：每个 UML 符号在 draw.io 里搜什么词、一张图该按什么顺序落笔、画完拿什么标准自查。覆盖用例图、活动图、顺序图、类图、界面草图五种图纸，末尾附「最容易画反的十二笔」总检表。","md",false,{},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-28",{"title":5,"description":2607},"软件分析与设计笔记",28,"posts\u002FswDesign\u002Fsw-design-notes-28",[2617,114,2618,2619],"应试","绘图","学习笔记","TFYE2xXvJXDKsnZC9gcfrUAZT68KwqbkD78eeMiMK-8",[2622,2623,2629,2635,2641,2647,2653,2659,2665,2671,2677,2683,2689,2695,2701,2707,2713,2719,2725,2731,2737,2743,2749,2755,2761,2767,2772,2777,2783,2789,2793,2797,2801,2805,2809,2813,2817,2821,2825,2829,2833,2839,2843,2849,2853,2857,2861,2865,2869,2873,2877,2882,2886,2890,2895,2900,2906,2910,2915,2919],{"path":2611,"title":5,"description":2607,"date":2606,"series":2613,"seriesOrder":2614},{"path":2624,"title":2625,"description":2626,"date":2627,"series":2613,"seriesOrder":2628},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-27","软件分析与设计笔记 27：Paper 1 应试：从读案例到交卷的一次完整演算","拿一份完整的案例，从头到尾走一遍：怎么读案例列角色、怎么在四个小问之间分配时间、每一张图从哪一句话推出来、两张表怎么填、交卷前拿什么清单自查。附 C25 真题与样卷的题型分值对照。","2026-11-18",27,{"path":2630,"title":2631,"description":2632,"date":2633,"series":2613,"seriesOrder":2634},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-26","软件分析与设计笔记 26：总结：把整条链路串起来","系列收尾：从需求到代码的完整链路回顾、每一环的产出与验收方式、六条贯穿全系列的原则，以及一份可以直接拿去做项目自查的清单。","2026-11-17",26,{"path":2636,"title":2637,"description":2638,"date":2639,"series":2613,"seriesOrder":2640},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-25","软件分析与设计笔记 25：代码重构：坏味道与手法","重构不改变外部行为、只改善内部结构：四种常见坏味道与对应手法、为什么动手之前必须先有测试、什么时候该重构，以及重构和前面那些设计模型是什么关系。","2026-11-16",25,{"path":2642,"title":2643,"description":2644,"date":2645,"series":2613,"seriesOrder":2646},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-24","软件分析与设计笔记 24：设计原则：内聚、耦合与多态","好设计怎么衡量：内聚与耦合分别在说什么、一次从「差设计」到「多态重设计」的完整对照、抽象类与接口的选择依据，以及复用为什么会从优势变成风险。","2026-11-15",24,{"path":2648,"title":2649,"description":2650,"date":2651,"series":2613,"seriesOrder":2652},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-23","软件分析与设计笔记 23：设计建模：从对象模型到能实现的方案","分析模型能用但还不能直接开工：对象模型怎么映射到关系模型、继承映射的三种方案怎么选、数据访问层与 Data Broker 解决什么问题，以及三层架构与 MVC 的分工。","2026-11-14",23,{"path":2654,"title":2655,"description":2656,"date":2657,"series":2613,"seriesOrder":2658},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-22","软件分析与设计笔记 22：分析建模：边界、实体与控制对象","不经过分析直接写代码会踩什么坑、三种分析对象各管一段、怎么用顺序图完成一次用例实现，以及从顺序图导出类的属性、操作与关系的方法。","2026-11-13",22,{"path":2660,"title":2661,"description":2662,"date":2663,"series":2613,"seriesOrder":2664},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-21","软件分析与设计笔记 21：UML：类图与顺序图","为什么需要一种共同的画法：类符号三格怎么画、五种关系的符号与设计含义、每种关系落到 Java 是什么写法，顺序图的三要素怎么摆；以及这三种最容易找不到的符号在 draw.io 里各搜什么词。","2026-11-12",21,{"path":2666,"title":2667,"description":2668,"date":2669,"series":2613,"seriesOrder":2670},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-20","软件分析与设计笔记 20：面向对象概念：对象、关系与多态","面向对象不是「用某个语言写代码」：对象与类的区别、封装真正在保护什么、五种关系（依赖、关联、聚合、组合、继承）各自何时用，以及多态为什么能减少条件判断。","2026-11-11",20,{"path":2672,"title":2673,"description":2674,"date":2675,"series":2613,"seriesOrder":2676},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-19","软件分析与设计笔记 19：规范化与逻辑数据模型","一次改地址引发的数据不一致，讲清规范化的真正动机；UNF 到 3NF 每一步在解决什么问题，派生字段为什么不能存，优化为什么和规范化方向相反，以及逻辑数据模型在 3NF 之上补了什么。","2026-11-10",19,{"path":2678,"title":2679,"description":2680,"date":2681,"series":2613,"seriesOrder":2682},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-18","软件分析与设计笔记 18：数据库分析：实体、关系与数据字典","为什么不能拿到需求就动手建表：实体与关系怎么判定、基数为什么必须由业务方确认、数据命名要遵守什么规则，以及数据字典四列里最容易被空着的那一列。","2026-11-09",18,{"path":2684,"title":2685,"description":2686,"date":2687,"series":2613,"seriesOrder":2688},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-17","软件分析与设计笔记 17：用生成式 AI 做设计与开发：能用的场景与要防的坑","生成式 AI 在工作流里真正站得住的三个场景 —— 造示例数据、解释陌生代码、起草初稿；它为什么会复现社会偏见、为什么会编得像真的，以及哪些内容绝不能直接采用。","2026-11-08",17,{"path":2690,"title":2691,"description":2692,"date":2693,"series":2613,"seriesOrder":2694},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-16","软件分析与设计笔记 16：从 persona 到 URS：一份交付物的完整骨架","把前面十几篇串成一份能交出去的东西：用户需求规格说明书的九个部分、每一章来自哪个环节、由谁确认，以及面向决策者的提案该讲清哪三件事。","2026-11-07",16,{"path":2696,"title":2697,"description":2698,"date":2699,"series":2613,"seriesOrder":2700},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-15","软件分析与设计笔记 15：非功能需求：把「快、稳、安全」变成数字","为什么「系统要快」不是一条需求：非功能需求怎么量化，决定性能的用户量、交易量、数据量三张表怎么估，安全需求要写清什么，以及可靠性的「不可用」该怎么定义。","2026-11-06",15,{"path":2702,"title":2703,"description":2704,"date":2705,"series":2613,"seriesOrder":2706},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-14","软件分析与设计笔记 14：软件测试：层级、方法与等价类划分","「我们测过了」这句话问题在哪：为什么静态评审和动态测试缺一不可，五个测试层级各自验证什么，白盒与黑盒的差别，以及用等价类划分和边界值把无限输入变成有限用例的方法。","2026-11-05",14,{"path":2708,"title":2709,"description":2710,"date":2711,"series":2613,"seriesOrder":2712},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-13","软件分析与设计笔记 13：需求获取：五种调查方法与一场访谈","需求从哪里来：五种事实调查方法各自适合回答什么、代价是什么，访谈从准备到记录的全过程，问卷设计里最容易犯的错，以及访谈记录必须写下来的那几项信息。","2026-11-04",13,{"path":2714,"title":2715,"description":2716,"date":2717,"series":2613,"seriesOrder":2718},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-12","软件分析与设计笔记 12：前端设计：把流程变成屏幕","界面设计不是「画得好看」：从活动图走到屏幕的三步，CRUD 任务流怎么当检查表，界面必须回答的三个问题，信息架构与五种导航类型，视觉一致性与留白，以及移动端与 Web 端的差别。","2026-11-03",12,{"path":2720,"title":2721,"description":2722,"date":2723,"series":2613,"seriesOrder":2724},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-11","软件分析与设计笔记 11：Agentic AI 与业务流程自动化","AI agent 到底是什么：五项能力与四个核心组件，什么场景该用定时任务、什么该用程序、什么才值得用 agent，两种实现路径的差别，必须提前防住的四类失败模式，以及设计方法从提示词到编排的演进。","2026-11-02",11,{"path":2726,"title":2727,"description":2728,"date":2729,"series":2613,"seriesOrder":2730},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-10","软件分析与设计笔记 10：精炼用例模型：include、extend 与泛化","三种精炼用例关系的判断标准：include 什么时候用、它和 extend 的区别到底在哪、参与者泛化与用例泛化各解决什么问题，以及精炼到什么程度就该停手。","2026-11-01",10,{"path":2732,"title":2733,"description":2734,"date":2735,"series":2613,"seriesOrder":2736},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-09","软件分析与设计笔记 09：功能需求（二）：从流程到业务实体","活动图画完之后，怎么从流程里筛出真正的业务实体：三条判断标准、哪些名词其实不该建实体、属性从哪里来，以及领域模型和后面的数据模型分别负责什么。","2026-10-31",9,{"path":2738,"title":2739,"description":2740,"date":2741,"series":2613,"seriesOrder":2742},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-08","软件分析与设计笔记 08：功能需求（一）：用例模型与活动图","从用户故事到用例的翻译过程：什么才算「好」的参与者，系统边界怎么划，用例描述必须写清哪四件事，活动图怎么把分支、并行与泳道画清楚，以及这两个图在 draw.io 里各用哪个形状、最容易画错哪一笔。","2026-10-30",8,{"path":2744,"title":2745,"description":2746,"date":2747,"series":2613,"seriesOrder":2748},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-07","软件分析与设计笔记 07：用户故事：把需求写成可验收的一句话","用户故事的三段结构，怎么从用户画像和数据地图里把它提取出来，一条故事多大算合适、时序为什么也是需求的一部分，以及验收标准怎么写才算真的可验收。","2026-10-29",7,{"path":2750,"title":2751,"description":2752,"date":2753,"series":2613,"seriesOrder":2754},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-06","软件分析与设计笔记 06：范围界定（数据侧）：用数据校验你的判断","访谈结论和数字对不上时该怎么办：分析的四个层次分别在回答什么问题、为什么不能跳级、数据准备与搜集怎么做成一张应用地图，以及数据最容易在哪几个地方骗你。","2026-10-28",6,{"path":2756,"title":2757,"description":2758,"date":2759,"series":2613,"seriesOrder":2760},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-05","软件分析与设计笔记 05：范围界定（用户侧）：用户画像与客户旅程图","为什么「所有用户」是一个陷阱，项目边界该怎么划，用户画像要写哪五个要素、最容易写成什么废纸，客户旅程图怎么把阶段、想法和情绪画在同一张纸上，以及怎么从这两样东西一步步推到可验证的需求。","2026-10-27",5,{"path":2762,"title":2763,"description":2764,"date":2765,"series":2613,"seriesOrder":2766},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-04","软件分析与设计笔记 04：接手陌生案例的第一步：三问与一张表","拿到一个完全陌生的业务案例，怎么从零开始不跑偏：只问 Who、What、Why 三个问题，把「问题—事实—假设—理由」记成一张四列表，说清为什么假设必须写明理由，以及带着问题进访谈为什么比空手去有效得多。","2026-10-26",4,{"path":2768,"title":2769,"description":2770,"date":2771,"series":2613,"seriesOrder":2561},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-03","软件分析与设计笔记 03：Agile 与 Scrum：迭代、角色与产出物","从「三周做完交付，客户说这不是我要的」讲起，说清瀑布式与迭代式的根本差别，Scrum 的三个角色和三种产出物，一个 sprint 里四次固定活动各自在解决什么问题，以及敏捷里最常见的几个误解。","2026-10-25",{"path":2773,"title":2774,"description":2775,"date":2776,"series":2613,"seriesOrder":2564},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-02","软件分析与设计笔记 02：设计思维、用户驱动与数据驱动","从「客服要一个能一次看完所有排期的界面」这个翻车案例讲起，说清设计思维到底是什么、用户驱动与数据驱动各自能看见什么又看不见什么、为什么真正的落点是把两者合起来的 data-informed design，以及访谈中怎么问出有用的信息。","2026-10-24",{"path":2778,"title":2779,"description":2780,"date":2781,"series":2613,"seriesOrder":2782},"\u002Fposts\u002Fswdesign\u002Fsw-design-notes-01","软件分析与设计笔记 01：课程地图与从需求到设计的主干","这一篇不写具体方法，先把整条链路铺开：软件分析与设计到底要解决什么问题，从需求到设计分成哪两段，中间有哪十几个环节，一份完整的交付物里应该有什么，以及后面 27 篇笔记怎么排、新人该按什么顺序读。","2026-10-23",1,{"path":2784,"title":2785,"description":2786,"date":2787,"series":2788,"seriesOrder":2782},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-01","Spring 学习笔记 01：IoC、依赖注入与第一个 Spring Boot 应用","从「手写 new 出来的三层结构」的痛点讲起，说清 IoC 容器、Bean 与依赖注入是怎么回事，再用 Maven 与 Spring Initializr 跑起第一个能返回 JSON 的应用。","2026-10-15","Spring 学习笔记",{"path":2790,"title":2791,"description":2792,"date":2787,"series":2788,"seriesOrder":2564},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-02","Spring 学习笔记 02：Spring Data JPA 基础——实体映射与 Repository","用 ORM 把类映射到表：@Entity、@Id、@GeneratedValue 怎么用，CrudRepository 三层接口怎么选，H2 与 MySQL 怎么配，以及 ddl-auto 到底该写哪个值。",{"path":2794,"title":2795,"description":2796,"date":2787,"series":2788,"seriesOrder":2561},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-03","Spring 学习笔记 03：JPA 查询——派生方法、JPQL 与分页排序","Repository 自带的方法只够按主键查，这篇讲三种自己造查询的方式：方法名派生、@Query 写 JPQL、原生 SQL，以及 Pageable 分页排序和投影返回。",{"path":2798,"title":2799,"description":2800,"date":2787,"series":2788,"seriesOrder":2766},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-04","Spring 学习笔记 04：JPA 关联映射与仓储测试","一对多、多对多怎么映射，谁负责维护外键，FetchType 与 CascadeType 该怎么选，顺带用 @DataJpaTest 与 AssertJ 把仓储层测起来。",{"path":2802,"title":2803,"description":2804,"date":2787,"series":2788,"seriesOrder":2760},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-05","Spring 学习笔记 05：Spring MVC 与 Thymeleaf 入门","一次页面请求在 Spring MVC 里走了哪几步，@Controller 怎么把数据交给模板，@PathVariable 与 @RequestParam 怎么取参数，以及控制器为什么必须是无状态的。",{"path":2806,"title":2807,"description":2808,"date":2787,"series":2788,"seriesOrder":2754},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-06","Spring 学习笔记 06：表单绑定与服务端校验","把表单字段绑到对象上，用 Bean Validation 注解做服务端校验，把错误信息显示回用户刚填的那一页，再补上自定义校验注解与全局异常处理。",{"path":2810,"title":2811,"description":2812,"date":2787,"series":2788,"seriesOrder":2748},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-07","Spring 学习笔记 07：Thymeleaf 片段复用与国际化","用 th:fragment 与 th:insert\u002Fth:replace 把导航栏、页脚抽成片段，页面套用统一布局，再用 messages.properties 与 LocaleResolver 做中英文切换。",{"path":2814,"title":2815,"description":2816,"date":2787,"series":2788,"seriesOrder":2742},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-08","Spring 学习笔记 08：HTTP Session 与会话状态管理","HTTP 无状态带来的问题，Cookie 与 Session 怎么分工，Spring 里读写会话的几种方式，以及会话固定、超时、多实例共享这些必须想清楚的事。",{"path":2818,"title":2819,"description":2820,"date":2787,"series":2788,"seriesOrder":2736},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-09","Spring 学习笔记 09：拦截器 HandlerInterceptor","登录检查、权限判断、请求耗时统计这类横切逻辑该放哪：HandlerInterceptor 的三个回调各在什么时机执行，怎么注册与排除路径，以及它和过滤器的分工。",{"path":2822,"title":2823,"description":2824,"date":2787,"series":2788,"seriesOrder":2730},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-10","Spring 学习笔记 10：Service 层与事务","一组数据库操作要么全成功要么全失败，靠 @Transactional 怎么做到；传播行为、隔离级别、回滚规则怎么选，以及自调用失效、乐观锁悲观锁这些实战里的坑。",{"path":2826,"title":2827,"description":2828,"date":2787,"series":2788,"seriesOrder":2724},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-11","Spring 学习笔记 11：REST API 基础——把 Service 暴露成接口","同一套 Service 怎么同时服务页面和客户端：@RestController 的路由与方法语义、状态码怎么给、DTO 怎么定，以及 MockMvc 端到端和切片测试的两种写法与各自的坑。",{"path":2830,"title":2831,"description":2832,"date":2787,"series":2788,"seriesOrder":2718},"\u002Fposts\u002Fjavaspring\u002Fspring-notes-12","Spring 学习笔记 12：REST 进阶——版本、更新、跨域与文档化","接口能跑通之后要处理的几件事：URL 与响应结构怎么定、版本怎么演进、更新怎么做到可安全重试、CORS 怎么配、HATEOAS 与 Spring Data REST 该不该用。",{"path":2834,"title":2835,"description":2836,"date":2837,"series":2838,"seriesOrder":2766},"\u002Fposts\u002Fjava\u002Fjava-functionalprogramming-notes","Java 函数式编程笔记：Lambda、函数式接口与 Streams","学习 Java 函数式编程时的个人笔记：Lambda 表达式的五步简写与方法引用、常见函数式接口、Stream 流水线与惰性求值，以及创建流、中间操作、终止操作与收集器的用法。示例代码均为自写，运行结果来自本地实测。","2026-10-13","Java 学习笔记",{"path":2840,"title":2841,"description":2842,"date":2837,"series":2838,"seriesOrder":2561},"\u002Fposts\u002Fjava\u002Fjava-generics-notes","Java 泛型笔记：泛型方法、有界类型与泛型类","学习 Java 泛型时的个人笔记：从重复的重载方法与多态尝试讲起，再到泛型方法与类型推断、有界泛型类型、Comparable 与 Number 边界，以及泛型类在集合中的用法。示例代码均为自写，运行结果来自本地实测。",{"path":2844,"title":2845,"description":2846,"date":2847,"series":2848,"seriesOrder":2766},"\u002Fposts\u002Fmysql\u002Fmysql-learning-04","MySQL 学习笔记 04：数据操纵（增删改）","MySQL 学习笔记第四篇：INSERT 插入（含批量插入与 INSERT ... SELECT）、UPDATE 更新、DELETE 删除，以及各自的坑。","2026-10-10","SQL 学习笔记",{"path":2850,"title":2851,"description":2852,"date":2847,"series":2848,"seriesOrder":2760},"\u002Fposts\u002Fmysql\u002Fmysql-learning-05","MySQL 学习笔记 05：DDL 概览","MySQL 学习笔记第五篇：数据定义语言概览——Schema、Table、View、Index、Constraints 这几类对象分别对应哪些 CREATE \u002F ALTER \u002F DROP 命令。",{"path":2854,"title":2855,"description":2856,"date":2847,"series":2848,"seriesOrder":2754},"\u002Fposts\u002Fmysql\u002Fmysql-learning-06","MySQL 学习笔记 06：CREATE TABLE 与数据类型","MySQL 学习笔记第六篇：CREATE TABLE 的完整语法、常用数据类型的选型建议，以及外键的两种定义方式。",{"path":2858,"title":2859,"description":2860,"date":2847,"series":2848,"seriesOrder":2748},"\u002Fposts\u002Fmysql\u002Fmysql-learning-07","MySQL 学习笔记 07：索引","MySQL 学习笔记第七篇：索引的作用与 B+ 树结构、单列与复合索引的创建、索引的代价与适用场景。",{"path":2862,"title":2863,"description":2864,"date":2847,"series":2848,"seriesOrder":2742},"\u002Fposts\u002Fmysql\u002Fmysql-learning-08","MySQL 学习笔记 08：DROP 与 ALTER","MySQL 学习笔记第八篇：DROP 删除数据库对象、ALTER 修改表结构，以及常见的坑。",{"path":2866,"title":2867,"description":2868,"date":2847,"series":2848,"seriesOrder":2736},"\u002Fposts\u002Fmysql\u002Fmysql-learning-09","MySQL 学习笔记 09：约束与数据完整性","MySQL 学习笔记第九篇：SQL 约束——NOT NULL、CHECK、PRIMARY KEY、FOREIGN KEY 等如何保证数据完整性，以及它们的对比。",{"path":2870,"title":2871,"description":2872,"date":2847,"series":2848,"seriesOrder":2730},"\u002Fposts\u002Fmysql\u002Fmysql-learning-10","MySQL 学习笔记 10：视图","MySQL 学习笔记第十篇：视图（Views）的定义与特性、和表的对比、创建与使用，以及可更新视图的限制。",{"path":2874,"title":2875,"description":2876,"date":2847,"series":2848,"seriesOrder":2724},"\u002Fposts\u002Fmysql\u002Fmysql-learning-11","MySQL 学习笔记 11：存储过程","MySQL 学习笔记第十一篇：存储过程（Stored Procedures）的概念、创建与调用、带参数的写法，以及优缺点。",{"path":2878,"title":2879,"description":2880,"date":2881,"series":2848,"seriesOrder":2782},"\u002Fposts\u002Fmysql\u002Fmysql-learning-01","MySQL 学习笔记 01：MySQL 基础知识","MySQL 学习笔记第一篇：MySQL Server 与 Workbench 的安装，数据库与 DBMS 的基本概念，关系模型、ACID 事务、常见数据类型，以及后续的学习路线。","2026-10-09",{"path":2883,"title":2884,"description":2885,"date":2881,"series":2848,"seriesOrder":2564},"\u002Fposts\u002Fmysql\u002Fmysql-learning-02","MySQL 学习笔记 02：SELECT 查询与过滤","MySQL 学习笔记第二篇：SELECT 的基本语法与逻辑执行顺序，WHERE 过滤（比较、LIKE、IN、BETWEEN、NULL）、各种 JOIN、UNION 与子查询。",{"path":2887,"title":2888,"description":2889,"date":2881,"series":2848,"seriesOrder":2561},"\u002Fposts\u002Fmysql\u002Fmysql-learning-03","MySQL 学习笔记 03：聚合、分组与输出控制","MySQL 学习笔记第三篇：COUNT\u002FSUM\u002FAVG 等聚合函数、GROUP BY 分组、HAVING 过滤、ORDER BY 与 LIMIT，以及一条 SELECT 的完整逻辑执行顺序。",{"path":2891,"title":2892,"description":2893,"date":2894,"series":2838,"seriesOrder":2564},"\u002Fposts\u002Fjava\u002Fjava-oop-notes","Java 面向对象笔记：类、继承、多态与异常","学习 Java 面向对象编程时的个人笔记：类与对象、封装与访问修饰符、继承与多态、集合、抽象类与接口、异常处理。示例代码均为自写，运行结果来自本地实测。","2026-10-06",{"path":2896,"title":2897,"description":2898,"date":2899,"series":2838,"seriesOrder":2782},"\u002Fposts\u002Fjava\u002Fjava-basics-notes","Java 基础语法笔记：从环境安装到方法与数组","学习 Java 基础语法时的个人笔记：JDK 安装、输入输出、变量与运算符、条件与循环、字符串、数组与方法。示例代码均为自写，运行结果来自本地实测。","2026-10-05",{"path":2901,"title":2902,"description":2903,"date":2904,"series":2905,"seriesOrder":2782},"\u002Fposts\u002Fgit\u002Fgit-install-and-basics","Git 安装与基本使用","从装好 Git 到跑通日常提交流程，把最常用的几条命令和它们背后的三个区域讲清楚。","2026-10-04","Git 入门",{"path":2907,"title":2908,"description":2909,"date":2904,"series":2905,"seriesOrder":2564},"\u002Fposts\u002Fgit\u002Flocal-remote-repository","本地远程仓库的部署","用自己的机器当 Git 服务器：建一个裸仓库、走 SSH 连上去，把本地提交推上去。",{"path":2911,"title":2912,"description":2913,"date":2904,"series":2914,"seriesOrder":2782},"\u002Fposts\u002Fguide\u002Fguide-file-layout","文件都放在哪","文章、图片、封面分别放在仓库的什么位置，哪些目录可以放手改、哪些碰了会出问题。","博客使用指南",{"path":2916,"title":2917,"description":2918,"date":2904,"series":2914,"seriesOrder":2564},"\u002Fposts\u002Fguide\u002Fguide-frontmatter","frontmatter 每个字段是什么意思","文章开头那段被横线包住的字段，逐个说明作用、默认行为和写错的后果。",{"path":2920,"title":2921,"description":2922,"date":2904,"series":2914,"seriesOrder":2561},"\u002Fposts\u002Fguide\u002Fguide-markdown","正文怎么写 —— Markdown 与排版效果","标题、链接、图片、代码、表格分别怎么写，以及本站对它们做了哪些自定义处理。",1793268147833]