% Anti-pattern gallery -- four figures that compile cleanly and still teach % the reader something false. Each pair is wrong / right. % ../scripts/build.sh antipatterns.tex \documentclass[border=10pt]{standalone} \usepackage[cjk]{superfig} \sfsetrole{a}{sfTeal} \sfsetrole{b}{sfOrange} \sfsetrole{c}{sfCoral} \sfsetrole{d}{sfViolet} \newcommand{\bad}[1]{{\color{sfCoral}$\times$}\;#1} \newcommand{\good}[1]{{\color{sfTeal}$\checkmark$}\;#1} \begin{document} \begin{tikzpicture} % (1) A decorative arrow vs a data-flow edge. \sfnode[role=a, at={(0,0)}]{A1}{编码器}{16mm}{10mm} \sfnode[role=b, at={(32mm,0)}]{A2}{指标卡}{16mm}{10mm} \sfarrow{A1}{A2} \sfnode[role=a, at={(64mm,0)}]{A3}{编码器}{16mm}{10mm} \sfnode[role=b, at={(96mm,0)}]{A4}{解码器}{16mm}{10mm} \sfarrowlabel{A3.east}{A4.west}{隐状态} \node[sf stage, anchor=south west] at ($(A1.north west)+(0,6mm)$) {(1) 装饰箭头}; \node[sf shape, anchor=north] (A1c) at ($(A1.south)!0.5!(A2.south)+(0,-3mm)$) {\bad{箭头不承载关系}}; \node[sf shape, anchor=north] (A3c) at ($(A3.south)!0.5!(A4.south)+(0,-3mm)$) {\good{隐状态从编码流向解码}}; % (2) A group that is only a visual border vs a real composite. \sfnode[role=a, at={(0,-32mm)}]{B1}{输入}{14mm}{10mm} \sfnode[role=d, at={(24mm,-32mm)}]{B2}{输出}{14mm}{10mm} \sfgroup[role=a]{Bg}{(B1)(B2)}{} \sfnode[role=b, at={(56mm,-32mm)}]{B3}{注意力}{16mm}{10mm} \sfnode[role=b, at={(82mm,-32mm)}]{B4}{前馈}{14mm}{10mm} \sfgroup[role=b]{Bb}{(B3)(B4)}{} \sfarrow{B3.east}{B4.west} \node[sf stage, anchor=south west] at ($(B1.north west)+(0,8mm)$) {(2) 组框只是装饰边}; \node[sf shape, anchor=north] (B1c) at ($(B1.south)!0.5!(B2.south)+(0,-7mm)$) {\bad{首尾框在一起,不是一个模块}}; \node[sf shape, anchor=north] (B3c) at ($(B3.south)!0.5!(B4.south)+(0,-7mm)$) {\good{主路模块是真实复合对象}}; % (3) One node doing two jobs vs a split. \sfnode[role=b, at={(0,-68mm)}]{C1}{注意力 + LN + 残差}{38mm}{12mm} \sfnode[role=b, at={(56mm,-68mm)}]{C2}{注意力}{16mm}{10mm} \sfnode[role=c, at={(84mm,-68mm)}]{C3}{残差加}{16mm}{10mm} \sfarrow{C2.east}{C3.west} \node[sf stage, anchor=south west] at ($(C1.north west)+(0,6mm)$) {(3) 一个节点做两件事}; \node[sf shape, anchor=north] (C1c) at ($(C1.south)+(0,-3mm)$) {\bad{机制被一口吞掉}}; \node[sf shape, anchor=north] (C2c) at ($(C2.south)!0.5!(C3.south)+(0,-3mm)$) {\good{一步一个对象}}; % (4) A new hue for the same object vs one role, two levels. \sfnode[role=a, level=2, at={(0,-100mm)}]{D1}{$x$}{14mm}{10mm} \sfnode[role=c, level=2, at={(24mm,-100mm)}]{D2}{$x$ 归一化}{20mm}{10mm} \sfnode[role=a, level=1, at={(64mm,-100mm)}]{D3}{$x$}{14mm}{10mm} \sfnode[role=a, level=3, at={(90mm,-100mm)}]{D4}{$x$ 归一化}{20mm}{10mm} \node[sf stage, anchor=south west] at ($(D1.north west)+(0,6mm)$) {(4) 同一对象换了色相}; \node[sf shape, anchor=north] (D1c) at ($(D1.south)!0.5!(D2.south)+(0,-3mm)$) {\bad{换色相像换了对象}}; \node[sf shape, anchor=north] (D3c) at ($(D3.south)!0.5!(D4.south)+(0,-3mm)$) {\good{同一角色,深浅分层}}; \node[inner sep=0pt, fit=(A1)(A4)(D1)(D4)(A1c)(D3c)(Bg)(Bb)] (all) {}; \sfmeaningbox{mb}{118mm}{all} {} {四张错图都能干净编译。编译器不检查图讲的事情对不对} {交付前按 \texttt{references/checklist.md} 做一次人眼审图} \end{tikzpicture} \end{document}