<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Paramer 开发记录 on Veno's Blog</title><link>https://v3n0.top/categories/paramer-%E5%BC%80%E5%8F%91%E8%AE%B0%E5%BD%95/</link><description>Recent content in Paramer 开发记录 on Veno's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><lastBuildDate>Tue, 16 Jun 2026 16:51:56 +0800</lastBuildDate><atom:link href="https://v3n0.top/categories/paramer-%E5%BC%80%E5%8F%91%E8%AE%B0%E5%BD%95/index.xml" rel="self" type="application/rss+xml"/><item><title>Paramer 开发记录 2 - 低效沟通的灾难与异步协作的探索</title><link>https://v3n0.top/post/paramer/2/</link><pubDate>Tue, 16 Jun 2026 16:51:56 +0800</pubDate><guid>https://v3n0.top/post/paramer/2/</guid><description>&lt;p&gt;拖更两个月，惭愧，但这两个月也是积累了相当多的新思考。&lt;/p&gt;
&lt;p&gt;第二篇原本在序言里主题被定为，开发踩坑。其实这个选题太莽撞。上篇技术选型问题也是开发踩坑问题。但是开发踩坑其实只是个表层的现象，我们要看到现象背后的本质。&lt;/p&gt;
&lt;p&gt;我实际上在第一篇之后，紧接着就为开发踩坑这一主题写了一些大纲，发现我根本写不出来。写不出来说明思考不足，经历不足，这时我就不想再硬写了，那样的文章是不成熟的没价值的。后面一段时间把本篇的草稿直接当成了《人月神话》的读书摘录笔记了，这本书真是常看常新。&lt;/p&gt;
&lt;p&gt;这一个多月我没有继续参与 Paramer 的开发工作。我先给自己差不多两周的时间自顾自放了个假，而后才回到团队。但仍然不是负责开发。由于我在项目里的参与时间足够久，项目理解足够，实际上充当了一个类似顾问的角色，因为产品经理和开发之间往往各自说着自己的语言，每天 @ 人然后失踪，然后进度停滞。我注意到这种情况时会尝试出来为双方明确各自观点，帮助同步各项任务进度，同步信息，提供项目建议。&lt;/p&gt;
&lt;p&gt;在这个过程中，因为是传话筒，所以意识到了到底有哪些话要传，什么时候要传话，不断意识到了到底在什么地方的信息沟通是低效的阻塞的。而这些是作为开发人员时，无法在团队中感知的，所谓不识庐山真面目，只缘身在此山中。&lt;/p&gt;
&lt;p&gt;开发踩坑是问题，问题背后的本质原因很多，在 Paramer 的开发经历中，团队沟通占相当大的一头。其实&lt;a class="link" href="https://v3n0.top/post/paramer/1/" target="_blank" rel="noopener"
&gt;上一篇&lt;/a&gt;我已经提到过：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;错误的团队沟通导致错误的需求理解，错误的需求理解导致错误的技术选型。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上一篇主要聚焦在了&lt;strong&gt;需求理解&lt;/strong&gt;，它直接对于开发造成影响。这一篇继续深入讨论，谈谈&lt;strong&gt;团队沟通&lt;/strong&gt;带来的问题。它会造成远不止需求理解的问题。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="失败案例"&gt;失败案例
&lt;/h2&gt;&lt;p&gt;上回说到从 SimFlow 原型重构的 Paramer V1 由于技术选型的失误已经误入歧途。下面看看 Paramer 在歧途中经历了怎样的灾难，开发人员经历了怎样的燃烧。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“How does a project get to be a year late? &amp;hellip; One day at a time.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;千里之堤，溃于蚁穴。生病，应急任务，私人问题，客户的紧急会议，每件事只会把进度延后半天或一天，一天天的进度缓慢难以识别，难以防备。积累起来，结果就会是项目延期一年。&lt;/p&gt;
&lt;h3 id="场景一不稳定的需求"&gt;场景一：不稳定的需求
&lt;/h3&gt;&lt;p&gt;团队闲聊的时候我想问问大家有没有想写的素材，&lt;a class="link" href="blog.minblog.top" &gt;月饼&lt;/a&gt;，我们的运维，说：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这样，你直接在聊天记录里搜索”不是说好”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;确实是这样，太多次在进行功能开发的时候，做完了一个需求，结果要么是产品变卦，要么是客户变卦，又或者是在开会对进度时才提起一个被人遗忘在聊天记录里的需求，种种此类。比如要给客户适配的调度器临时变卦，比如功能开发完了才说不够还需要补上新的需求等等。&lt;/p&gt;
&lt;p&gt;还有一种情况是由于产品经理虽然做过一些技术，但并未有过该产品对应技术栈的经验，这会导致错误的在表达产品需求的过程中提出很多本不必要的技术层面的要求。例如，硬件开发经历的产品经理指导后端开发，把应用需要长时间稳定运行这一需求描述为了需要在应用里做系统服务，等等。&lt;/p&gt;
&lt;p&gt;这些情况在 Paramer 的开发历程中屡见不鲜。我举一个列表排序这种比较通用的需求案例，来讲讲当时的团队内是怎么做沟通的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Day 1&lt;/p&gt;
&lt;p&gt;开发燃烧两周之后，跑到线下开会，验收前后端实则是联调。&lt;/p&gt;
&lt;p&gt;由于接口没对好，前端出 bug 访问不到后端的 API，众人汗颜，产品表示第二天线上开会验收成果&lt;/p&gt;
&lt;p&gt;Day 2&lt;/p&gt;
&lt;p&gt;产品经理因为并不只是产品经理，他有更重要的事情忙去了，表示验收改到明天。今日并未验收&lt;/p&gt;
&lt;p&gt;今日开发无事可做&lt;/p&gt;
&lt;p&gt;Day 3&lt;/p&gt;
&lt;p&gt;开视频会议验收。产品口头表示，这个记录排序现在是按 ID 排的，记录有的绿有的黄有的红，不整齐。改成按状态排序。&lt;/p&gt;
&lt;p&gt;后端开发调整了 SQL&lt;/p&gt;
&lt;p&gt;Day 7&lt;/p&gt;
&lt;p&gt;团队内部使用人员说，这个排序顺序好像有点奇怪，状态优先级不应该是 Running 放最前面，是 Completed 放最前面。&lt;/p&gt;
&lt;p&gt;后端再次调整了 SQL&lt;/p&gt;
&lt;p&gt;Day N&lt;/p&gt;
&lt;p&gt;前端在群聊里问（没错这几乎是我们提 Issue 的方式）：
&lt;img src="https://v3n0.top/post/paramer/2/image-1.png"
width="652"
height="1016"
srcset="https://v3n0.top/post/paramer/2/image-1_hu_a2942a744e4ff4e1.png 480w, https://v3n0.top/post/paramer/2/image-1_hu_7cf0c070fa6eb9b1.png 1024w"
loading="lazy"
alt="既要又要"
class="gallery-image"
data-flex-grow="64"
data-flex-basis="154px"
&gt;
Day N+N&lt;/p&gt;
&lt;p&gt;产品给客户试用了。产品经理说，客户还是喜欢按 ID 排序。&lt;/p&gt;
&lt;p&gt;产品看了眼开发，发现他燃烧起来了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;光是这样可能看不出什么很大的问题，稍微改几行代码的事情。&lt;/p&gt;
&lt;p&gt;实则不然。&lt;/p&gt;
&lt;p&gt;笔者为了追溯这一个功能需求的反复变动，到底经历了什么呢：我把这个群几个月的每天起步几十一百条的聊天记录，翻过去找哪些截图和聊天和这个功能有关，又去翻仓库的 commit message，才追溯到的。&lt;/p&gt;
&lt;p&gt;想象，这样的不稳定的变更，每天有不同的十个“有人@你”，散落在群聊消息里。有的压根没描述清楚你还要进一步问，但你@他发现他也没回，也许他也在燃烧；有的早就已经被提过了，你记得跟他说过为什么现在要做成这样，可你翻不到几个星期之前的聊天记录了；而你同时在赶着现在说要加急开发的功能的 DDL。那就变成地狱了&lt;/p&gt;
&lt;h3 id="场景二进度灾难"&gt;场景二：进度灾难
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;（本节引用段中的内容均来自《人月神话》原文）&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;《人月神话》里这样讲到过：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;不为系统测试安排足够的时间简直就是一场灾难。因为延迟发生在项目快完成的时候。直到项目的发布日期，才有人发现进度上的问题。因此，坏消息没有任何预兆，很晚才出现在客户和项目经理面前。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这本书真的是常看常新，回过头来看 Paramer 的初期开发基本是踩遍了五十多年前人们就踩过的坑。&lt;/p&gt;
&lt;p&gt;作为一个比较天真的后端开发，看到已经有跑通了的 Simflow 原型，认为两星期一个月差不多就能完成代码的初步开发。&lt;/p&gt;
&lt;p&gt;这犯了第一宗罪：编程人员常有的，认为“一切都将运作良好”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所以系统编程的进度安排背后的第一个假设是：一切都将运作良好，每一项任务仅花费它所&amp;quot;应该&amp;quot;花费的时间。对这种弥漫在编程人员中的乐观主义，理应受到慎重的分析&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在经过了两周多的 Paramer 开发之后，进度自然明显赶不上了。此前，完全没有做好 Paramer 的需求明确，每天的 Paramer 开发时常要被 Simflow 的 bugfix 和运维任务打断，并且这并不仅仅是一项重构任务，因为我们在重构的基础上，贪婪的为这个版本加上了一些原有功能以外的新功能需求。我们还忽略了测试的时间，直接把开发的时间当做了整个工程时间。&lt;/p&gt;
&lt;p&gt;那么进度延后之后，有哪些选择呢？从项目经理的角度来说，直觉上会出现三个选择：增添人手，删减任务，重新安排进度。&lt;/p&gt;
&lt;p&gt;根据 Brooks 法则，向进度落后的项目中增加人手，只会使进度更加落后。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;在现实情况中，一旦开发团队观察到进度的偏差，总是倾向于对任务进行削减。当项目延期所导致的后续成本非常高时，这常常是唯一可行的方法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;而由于初入团队，仍然身为学生的编程人员自然不敢对于自己预先预估出的已有的验收日期提出修改。而团队的项目经理当时又是一个完全缺失的状态，毫无进度监督可言。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;None love the bearer of bad news.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这犯了第二宗罪：&lt;/p&gt;
&lt;p&gt;本应当是随时可见的项目进度，在老板那里会变成隔十几天才能看到一次进展。最后会演变成一种更加糟糕的情况：不仅删减任务，还重新安排进度。&lt;/p&gt;
&lt;p&gt;插一句，实际上就连验收时间都是一个没被统一的量：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/2/image-2.png"
width="488"
height="890"
srcset="https://v3n0.top/post/paramer/2/image-2_hu_87409931515b6be8.png 480w, https://v3n0.top/post/paramer/2/image-2_hu_4fe8e6773b79c003.png 1024w"
loading="lazy"
alt="到底是 21 还是 24"
class="gallery-image"
data-flex-grow="54"
data-flex-basis="131px"
&gt;&lt;/p&gt;
&lt;p&gt;然而最终是 21 号验收了一次。&lt;/p&gt;
&lt;p&gt;需要注意的是，本篇我更希望关注的并不是进度为什么估算错了，而是：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么没人知道进度已经错了&lt;/strong&gt;？&lt;/p&gt;
&lt;p&gt;这两个问题完全不一样。前者是关于项目进度监督、风险暴露机制以及项目经理在其中应承担的职责，我会在后续专门讨论。&lt;/p&gt;
&lt;p&gt;本篇我更想讨论的问题是，本应当是随时可见的项目进度，在老板那里会变成隔十几天才能看到一次进展。项目延期并不可怕，甚至对我们这种预研性质初期项目，不痛不痒，可怕的是项目已经延期两周了，而负责推进的人还不知道。&lt;/p&gt;
&lt;p&gt;有趣的是，无论是需求变更，还是进度失控。它们最终都指向同一个问题：信息没有被正确地传递。随着团队人数增长，这个问题变得越来越严重。&lt;/p&gt;
&lt;h3 id="场景三信息只存在于人的脑子里"&gt;场景三：信息只存在于人的脑子里
&lt;/h3&gt;&lt;p&gt;再举个接口交接的案例。谷子哥，Cachelize，是我们当时的一个前端。为了做参数优化的图形化显示，他需要优化器后端提供一些新的接口，给一份接口文档。但他催接口催了十天。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/2/image-3.png"
width="500"
height="934"
srcset="https://v3n0.top/post/paramer/2/image-3_hu_527ae54783be0c28.png 480w, https://v3n0.top/post/paramer/2/image-3_hu_5c993a6747a2d667.png 1024w"
loading="lazy"
alt="24 日提出接口需求"
class="gallery-image"
data-flex-grow="53"
data-flex-basis="128px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/2/image-4.png"
width="404"
height="154"
srcset="https://v3n0.top/post/paramer/2/image-4_hu_c14e978ea2a34b04.png 480w, https://v3n0.top/post/paramer/2/image-4_hu_34d94afc06a386c9.png 1024w"
loading="lazy"
alt="次月 4 日才看到接口文档"
class="gallery-image"
data-flex-grow="262"
data-flex-basis="629px"
&gt;&lt;/p&gt;
&lt;p&gt;在 Paramer 的团队中，我之前一直以为我们缺少的是人手。但后来发现，很多时候缺少的不是人，而是信息。&lt;/p&gt;
&lt;p&gt;代码在仓库里不等于别人知道怎么调用，配置在服务器里不等于别人知道怎么部署，知识在脑子里不等于团队拥有知识。重要信息如果只存在于人的脑子里，那么组织就无法交接。&lt;/p&gt;
&lt;p&gt;真正的问题并不是这个接口文档需要按什么时间给，真正的问题是整个团队默认了一种工作方式：信息保存在人身上，而不是保存在组织。于是所有的问题都会变成，等某人有空之后尽快回复我。&lt;/p&gt;
&lt;h2 id="再多的群聊装不下膨胀的消息"&gt;再多的群聊装不下膨胀的消息
&lt;/h2&gt;&lt;p&gt;随着组织规模扩大到十几人，每天的群聊消息达到了几百条甚至上千条，于是提议按工作组分群聊天。&lt;/p&gt;
&lt;p&gt;可以从群头像看到大家美丽的精神状态&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/2/image.png"
width="464"
height="586"
srcset="https://v3n0.top/post/paramer/2/image_hu_e92781d8f28e9f7d.png 480w, https://v3n0.top/post/paramer/2/image_hu_ec8d6506424bd865.png 1024w"
loading="lazy"
alt="我活到头了.jpg"
class="gallery-image"
data-flex-grow="79"
data-flex-basis="190px"
&gt;&lt;/p&gt;
&lt;p&gt;但是分群真的能解决问题吗？&lt;/p&gt;
&lt;p&gt;其实稍微多想一层都不会认为这是个可拓展的模式。现在觉得消息太多，于是分了个这些群。那逐渐扩张，是否还会再从某一个群继续分裂，需求讨论群，测试群，临时问题群，On Call 群。。。&lt;/p&gt;
&lt;p&gt;似乎每一次遇到沟通问题，第一反应都是，再建一个群。&lt;/p&gt;
&lt;p&gt;于是现在甚至连需求都做不到同步了。EDA 群在用 Paramer 的时候，发现了问题，在 EDA 群里提了个可能的需求。Paramer 的开发人员在 Paramer 群里讨论了实现方案，运维在运维群里等着部署环境，此刻算法群里沉浸式讨论数学。&lt;/p&gt;
&lt;p&gt;到最后，需求改没改，接口定没定，环境配没配，谁也不知道。因为信息已经散落在不同群聊里。&lt;/p&gt;
&lt;p&gt;分群什么都没做到，我们只是把一个信息黑洞，拆成了四个信息黑洞。&lt;/p&gt;
&lt;h2 id="异步的团队同步的沟通"&gt;异步的团队，同步的沟通
&lt;/h2&gt;&lt;p&gt;再回头看看上面这三个失败案例，实际上应当这样总结：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;场景一：需求信息丢失&lt;/li&gt;
&lt;li&gt;场景二：进度信息丢失&lt;/li&gt;
&lt;li&gt;场景三：知识信息丢失&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;开篇说到一个多月我没有继续参与 Paramer 的开发工作。最终我看到这样的一个事情：一个用于确定需求的只需要十分钟的三个人参与就行的线上会议，三天没开下来。期间不是 A 不在线就是 B 不在线，等到终于看到消息，或者我终于想起来 @ 两边问问他们开没开过会，已经是第二天。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/2/image-5.png"
width="1030"
height="810"
srcset="https://v3n0.top/post/paramer/2/image-5_hu_ed148493f8d7cde2.png 480w, https://v3n0.top/post/paramer/2/image-5_hu_8fb018b895c10681.png 1024w"
loading="lazy"
alt="经审计实则是三天"
class="gallery-image"
data-flex-grow="127"
data-flex-basis="305px"
&gt;&lt;/p&gt;
&lt;p&gt;这次之后，我把团队里从上到下全拉出来批斗了一番。但其实也只是指出了哪些地方很明显不对劲，还没有找到问题本质。&lt;/p&gt;
&lt;p&gt;先前我也参与过协作节奏控制的非常好的一个西安的团队，看上去各种项目的推进速度一点都不慢，工作强度感觉却比 Paramer 这个项目轻不少。有朋友说，他们的工作模式已经非常大厂了。但效率高，又真的是因为大家坐在同一个办公室里吗？&lt;/p&gt;
&lt;p&gt;如果是这样，只不过是把我们的群聊，变成了人腿从一个工位跑到另一个工位，变成了语音频道交流。确实保证两边都在线了，效率又到底能提高多少呢？要知道，音频是极其低效的信息传递信道。&lt;/p&gt;
&lt;p&gt;问题到底出在哪里，这得从我们的团队形式说起。&lt;/p&gt;
&lt;p&gt;我们团队的主要成员都是学生，同一时间，有人能有空，有人得上课，有人作息不在一个时区。天然不可能朝九晚五。就算再怎么要求 On Call，考试，签到，实验课验收，体育课，总不能不去吧。&lt;/p&gt;
&lt;p&gt;从组织形态上来说，我们早就已经是一个异步团队了。然而我们的沟通方式，却是一个同步的形式。&lt;/p&gt;
&lt;p&gt;接触到的这个西安团队协作模式，在我经历了 Paramer 的磨难之后，给了我非常大的震撼，深深感叹他们工作流的规范程度。但当时仅仅停留在他们文档做的多，飞书用的多，任务面板维护的多，PR 写的细，等等的现象上面，没有思考过这些行为的本质。现在这番对比，才意识到，真正的区别在于信息传递的同步还是异步。&lt;/p&gt;
&lt;p&gt;什么是同步和异步？&lt;/p&gt;
&lt;p&gt;并不能因为这个词从编程到了团队管理就变得不认识。从编程的角度看，其实就是两种调用模型。同步沟通很像阻塞调用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;发起请求 → 等对方返回 → 才能继续下一步
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;而异步沟通更像消息队列 + 回调 + 事件驱动：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;发起请求 → 把信息写入任务队列 → 自己继续做别的事
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上面主要体现的是一个是否阻塞的问题。另一个问题是，同步沟通往往伴随着缺乏各种信息的单一事实来源。&lt;/p&gt;
&lt;p&gt;比如同一个需求，在没有单一事实来源的情况下会变成这样：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 说：“这个接口是按状态排序”&lt;/li&gt;
&lt;li&gt;B 在群里补一句：“其实客户更想按 ID”&lt;/li&gt;
&lt;li&gt;C 过两天口头确认：“先按 Running 在前吧”&lt;/li&gt;
&lt;li&gt;D 写代码的时候看到的是：“按 Completed 优先”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终结果是，没有一个地方记录最终到底是什么，只有一堆彼此冲突的局部记忆。&lt;/p&gt;
&lt;p&gt;而在有单一事实来源的情况下，信息查询的唯一入口：Issue / PRD / 文档&lt;/p&gt;
&lt;p&gt;任何人，甚至不是人而是 Agent，随时都可以看到最新版本是什么，而不是：“你记得我们上次怎么说的吗？”&lt;/p&gt;
&lt;p&gt;同样的问题可以发生在其他的地方，比如进度管理等，不再赘述。&lt;/p&gt;
&lt;p&gt;然而，在同步沟通的环境下，大家明知道沟通非常累，却反而更加不愿意维护这样的单一事实来源，这并不是做不到这件事。&lt;/p&gt;
&lt;p&gt;在群聊 + 临时会议的模式下，@ 一个人，改一句话比改文档快，于是信息会不断回流到看起来更省事的群聊，而不是维护到文档，或是任务面板。同步沟通系统默认奖励快速响应，惩罚结构化沉淀，最终形成恶性的螺旋。&lt;/p&gt;
&lt;h2 id="异步协作"&gt;异步协作
&lt;/h2&gt;&lt;p&gt;当我意识到真正的问题在于缺乏异步沟通协作之后，去网上搜索，才认识到原来已有不少早就规模化应用异步协作的大型团队。&lt;/p&gt;
&lt;p&gt;我特别喜欢 GitLab 这个例子。他们的员工遍布全球 60 多个时区，却能在同一个团队里协作。他们维护了 &lt;a class="link" href="https://handbook.gitlab.com/handbook/" target="_blank" rel="noopener"
&gt;The GitLab Handbook&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;具体的异步协作好处，以及具体落实的方式，我已无心赘述，各种先例远比我在博客里说的要多要全。如果你完全没了解过，希望初步了解关于异步协作的部分，直接看这一章节：&lt;a class="link" href="https://handbook.gitlab.com/handbook/company/culture/all-remote/asynchronous/" target="_blank" rel="noopener"
&gt;How to embrace asynchronous communication for remote work&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;不过，我最喜欢的还是那一句话：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The easiest way to take on an asynchronous mindset is to ask this question: “How would I deliver this message, present this work, or move this project forward right now if no one else on my team (or in my company) were awake?&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Paramer 开发记录 1 - 错误的技术选型</title><link>https://v3n0.top/post/paramer/1/</link><pubDate>Fri, 17 Apr 2026 15:39:25 +0800</pubDate><guid>https://v3n0.top/post/paramer/1/</guid><description>&lt;p&gt;著名的程序员 V 说过：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;错误的团队沟通导致错误的需求理解，错误的需求理解导致错误的技术选型。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Paramer 这个项目，总结一下，就是一个参数化计算任务的批量运行管理平台。用户可以自行使用 Paramer SDK 编写任意形式的计算任务脚本（称为 Template），只需要确认输入输出格式符合规范。支持对接外部的调度器进行分布式的任务调度，支持在后端管理不同的 Template 版本。&lt;/p&gt;
&lt;p&gt;然而这个总结是我接触这个项目到现在一年了才能做出的精炼的总结。实际上当项目拿到手时，我看到的是古神低语。&lt;/p&gt;
&lt;p&gt;在接触 Paramer 之前，我对于后端的了解仅限于用 go gin 写了几个简单到几乎是 hello world 的路由，但是稍微了解了一下项目大概会怎样启动，怎样划分模块。&lt;/p&gt;
&lt;h2 id="黑历史---simflow-时期"&gt;黑历史 - Simflow 时期
&lt;/h2&gt;&lt;p&gt;这一段其实应当放在第 0 篇: &lt;a class="link" href="https://v3n0.top/post/paramer/0-preface" target="_blank" rel="noopener"
&gt;Paramer 开发记录 0 - 开端&lt;/a&gt; 更为合适。但是当时比较匆忙，还没定好每篇大纲就 push 了，现在补一下，作为背景故事的补充。&lt;/p&gt;
&lt;p&gt;最开始这个项目他们打算叫 SimFlow。我完全不知道 Sim 是什么， Flow 是什么。我只是从各种看不懂的术语中模糊地感知他们是搞硬件的，搞电磁领域的研究，只知道他们似乎想要结合物理和 AI，用于加快各种器件的研发。&lt;/p&gt;
&lt;p&gt;先前他们已经尝试做了一个让人非常眼前一黑的原型，我时至今日都没办法一下子搞清楚这项目是怎么跑起来的。&lt;/p&gt;
&lt;p&gt;他们分了一段时间给我先熟悉一下项目。&lt;/p&gt;
&lt;p&gt;代码即视感如图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://v3n0.top/post/paramer/1/image.png"
width="2940"
height="1840"
srcset="https://v3n0.top/post/paramer/1/image_hu_2055fb81fcd4bc1.png 480w, https://v3n0.top/post/paramer/1/image_hu_72108f181a446950.png 1024w"
loading="lazy"
alt="一千三百行处处爆红的单文件 Python Server"
class="gallery-image"
data-flex-grow="159"
data-flex-basis="383px"
&gt;
&lt;img src="https://v3n0.top/post/paramer/1/image-1.png"
width="1592"
height="1382"
srcset="https://v3n0.top/post/paramer/1/image-1_hu_3cde100d38d1bb26.png 480w, https://v3n0.top/post/paramer/1/image-1_hu_eb3b7cb19e0f1f69.png 1024w"
loading="lazy"
alt="地狱 API 编排"
class="gallery-image"
data-flex-grow="115"
data-flex-basis="276px"
&gt;
&lt;img src="https://v3n0.top/post/paramer/1/image-2.png"
width="1972"
height="1352"
srcset="https://v3n0.top/post/paramer/1/image-2_hu_857382dda23a1abb.png 480w, https://v3n0.top/post/paramer/1/image-2_hu_3c0e5ec1106bd7e.png 1024w"
loading="lazy"
alt="一个类负责一切，另一个类负责另一个一切（并调用那个调用一切的类）"
class="gallery-image"
data-flex-grow="145"
data-flex-basis="350px"
&gt;
&lt;img src="https://v3n0.top/post/paramer/1/image-3.png"
width="1738"
height="1694"
srcset="https://v3n0.top/post/paramer/1/image-3_hu_dcccb6b54dfe614b.png 480w, https://v3n0.top/post/paramer/1/image-3_hu_c0d57395fbf92ae3.png 1024w"
loading="lazy"
alt="薨"
class="gallery-image"
data-flex-grow="102"
data-flex-basis="246px"
&gt;
&lt;img src="https://v3n0.top/post/paramer/1/image-4.png"
width="1500"
height="1544"
srcset="https://v3n0.top/post/paramer/1/image-4_hu_ebbf272d2b856627.png 480w, https://v3n0.top/post/paramer/1/image-4_hu_3790d20d1d16b087.png 1024w"
loading="lazy"
alt="真的有人这样导入包的啊"
class="gallery-image"
data-flex-grow="97"
data-flex-basis="233px"
&gt;&lt;/p&gt;
&lt;p&gt;以及启动时要管理几十个长成 SIMFLOW_XXXXX_XXX_XX_XXXXX_XXX 几乎要看起来一模一样这样的环境变量，几乎完全为 0 的文档，一百四十多行的 requirements.txt，后端无框架，直接 aiohttp 手搓，每一个路由函数都是一个巨大的面条代码，没有 ORM，没有迁移脚本，纯靠 &lt;code&gt;self.db_module = importlib.import_module('aiosqlite')&lt;/code&gt;，然后手搓一切 SQL。&lt;/p&gt;
&lt;p&gt;当我对于 simflow 完全感到束手无策时，我时常会注意到 &lt;code&gt;xfmr_6port&lt;/code&gt; 这个字样，只知道似乎它和 simflow 密切相关，甚至直接耦合。我不理解 xfmr 是什么诡异的字母组合，6port 又是什么也看不懂。于是我提问，得到了一个非常简短的回答：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;xfmr 就是 Transformer。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;哦，Transformer，这下知道跟啥有关了。不是说要搞物理 + AI 嘛，也许有希望能串起来了。但 6port 又是个啥。&lt;/p&gt;
&lt;p&gt;于是我去了 xfmr_6port 的项目文件夹，看到了另一不可名状之物，比 simflow 更不可名状一点。&lt;/p&gt;
&lt;p&gt;图就不放了，好奇的可以直接问我。大概描述一下就是，比 simflow 更没组织的少量 Python 脚本，大量的完全没法理解的 shell 脚本，非常大量的我见都没见过的后缀名的 VSCode 都不知道上哪下插件来显示语法，也不知道到底有没有用只能假设全都有用的文本文件。&lt;/p&gt;
&lt;p&gt;但我必须得了解这个项目，想问，又不知道我&lt;strong&gt;对于一个项目，真正需要了解什么&lt;/strong&gt;，真问了，发现回答的也不太听得懂。给人一种看上去他们好像自己也很忙很折磨，也没时间让我真的理解来龙去脉的感觉。一旦问到一些自己感到迷惑的地方，他们又会表示，这个地方你不用管，你只需要关心那一块就行了。&lt;/p&gt;
&lt;p&gt;而且因为完全没明白对方想表达什么导致现在完全记不得问了什么，答复什么&lt;/p&gt;
&lt;p&gt;问来问去，看来看去，看了一圈，也没看到有关 Transformer 的东西。于是，Veno 放弃了思考。&lt;/p&gt;
&lt;p&gt;几天之后，我在某个 xml 文件里看到了个 pin 这个字样，一拍脑袋突然意识到：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这 Transformer 他娘的是变压器&lt;/strong&gt;！一直说什么物理 AI，AI 物理的，敢情是到现在还没接过任何一个 AI 啊。&lt;/p&gt;
&lt;p&gt;绝望的是我后来需要为这个项目多写几个 CURD 路由并且保证它不崩，好在它真跑成功了。&lt;/p&gt;
&lt;p&gt;虽然我认为&lt;strong&gt;真的很没必要了解 Simflow 的代码结构&lt;/strong&gt;，但如果你真的好奇当前的软件是个什么情况, AI 整理出来的代码结构图我会放在本文末尾。需要注意的是，我当时对 Backend Server 以外的区域一无所知，只知道是一个黑盒系统，我丢进去一个输出 X，有可能会得到一个 Y。&lt;/p&gt;
&lt;p&gt;就这样我维护了 simflow 差不多一个月的时间。&lt;/p&gt;
&lt;h2 id="完全重写---paramer-v1"&gt;完全重写 - Paramer V1
&lt;/h2&gt;&lt;p&gt;这样的代码不可能继续高效维护的，由于我们目前属于一个预研项目，没有很紧急的 DDL，大家决定重构一版。更准确地说，这是准备完全重做一个版本。&lt;/p&gt;
&lt;p&gt;因为 Simflow 这个名字被注册过，所以使用了 Paramer 这个名字。&lt;/p&gt;
&lt;p&gt;你可以直接认为，我现在正从零开始写一个项目。&lt;/p&gt;
&lt;p&gt;在重写之前，作为团队中唯一的后端开发的我，仍然没有深刻理解 Paramer 这个产品到底想做成什么样子。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;对产品的理解偏差恰恰是一件非常危险的事&lt;/strong&gt;，并且直接导致后续各种路线错误，包括技术选型，后端架构，代码结构，开发周期预估等等。&lt;/p&gt;
&lt;h2 id="如何理解产品"&gt;如何理解产品
&lt;/h2&gt;&lt;p&gt;著名程序员 V 曾经说过：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;构建产品的前提，是理解产品&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;究竟怎样才算理解产品呢？他提出了三大考虑维度：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;客户群体&lt;/li&gt;
&lt;li&gt;解决方案&lt;/li&gt;
&lt;li&gt;计费形式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;然而，由于错误的团队沟通导致了错误的需求理解。以上的视角是一年之后，也就是写博客时的 Veno 的视角。一年之前的 Veno，&lt;strong&gt;仅仅和团队沟通出了第二点的一半&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;经过几天的沟通和开会，当时的我总结出的旭哥提出的需求，差不多是这样的：我们需要一个分布式集群的，可拓展的，异步的，容器化的，仿真任务管理后端。并且允许通过“模板”来定义多种多样的仿真任务，由 Paramer 管理。&lt;/p&gt;
&lt;p&gt;直到现在才知道，原来那个 xfmr_6port，他们是想把它做成一个示例用的任务模板，Paramer 会需要能管理各种各样的模板，比如 xfmr_4port, 8port 等等。&lt;/p&gt;
&lt;p&gt;可惜的是当时的 Veno 并没有关注到真正应该关注的问题，也没有想着跟产品经理 battle，去砍掉一些不合理的需求。&lt;/p&gt;
&lt;p&gt;于是得到了大概这样的关键词：分布式，容器化，模板化。&lt;/p&gt;
&lt;p&gt;对比一下过去和现在关注到的重点：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Then&lt;/th&gt;
&lt;th&gt;Now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. 分布式&lt;/td&gt;
&lt;td&gt;1. 客户群体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. 容器化&lt;/td&gt;
&lt;td&gt;2. 解决方案&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. 模板化&lt;/td&gt;
&lt;td&gt;3. 计费形式&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;记住这个对比，它是悲剧的开端。&lt;/p&gt;
&lt;h2 id="错误的技术选型"&gt;错误的技术选型
&lt;/h2&gt;&lt;p&gt;我们回到当时的 Veno 的视角，看看他面对目前理解的需求，做出了怎样的技术选型。&lt;/p&gt;
&lt;p&gt;首先，我们需要分布式，容器化，可拓展的高性能计算任务资源调度，显然会想到大概会是需要 Kubernetes。调研了一下，有没有适用于 Kubernetes 的 HPC 任务编排框架呢？搜了下还挺多，Kubeflow, Volcano, Kueue。到底选哪个？&lt;/p&gt;
&lt;p&gt;思考这个问题时，必须注意到：EDA 和 AI 训练存在相当大的大区别，因此 EDA 的调度问题也绝不能直接照搬 AI 训练的经验。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;EDA 是 IO 和 CPU 密集型的任务，AI 训练是 GPU 密集型任务。&lt;/li&gt;
&lt;li&gt;EDA 是多阶段，多周期的任务，存在复杂的状态和织成网一样的流程，而 AI 训练的状态相对简单，是线性的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;此时不得不明确，在这一个层级，我们只希望使用到计算资源的调度分配，而不希望让它负责任务流的编排。因为在用户友好的前提下，它们很难满足条件。在资源调度上，似乎 Volcano 是最符合需求的。&lt;/p&gt;
&lt;p&gt;那么，选择了云原生架构下的计算资源调度器 Volcano。&lt;/p&gt;
&lt;p&gt;其次，我们需要让用户可以写自定义的任务脚本作为“模板”，那么就需要一个 SDK，用 Python 实现 SDK 是合适的。&lt;/p&gt;
&lt;p&gt;其次因为还想着从 Simflow 重构，想着也许大概可能会想参考到一些 Simflow 的任务流逻辑等等的代码，加上之前自己写 Python 多一点，也许用 Python 的话说不定实现起来会快很多，并且我们的重点计算负载也不会在后端服务上，不会有很高的并发需求。于是准备继续用 Python 实现后端。在 Python 方面，框架用 FastAPI。ORM 会选择 SQLAlchemy，以及其他的微服务基建设施。&lt;/p&gt;
&lt;p&gt;目前为止，一切看上去都非常合理，对不对？&lt;/p&gt;
&lt;h2 id="换个视角技术选型截然不同"&gt;换个视角，技术选型截然不同
&lt;/h2&gt;&lt;p&gt;我们回顾一下上面的 Then and Now:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Then&lt;/th&gt;
&lt;th&gt;Now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. 分布式&lt;/td&gt;
&lt;td&gt;1. 客户群体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. 容器化&lt;/td&gt;
&lt;td&gt;2. 解决方案&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. 模板化&lt;/td&gt;
&lt;td&gt;3. 计费形式&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一年之前，由于团队沟通上的失败，产品经验的缺乏，以及大家都是偏向技术思维，共同导致我们完完全全只注意到了产品理解三要点中，第二点的部分内容，&lt;strong&gt;甚至没有排除掉不合理的技术需求&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;现在我们已经知道了我们到底要问清楚哪些事情，一条条来看，就会清楚上面的技术选型错在哪里。&lt;/p&gt;
&lt;h3 id="客户群体"&gt;客户群体
&lt;/h3&gt;&lt;p&gt;现在的 Veno 如果接手该项目，首先会尝试询问并了解这个项目的客户都是什么人。得知：&lt;/p&gt;
&lt;p&gt;我们会把产品卖给硬件公司，而硬件公司的那帮硬件工程师相当缺乏软件工程素养。他们在软件上是技术白痴，认为一旦出现了浏览器和网页就意味着需要联网，不知道 IP 是个什么东西，更不能指望他们写配置文件，系统服务等等。&lt;/p&gt;
&lt;p&gt;并且硬件工程师由于各种软件的缘故，他们必须在非常老旧的 Linux 发行版上完成大部分工作，例如 CentOS 7/8，RHEL 8。&lt;/p&gt;
&lt;p&gt;用户大概率无法连接公网，只能在企业内网中工作，保密级别高。&lt;/p&gt;
&lt;h3 id="解决方案"&gt;解决方案
&lt;/h3&gt;&lt;p&gt;这是相对来讲很难沟通的一点，对产品经理的要求更高。产品经理需要有很强的明确产品需求的能力以及目标拆解的能力，这一点我打算放在后续的团队沟通章节里细讲，这里我直接非常粗略地讲一下。&lt;/p&gt;
&lt;p&gt;可以这样考虑：现在的行业中产生了什么痛点，我们的产品可以怎样解决痛点。对于 Paramer 这个产品，真正的想法如下。&lt;/p&gt;
&lt;p&gt;行业的痛点是这样的：EDA 软件各家独大，却又在整个仿真流程各个步骤中各自不可或缺。仿真的结果数据体积庞大（因为是 EDA 项目文件），许多仿真结果难以持久化，难以查询。整个仿真流程耗费相当算力，却又不得不经常对相同的输入完全重算。&lt;/p&gt;
&lt;p&gt;我们提供的解决方案：通过 Template 这一概念，使得用户可以将复杂的仿真任务流程抽象为一个自定义的参数化的输入 X 输出 Y 的函数。任务脚本只需要定义一次便可使用多种多样的 X 进行计算，而自定义参数和格式的 X 和 Y 使得用户可以便捷地提取并记录庞大仿真结果文件中的关键数据，并对其进行处理。&lt;/p&gt;
&lt;p&gt;用户仿真的目的是检验在某一 X 输入下能否得到理想目标中的 Y。由于参数化的特性，用户甚至可以对 Y 应用数学原理，使用各类优化算法，使用尽可能少的仿真次数，就能找到目标 Y 所对应的 X，这将大大降低人力成本。&lt;/p&gt;
&lt;h3 id="计费方式"&gt;计费方式
&lt;/h3&gt;&lt;p&gt;现在的 Veno 又继续沟通，得知了这一软件会是一个 B 端产品。To B / To C 产品的本质区别不太能直接简单说成面向组织/面向个人，或许应当单独放一个文章讲。总之，大概会有这样的特性：付费者，使用者，决策者相互分离，需要定制，生命周期长，收费是签合同，搞订阅。&lt;/p&gt;
&lt;p&gt;对于 Paramer，软件是订阅制的，并且产品单价相当高，软件本体一份预估卖到至少二十万以上甚至更多，如果附加 Feature 则继续加价。&lt;/p&gt;
&lt;h3 id="初始的技术选型步步错"&gt;初始的技术选型，步步错
&lt;/h3&gt;&lt;p&gt;B 端产品，用户技术白痴，平台限制 Linux，系统老旧，无法联公网。那么我们不可能是一个 SaaS 产品，不可能云原生，更不可能指望客户运维 k8s。好了，volcano 以及一切的微服务相关技术栈被立刻排除。&lt;/p&gt;
&lt;p&gt;系统老旧，部署越便捷越好。要么需要将软件容器化，虚拟机镜像，要么是在兼容老系统的容器中编译的 standalone 应用。&lt;/p&gt;
&lt;p&gt;计费方式，由于软件的单价很高，破解的成本必须大于购买成本，License 的强度成为了重中之重。甚至说 License 的考虑优先级必须被排在首位，远高于运行效率等问题。那么 Python 显然必须要被干掉，&lt;/p&gt;
&lt;p&gt;又因为我们是离线不联网的环境，所有的 License 工作不会存在网安，只会存在反逆向。那么实际上应当调研各个编程语言对应最强的加密手段如何，避免开发之后再亡羊补牢。事实上，由于我们没有在开发初期就考虑 License 问题，直接导致了后续的灾难。&lt;/p&gt;
&lt;p&gt;讲到这里，之前的技术选型已经全部死完了。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结
&lt;/h2&gt;&lt;p&gt;回头看这一段黑历史，最大的教训是，在没有搞清楚产品是什么之前，就开始做技术选型。&lt;/p&gt;
&lt;p&gt;我想在这里再次回顾一下上面的 Then and Now:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Then&lt;/th&gt;
&lt;th&gt;Now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. 分布式&lt;/td&gt;
&lt;td&gt;1. 客户群体&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. 容器化&lt;/td&gt;
&lt;td&gt;2. 解决方案&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. 模板化&lt;/td&gt;
&lt;td&gt;3. 计费形式&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;当时的思考路径是这样的：&lt;/p&gt;
&lt;p&gt;听到“分布式” → Kubernetes
听到“计算调度” → Volcano / Kubeflow
听到“模板” → Python SDK
想快速做出原型 → FastAPI + SQLAlchemy&lt;/p&gt;
&lt;p&gt;这一整套推理链条没有逻辑错误，我甚至觉得是标准答案。重要的是，先前的关注点走在了错误的抽象层级上，直接跳跃到了技术实现阶段，这导致把一些技术方向和真实需求混为一谈。但技术往往是最后才需要优化的东西，尤其是 To B 的场景中。&lt;/p&gt;
&lt;p&gt;从来都不应该默认技术方向是需求的一部分。因为：&lt;/p&gt;
&lt;p&gt;技术并不是为技术本身服务的，是为需求服务的，而需求需要被质疑。&lt;/p&gt;
&lt;p&gt;想要分布式，那后端本身真的需要分布式吗？需要容器化，客户真的能用吗？当这些问题没有被反问时，它们就会以理所当然的形式进入系统设计，然后变成架构的基石。一旦基石错了，后面所有设计都只能是在错误的毛坯上精装修。人话，堆屎山。&lt;/p&gt;
&lt;p&gt;所以才会有这样的说法：一旦一个人太过沉迷技术，那么他就不适合做领导者。&lt;/p&gt;
&lt;p&gt;错误的团队沟通导致错误的需求理解，错误的需求理解导致错误的技术选型。这一条因果链会逐渐放大上一个环节的错误，等你发现问题的时候，已经不是改一改能解决的了，必须推倒重来。&lt;/p&gt;
&lt;h2 id="ai-提供的-simflow-代码结构未经检查仅供参考"&gt;AI 提供的 Simflow 代码结构（未经检查，仅供参考）
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;span class="lnt"&gt;102
&lt;/span&gt;&lt;span class="lnt"&gt;103
&lt;/span&gt;&lt;span class="lnt"&gt;104
&lt;/span&gt;&lt;span class="lnt"&gt;105
&lt;/span&gt;&lt;span class="lnt"&gt;106
&lt;/span&gt;&lt;span class="lnt"&gt;107
&lt;/span&gt;&lt;span class="lnt"&gt;108
&lt;/span&gt;&lt;span class="lnt"&gt;109
&lt;/span&gt;&lt;span class="lnt"&gt;110
&lt;/span&gt;&lt;span class="lnt"&gt;111
&lt;/span&gt;&lt;span class="lnt"&gt;112
&lt;/span&gt;&lt;span class="lnt"&gt;113
&lt;/span&gt;&lt;span class="lnt"&gt;114
&lt;/span&gt;&lt;span class="lnt"&gt;115
&lt;/span&gt;&lt;span class="lnt"&gt;116
&lt;/span&gt;&lt;span class="lnt"&gt;117
&lt;/span&gt;&lt;span class="lnt"&gt;118
&lt;/span&gt;&lt;span class="lnt"&gt;119
&lt;/span&gt;&lt;span class="lnt"&gt;120
&lt;/span&gt;&lt;span class="lnt"&gt;121
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+-----------------------------------------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;USER&lt;/span&gt; &lt;span class="n"&gt;BROWSER&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+--------------------------------+--------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;WebSocket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+------------------------------------------------------------------+------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;FRONTEND&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;React&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimflowFrontend&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;SimflowDeploy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+--------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Monitor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Simdetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+--------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Redux&lt;/span&gt; &lt;span class="n"&gt;Store&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;axiosfun&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+--------------------------------+---------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;WebSocket&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+--------------------------------&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;-------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;BACKEND&lt;/span&gt; &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;simflow_server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IPv6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SIMFLOW_PORT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-------------------------------+-----------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;REST&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;WebSocket&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;initiate_simulation&lt;/span&gt; &lt;span class="o"&gt;+-----------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;update_simulation&lt;/span&gt; &lt;span class="n"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stop_simulation&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PCellManager&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;download_simulation&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;delete_simulation_&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;db_query_all&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;get_default_params&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;reads&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;SIMFLOW_XML_PATH&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;get_simulation_settings&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;reads&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------+----------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------------------------------&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;---------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PCellManager&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;async&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;initiate_simulation_workflow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;update_simulation_workflow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;stop_simulation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;delete_simulation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;DatabaseManager&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SQLite&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;MySQL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;templates&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pcell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;failure_cache&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;simstatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------------------------------&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;----------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;job_operation&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------|-----------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-----------------------------------|--------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+--------------------------------------|----------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;+-----------------+-----------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plugin_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+------------------------------------------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SIMFLOW&lt;/span&gt; &lt;span class="n"&gt;DAEMON&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SIMFLOW_DAEMON_LISTEN_PORT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8079&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-------------------------------+---------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Plugins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Daemon&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Dynamically&lt;/span&gt; &lt;span class="n"&gt;loads&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;SIMFLOW_PLUGINS_PATH&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Calls&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Markdown&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HTML&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;Jinja2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Registers&lt;/span&gt; &lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-------------------------------+---------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-------------------------------&lt;/span&gt;&lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="o"&gt;---------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SLURM&lt;/span&gt; &lt;span class="n"&gt;Plugin&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slurm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------------------+&lt;/span&gt; &lt;span class="o"&gt;+-----------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SlurmInfo&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sbatch&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SlurmManager&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;squeue&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SlurmAPIManager&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;scancel&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;SlurmDocsManager&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-----------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+---------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slurm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slurm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slurm&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+-----------------------------------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+------------------------------------------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sbatch&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;squeue&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;scancel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+--------------------------------------&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;--------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SLURM&lt;/span&gt; &lt;span class="n"&gt;CLUSTER&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Compute&lt;/span&gt; &lt;span class="ne"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Job&lt;/span&gt; &lt;span class="n"&gt;Scheduler&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;runsim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="n"&gt;executed&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slurmctld&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+-----------------------------------------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+---------------------------------------------------------------------+--+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;xfmr_6port&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SIMFLOW_TEMPLATE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;runsim&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MAIN&lt;/span&gt; &lt;span class="n"&gt;SIMULATION&lt;/span&gt; &lt;span class="n"&gt;ORCHESTRATOR&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Load&lt;/span&gt; &lt;span class="n"&gt;Cadence&lt;/span&gt; &lt;span class="n"&gt;IC231&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;EMX&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Export&lt;/span&gt; &lt;span class="n"&gt;OA&lt;/span&gt; &lt;span class="n"&gt;layout&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PCELL&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbAccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Export&lt;/span&gt; &lt;span class="n"&gt;GDS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strmout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt; &lt;span class="n"&gt;EMX&lt;/span&gt; &lt;span class="n"&gt;EM&lt;/span&gt; &lt;span class="n"&gt;simulations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;modes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;emx_script&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="n"&gt;extraction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;emx_script_LR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inductance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;emx_script_CR&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;capacitance&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resistance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Parameter&lt;/span&gt; &lt;span class="n"&gt;extraction&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;xfmr_6port_param_extract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;simulation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;datadisplay&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;scalablemodel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pcelldev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ADS&lt;/span&gt; &lt;span class="n"&gt;viz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PCELL&lt;/span&gt; &lt;span class="n"&gt;layouts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;+----------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;simflow&lt;/span&gt; &lt;span class="n"&gt;reads&lt;/span&gt; &lt;span class="n"&gt;KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VALUE&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;default_params&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cell&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;default_settings&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pins&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;+--------------------------------------------------------------+&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;+------------------------------------------------------------------------+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Paramer 开发记录 0 - 开端</title><link>https://v3n0.top/post/paramer/0-preface/</link><pubDate>Fri, 10 Apr 2026 01:05:40 +0800</pubDate><guid>https://v3n0.top/post/paramer/0-preface/</guid><description>&lt;p&gt;不断开发，迭代，维护了一年的项目，需要整理一下自己的经历。&lt;/p&gt;
&lt;p&gt;这个系列连本篇博客预计共十篇，顺序依据这个项目的开发历程中先后得到的感悟而编排。包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;技术选型&lt;/li&gt;
&lt;li&gt;开发踩坑&lt;/li&gt;
&lt;li&gt;团队沟通&lt;/li&gt;
&lt;li&gt;项目重构&lt;/li&gt;
&lt;li&gt;架构设计&lt;/li&gt;
&lt;li&gt;文档维护&lt;/li&gt;
&lt;li&gt;团队管理&lt;/li&gt;
&lt;li&gt;软件安全&lt;/li&gt;
&lt;li&gt;项目交接&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是，首先这不是一个常规的后端应用，其次这也不是什么技术大厂里的开发规范流程，况且我仍然缺乏开发经验，因此这个系列注定不是软件开发流程的教科书，甚至可以说这是教科书的反面。我不知道这个系列的参考价值如何，仅仅是想记录自己所花费的心力，不想它们被忘记，最终无从回忆。&lt;/p&gt;
&lt;p&gt;这个开发记录系列其实要叫“Paramer 开发血泪史”，我已经提到这大概会是教科书的反面。如果要按文章内容算的话，大概这九篇会这样安排：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;让零开发经验的人做技术选型的后果&lt;/li&gt;
&lt;li&gt;所有以为“不会出问题”的地方，最后都会出问题&lt;/li&gt;
&lt;li&gt;“我以为你知道”&lt;/li&gt;
&lt;li&gt;为什么不一开始考虑好怎么写呢&lt;/li&gt;
&lt;li&gt;过度设计&lt;/li&gt;
&lt;li&gt;如果你给人类写的文档最后只有 AI 会读&lt;/li&gt;
&lt;li&gt;软件工程，修饰词是软件，主语是工程&lt;/li&gt;
&lt;li&gt;软件安全不可能三角：离线，高破解成本，运行效率&lt;/li&gt;
&lt;li&gt;你想交接，但只有你一个人了解这个项目&lt;/li&gt;
&lt;/ol&gt;</description></item></channel></rss>